diff --git a/archreview/plans/00-MASTER-TRACKER.md b/archreview/plans/00-MASTER-TRACKER.md index 5ffac184..bcc9e53c 100644 --- a/archreview/plans/00-MASTER-TRACKER.md +++ b/archreview/plans/00-MASTER-TRACKER.md @@ -16,7 +16,7 @@ Every plan follows the TDD bite-sized-task format and ships a co-located `.tasks | [PLAN-04](PLAN-04-data-audit-backbone.md) | Data & Audit Backbone | 26 | 26 | βœ… Complete (all 26 tasks; merged to `main` `dbd3ed2f` via fast-forward; branch removed) | 27 items: 22 fixed, 4 deferred, 1 won't-fix (incl. NodeB reconcile from report 08) | | [PLAN-05](PLAN-05-templates-deployment-transport.md) | Templates, Deployment & Transport | 25 | 25 | βœ… Complete (all 25 tasks; merged to `main` `ec23db35` via fast-forward; worktree removed, branch deleted) | 33 line-items: 27 fixed, 6 deferred with rationale | | [PLAN-06](PLAN-06-edge-integrations.md) | Edge Integrations | 24 | 24 | βœ… Complete (all 24 tasks; merged to `main` `3e964ac2` via fast-forward; worktree removed, branch deleted) | 24 findings: 21 fixed, 3 deferred/won't-fix | -| [PLAN-07](PLAN-07-ui-management-security.md) | UI, Management & Security | 33 | 3 | 🟨 In progress (P0: T1, T2, T3) | 24 items: 20 fixed, 3 partial (deferrals documented), 1 won't-fix | +| [PLAN-07](PLAN-07-ui-management-security.md) | UI, Management & Security | 33 | 32 | βœ… Complete (all 32 active tasks; T33 `skipped-duplicate` β€” CLI.Tests already in slnx via PLAN-08 T1; merged to `main` via fast-forward; worktree removed, branch deleted) | 24 items: 20 fixed, 3 partial (deferrals documented), 1 won't-fix | | [PLAN-08](PLAN-08-conventions-tests.md) | Conventions & Tests | 11 | 1 | 🟨 In progress (P0: T1) | 13 covered, 4 owned by other plans, ~20 triaged into deferred-work register | Status values: ⬜ Not started Β· 🟨 In progress Β· βœ… Complete Β· ⏸ Blocked @@ -35,9 +35,11 @@ Status values: ⬜ Not started Β· 🟨 In progress Β· βœ… Complete Β· ⏸ Blocke **Wave 4 β€” PLAN-06 COMPLETE (2026-07-10):** all 24 tasks delivered and **merged to `main` `3e964ac2` via fast-forward** (main was still at PLAN-05's `9b0cf44c`, zero divergence; worktree removed, branch deleted). Edge Integrations hardening across six report-and-wait waves of file-disjoint parallel subagents: the **InboundAPI** spine β€” revision-checked compiled-handler cache (heals failover / direct-SQL / known-bad staleness, DB row now authoritative β€” T1/T2), `InvalidateMethod` seam consuming PLAN-05's `IScriptArtifactChangeBus` contract (T3), deferred DI-scope disposal + orphan-execution telemetry (T4), machine-readable error `code`s incl. `SITE_UNREACHABLE` + 415-on-non-JSON (T5), `IOptionsMonitor` hot-reload (T6), parallel startup compile (T7); the **ESG** per-system `TimeoutSeconds` full vertical slice (entityβ†’EF migrationβ†’artifactβ†’site SQLiteβ†’client honorβ†’mgmtβ†’CLIβ†’UIβ†’doc β€” T8–T12) plus `{param}` path-template substitution (T13), bounded outbound response buffering (T14), structured JSON `AuthConfiguration` with legacy-colon fallback (T15), cancellation-aware `IsTransient` (T16); the **Notification** batch β€” SMS first-transient short-circuit (T17), wired the dead `SmsConfiguration.MaxRetries/RetryDelay` per-type retry policy (T18), configurable OAuth2 authority/scope (entityβ†’EF migrationβ†’token serviceβ†’mgmt/CLI/UI surfaces β€” T19/T20), deterministic lowest-Id SMTP selection + atomic OAuth2 token cache (T21), Twilio `AccountSid` format validation (T22); and the docs (DelmiaNotifier at-least-once semantics β€” T23; dual-key API-key rotation procedure β€” T24). Two EF migrations added (`AddExternalSystemTimeoutSeconds` T8, `AddSmtpOAuth2AuthorityScope` T19, serialized on the shared snapshot). **Terminal verification:** full slnx build 0 warn/0 err; every unit + integration suite green (InboundAPI 253, ESG 132, NotificationOutbox 132, NotificationService 57, ManagementService 245, CLI 346, CentralUI 893, SiteRuntime 494, Commons 597, ConfigDB 338, Host 260, + all others). Only residue: the same environmental 8 `CentralUI.PlaywrightTests` Deployment E2E failures (`SQLite Error 14` on `instance deploy` β€” needs a live docker cluster; PLAN-06 touched zero files in that project's deployment-DB path). Execution note: `isolation:"worktree"` subagents proved non-isolating here (shared index β†’ commit races); the working model was pre-created dedicated `git worktree`s per task + cherry-pick onto an integration branch + per-wave combined build/impacted-suite barrier. Initiative total: **152 of 192** (sum of the Done column). +**Wave 5 β€” PLAN-07 COMPLETE (2026-07-10):** all 32 active tasks (T4–T32; T1–T3 landed in P0; **T33 `skipped-duplicate`** β€” CLI.Tests already in the slnx via PLAN-08 T1) delivered on worktree branch `plan07` and **merged to `main` via fast-forward** (main was still at PLAN-06's `4fb754f9`, zero divergence; all worktrees removed, branch deleted). UI/Management/Security hardening across six report-and-wait waves of file-disjoint parallel subagents against the dominant **ManagementActor single-writer lane** (15 tasks serialized in one integration worktree; the file-disjoint remainder ran in dedicated per-task worktrees, cherry-picked in with a per-wave combined build + impacted-suite barrier): **C1** auth-disabled artifact killed + `DisableLoginGuard` fail-fast (T1–T3, P0); **C2** `DeployToSiteAsync` single-site deploy + fleet-wide site-scope guard (T4/T5); **C3** connection/external-system/DB-connection secret elision via `ConfigSecretScrubber` + sentinel-preserving update (T6–T9); **UA1/C6/C5** any-of role gates + `ListSecuredWrites` gating + area-gate reconciliation (Designer|Deployer) + role-casing canonicalization (T10–T12); **UA2** the frozen `GetRequiredRoles` authorization matrix over all **138** registered commands + dispatch-coverage guard (T13/T24); **S2/P3** real server-side secured-write TTL + expiry-at-approve/reject + opportunistic list sweep + list paging + UI history pager & submission-age dialog (T14–T18); **S1** 5-min transport/deploy Ask timeout + shipped config (T19/T20); **C4** additive `SiteIdentifier` on browse/verify/cert commands + actor dispatch (Designer browse/verify, Admin cert-trust) + dispatch-coverage + CLI parity (T21–T25); **P1/UA5** `LoginThrottle` per-username+IP LDAP-bind lockout wired into every bind surface (T26/T27); **P2** additive Skip/Take paging on template/instance lists (T28); **S3** `PollGate` reentrancy guard on Health/AlarmSummary timers (T29); **S4** transport single-flight + export base64-copy elimination (T30); **S5/C7/C8/P4/UA6** debug-stream fault logging + event-log-filter doc fix + AlarmSummary memoization/a11y + the stale CLAUDE.md `SourceNode` note corrected (C7/C8 both verified true β€” T31/T32). Two message-contract additions (`AuditKind.SecuredWriteExpire`, secured-write list paging params) landed additively; no EF migrations needed. **Terminal verification:** full slnx build 0 warn/0 err; 28 of 30 test assemblies green (ManagementService 448 incl. the frozen matrix + dispatch-coverage, CentralUI 898, CLI 359, Security 175, Commons 609, Communication 263, Transport 138, ConfigDB 341, SiteRuntime 494, Host 260, + all others), after fixing one stale enum-count lock-in test (`AuditEnumTests` 15β†’16 for T15's additive `SecuredWriteExpire` β€” the per-task filtered runs never hit that Commons guard, so the full sweep caught it, exactly as in PLAN-04). Only residue: the same environmental 8 `CentralUI.PlaywrightTests` Deployment E2E failures (`SQLite Error 14` on `instance deploy` β€” needs a live docker cluster; PLAN-07 touched zero files in that project's deployment-DB path). Initiative total: **181 of 192** (sum of the Done column; PLAN-07's max is 32/33 with T33 a documented skip). + ## Parallelization Map β€” Incomplete Tasks (2026-07-09) -Covers the plans with open tasks: PLAN-07 (30), PLAN-08 (10). PLAN-01/02/03/04/05/06 are complete β€” nothing to parallelize there (PLAN-05 finished 2026-07-10; PLAN-06 finished 2026-07-10; the section below is retained for its cross-plan mutex analysis, which still governs PLAN-07–08). **"Ready"** = every `blockedBy` entry is already `completed` in the plan's `.tasks.json`, so the task can start now. Ready sets are recomputed below from the live manifests; re-derive after each merge. +Covers the plans with open tasks: PLAN-08 (10). PLAN-01/02/03/04/05/06/07 are complete β€” nothing to parallelize there (PLAN-05 finished 2026-07-10; PLAN-06 finished 2026-07-10; PLAN-07 finished 2026-07-10; the section below is retained for its cross-plan mutex analysis, which still governs PLAN-08 and documents how PLAN-07's ManagementActor lane was run). **"Ready"** = every `blockedBy` entry is already `completed` in the plan's `.tasks.json`, so the task can start now. Ready sets are recomputed below from the live manifests; re-derive after each merge. ### Cross-plan serialization mutexes (a task holding one must be the ONLY task touching that surface, anywhere) @@ -59,7 +61,7 @@ Covers the plans with open tasks: PLAN-07 (30), PLAN-08 (10). PLAN-01/02/03/04/0 - **PLAN-04** β€” βœ… COMPLETE (2026-07-09); all 26 tasks done, merged to `main` `dbd3ed2f`. No longer a parallelization lane. - **PLAN-05** β€” βœ… COMPLETE (2026-07-10); all 25 tasks done, merged to `main` `ec23db35` (fast-forward). No longer a parallelization lane. (Historical: the BundleImporter serial chain T1β†’2→…→6β†’19β†’20β†’23 ran in-worktree; T14's `IScriptArtifactChangeBus` contract is shipped for PLAN-06 to consume.) - **PLAN-06** β€” βœ… COMPLETE (2026-07-10); all 24 tasks done, merged to `main` `3e964ac2` (fast-forward). No longer a parallelization lane. (Historical: ran as 6 waves β€” W1{1,6,7,8,17,23} W2{2,9,10,12,18,19} W3{3,13,21} W4{4,11,14} W5{5,15,20} W6{16,22,24}; the ExternalSystemClient chain T9β†’13β†’14β†’15β†’16 and inbound-executor chain T1β†’3β†’4β†’5 were the two serial spines.) -- **PLAN-07** β€” ready non-ManagementActor (mutually concurrent, file-disjoint): **{4, 6, 14, 19, 21, 26, 29 | 32}** (ArtifactDeploymentService / ConfigSecretScrubber / SecuredWriteRepository / ManagementEndpoints+options / Commons Browse-Cert message records / Security LoginThrottle / CentralUI PollGate β€” T29 and T32 share `AlarmSummary.razor`, so serialize those two). Ready **ManagementActor** tasks (β†’ the ONE global Lane M): **{8, 9, 10, 12, 28, 30, 31}** β€” **start with T10** (it unblocks T11, T13, T22, T23). **T33 = skip (dedupe).** +- **PLAN-07** β€” βœ… COMPLETE (2026-07-10); all 32 active tasks done, merged to `main` (fast-forward); T33 `skipped-duplicate`. No longer a parallelization lane. (Historical: ran as 6 waves β€” W1{4,6,10,14,19,21,26,29} W2{7,8,9,27,32} W3{11,20,22,23} W4{13,15,16,17,24} W5{5,12,18,25,28} W6{30,31}; Lane M = the ManagementActor single-writer chain T10β†’7β†’8β†’9β†’11β†’22β†’23β†’15β†’16β†’17β†’5β†’12β†’28β†’30β†’31 driven serially in the integration worktree, with the file-disjoint remainder in dedicated per-task worktrees cherry-picked in per wave.) - **PLAN-08** β€” ready: **{2, 3, 4, 5, 7, 8, 9, 11}** β€” each is a new per-component validator file or an isolated test/doc, so **mutually parallel**, with one caveat: **T4 shares `Host/Program.cs` with P06 T7** (sequence them). This is the initiative's single highest-parallelism slice (independent validator files). T6, T10 stay blocked. ### Recommended concurrent execution diff --git a/archreview/plans/PLAN-07-ui-management-security.md.tasks.json b/archreview/plans/PLAN-07-ui-management-security.md.tasks.json index bf9f637a..96d35eee 100644 --- a/archreview/plans/PLAN-07-ui-management-security.md.tasks.json +++ b/archreview/plans/PLAN-07-ui-management-security.md.tasks.json @@ -1,39 +1,241 @@ { "planPath": "archreview/plans/PLAN-07-ui-management-security.md", "tasks": [ - { "id": 1, "subject": "Task 1: DisableLoginGuard β€” refuse the flag outside Development", "status": "completed", "blockedBy": [] }, - { "id": 2, "subject": "Task 2: Wire the guard at the Host composition root + doc", "status": "completed", "blockedBy": [1] }, - { "id": 3, "subject": "Task 3: Scrub deploy/wonder-app-vd03 β€” remove DisableLogin: true (on-disk only; deploy/ is gitignored)", "status": "completed", "blockedBy": [] }, - { "id": 4, "subject": "Task 4: ArtifactDeploymentService.DeployToSiteAsync", "status": "pending", "blockedBy": [] }, - { "id": 5, "subject": "Task 5: HandleDeployArtifacts honors SiteId + site-scope enforcement + docs", "status": "pending", "blockedBy": [4] }, - { "id": 6, "subject": "Task 6: ConfigSecretScrubber β€” JSON secret elision + sentinel merge", "status": "pending", "blockedBy": [] }, - { "id": 7, "subject": "Task 7: DataConnection List/Get/audit secret elision + sentinel-preserving update", "status": "pending", "blockedBy": [6] }, - { "id": 8, "subject": "Task 8: ExternalSystem AuthConfiguration elision + preserve-if-null update", "status": "pending", "blockedBy": [] }, - { "id": 9, "subject": "Task 9: DatabaseConnection ConnectionString elision + preserve-if-null update", "status": "pending", "blockedBy": [] }, - { "id": 10, "subject": "Task 10: GetRequiredRoles any-of refactor + gate ListSecuredWrites", "status": "pending", "blockedBy": [] }, - { "id": 11, "subject": "Task 11: Reconcile the area-management role gate (code + three docs)", "status": "pending", "blockedBy": [10] }, - { "id": 12, "subject": "Task 12: Canonicalize role-mapping casing at the write path", "status": "pending", "blockedBy": [] }, - { "id": 13, "subject": "Task 13: GetRequiredRoles matrix test β€” freeze the authorization table", "status": "pending", "blockedBy": [10, 11, 22, 23] }, - { "id": 14, "subject": "Task 14: SecuredWrite repository β€” TryMarkExpiredAsync + CountAsync", "status": "pending", "blockedBy": [] }, - { "id": 15, "subject": "Task 15: Server-side secured-write TTL β€” enforce at approve/reject", "status": "pending", "blockedBy": [14] }, - { "id": 16, "subject": "Task 16: Opportunistic expiry sweep in HandleListSecuredWrites", "status": "pending", "blockedBy": [15] }, - { "id": 17, "subject": "Task 17: Secured-write list paging β€” command, handler, CLI", "status": "pending", "blockedBy": [14] }, - { "id": 18, "subject": "Task 18: SecuredWrites page β€” history pager + age in approve dialog + docs", "status": "pending", "blockedBy": [17] }, - { "id": 19, "subject": "Task 19: Per-command long-running Ask timeout", "status": "pending", "blockedBy": [] }, - { "id": 20, "subject": "Task 20: Ship ManagementService timeout config + doc", "status": "pending", "blockedBy": [19] }, - { "id": 21, "subject": "Task 21: Browse/Verify/Cert commands gain optional SiteIdentifier", "status": "pending", "blockedBy": [] }, - { "id": 22, "subject": "Task 22: Actor handlers β€” BrowseNode / SearchAddressSpace / VerifyEndpoint", "status": "pending", "blockedBy": [10, 21] }, - { "id": 23, "subject": "Task 23: Actor handlers β€” TrustServerCert / RemoveServerCert / ListServerCerts (Admin)", "status": "pending", "blockedBy": [10, 21] }, - { "id": 24, "subject": "Task 24: Dispatch-coverage test β€” every registered command reaches a handler", "status": "pending", "blockedBy": [22, 23] }, - { "id": 25, "subject": "Task 25: CLI parity β€” browse / search / verify-endpoint / certs commands", "status": "pending", "blockedBy": [22, 23] }, - { "id": 26, "subject": "Task 26: LoginThrottle β€” fixed-window LDAP-bind failure lockout", "status": "pending", "blockedBy": [] }, - { "id": 27, "subject": "Task 27: Wire the throttle β€” ManagementAuthenticator + auth endpoints + doc", "status": "pending", "blockedBy": [26] }, - { "id": 28, "subject": "Task 28: Additive paging for ListTemplates / ListInstances", "status": "pending", "blockedBy": [] }, - { "id": 29, "subject": "Task 29: PollGate β€” non-reentrant poll timers on Health + Alarm Summary", "status": "pending", "blockedBy": [] }, - { "id": 30, "subject": "Task 30: Transport single-flight + base64 copy elimination", "status": "pending", "blockedBy": [] }, - { "id": 31, "subject": "Task 31: Low cleanup A β€” hub send fault logging, event-log filter comment, stale CLAUDE.md note", "status": "pending", "blockedBy": [] }, - { "id": 32, "subject": "Task 32: Low cleanup B β€” AlarmSummary memoization + sortable-header a11y", "status": "pending", "blockedBy": [] }, - { "id": 33, "subject": "Task 33: Add CLI.Tests to the slnx + retire the gotcha", "status": "pending", "blockedBy": [] } + { + "id": 1, + "subject": "Task 1: DisableLoginGuard \u2014 refuse the flag outside Development", + "status": "completed", + "blockedBy": [] + }, + { + "id": 2, + "subject": "Task 2: Wire the guard at the Host composition root + doc", + "status": "completed", + "blockedBy": [ + 1 + ] + }, + { + "id": 3, + "subject": "Task 3: Scrub deploy/wonder-app-vd03 \u2014 remove DisableLogin: true (on-disk only; deploy/ is gitignored)", + "status": "completed", + "blockedBy": [] + }, + { + "id": 4, + "subject": "Task 4: ArtifactDeploymentService.DeployToSiteAsync", + "status": "completed", + "blockedBy": [] + }, + { + "id": 5, + "subject": "Task 5: HandleDeployArtifacts honors SiteId + site-scope enforcement + docs", + "status": "completed", + "blockedBy": [ + 4 + ] + }, + { + "id": 6, + "subject": "Task 6: ConfigSecretScrubber \u2014 JSON secret elision + sentinel merge", + "status": "completed", + "blockedBy": [] + }, + { + "id": 7, + "subject": "Task 7: DataConnection List/Get/audit secret elision + sentinel-preserving update", + "status": "completed", + "blockedBy": [ + 6 + ] + }, + { + "id": 8, + "subject": "Task 8: ExternalSystem AuthConfiguration elision + preserve-if-null update", + "status": "completed", + "blockedBy": [] + }, + { + "id": 9, + "subject": "Task 9: DatabaseConnection ConnectionString elision + preserve-if-null update", + "status": "completed", + "blockedBy": [] + }, + { + "id": 10, + "subject": "Task 10: GetRequiredRoles any-of refactor + gate ListSecuredWrites", + "status": "completed", + "blockedBy": [] + }, + { + "id": 11, + "subject": "Task 11: Reconcile the area-management role gate (code + three docs)", + "status": "completed", + "blockedBy": [ + 10 + ] + }, + { + "id": 12, + "subject": "Task 12: Canonicalize role-mapping casing at the write path", + "status": "completed", + "blockedBy": [] + }, + { + "id": 13, + "subject": "Task 13: GetRequiredRoles matrix test \u2014 freeze the authorization table", + "status": "completed", + "blockedBy": [ + 10, + 11, + 22, + 23 + ] + }, + { + "id": 14, + "subject": "Task 14: SecuredWrite repository \u2014 TryMarkExpiredAsync + CountAsync", + "status": "completed", + "blockedBy": [] + }, + { + "id": 15, + "subject": "Task 15: Server-side secured-write TTL \u2014 enforce at approve/reject", + "status": "completed", + "blockedBy": [ + 14 + ] + }, + { + "id": 16, + "subject": "Task 16: Opportunistic expiry sweep in HandleListSecuredWrites", + "status": "completed", + "blockedBy": [ + 15 + ] + }, + { + "id": 17, + "subject": "Task 17: Secured-write list paging \u2014 command, handler, CLI", + "status": "completed", + "blockedBy": [ + 14 + ] + }, + { + "id": 18, + "subject": "Task 18: SecuredWrites page \u2014 history pager + age in approve dialog + docs", + "status": "completed", + "blockedBy": [ + 17 + ] + }, + { + "id": 19, + "subject": "Task 19: Per-command long-running Ask timeout", + "status": "completed", + "blockedBy": [] + }, + { + "id": 20, + "subject": "Task 20: Ship ManagementService timeout config + doc", + "status": "completed", + "blockedBy": [ + 19 + ] + }, + { + "id": 21, + "subject": "Task 21: Browse/Verify/Cert commands gain optional SiteIdentifier", + "status": "completed", + "blockedBy": [] + }, + { + "id": 22, + "subject": "Task 22: Actor handlers \u2014 BrowseNode / SearchAddressSpace / VerifyEndpoint", + "status": "completed", + "blockedBy": [ + 10, + 21 + ] + }, + { + "id": 23, + "subject": "Task 23: Actor handlers \u2014 TrustServerCert / RemoveServerCert / ListServerCerts (Admin)", + "status": "completed", + "blockedBy": [ + 10, + 21 + ] + }, + { + "id": 24, + "subject": "Task 24: Dispatch-coverage test \u2014 every registered command reaches a handler", + "status": "completed", + "blockedBy": [ + 22, + 23 + ] + }, + { + "id": 25, + "subject": "Task 25: CLI parity \u2014 browse / search / verify-endpoint / certs commands", + "status": "completed", + "blockedBy": [ + 22, + 23 + ] + }, + { + "id": 26, + "subject": "Task 26: LoginThrottle \u2014 fixed-window LDAP-bind failure lockout", + "status": "completed", + "blockedBy": [] + }, + { + "id": 27, + "subject": "Task 27: Wire the throttle \u2014 ManagementAuthenticator + auth endpoints + doc", + "status": "completed", + "blockedBy": [ + 26 + ] + }, + { + "id": 28, + "subject": "Task 28: Additive paging for ListTemplates / ListInstances", + "status": "completed", + "blockedBy": [] + }, + { + "id": 29, + "subject": "Task 29: PollGate \u2014 non-reentrant poll timers on Health + Alarm Summary", + "status": "completed", + "blockedBy": [] + }, + { + "id": 30, + "subject": "Task 30: Transport single-flight + base64 copy elimination", + "status": "completed", + "blockedBy": [] + }, + { + "id": 31, + "subject": "Task 31: Low cleanup A \u2014 hub send fault logging, event-log filter comment, stale CLAUDE.md note", + "status": "completed", + "blockedBy": [] + }, + { + "id": 32, + "subject": "Task 32: Low cleanup B \u2014 AlarmSummary memoization + sortable-header a11y", + "status": "completed", + "blockedBy": [] + }, + { + "id": 33, + "subject": "Task 33: Add CLI.Tests to the slnx + retire the gotcha", + "status": "skipped-duplicate", + "blockedBy": [] + } ], - "lastUpdated": "2026-07-08" + "lastUpdated": "2026-07-10" }