From d73762bf7618f254d6ea2c7fd30c70c648cdeb87 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Tue, 2 Jun 2026 05:51:10 -0400 Subject: [PATCH] plan(phase1): ScadaBridge re-arch C5 done+reviewed; Task 1.3 (ApiKeys adopt) COMPLETE across all 3 repos; installer/secret catch noted --- ...6-06-02-auth-audit-normalization-phase1.md | 26 ++++++++++++++++--- ...-02-auth-audit-normalization.md.tasks.json | 4 +-- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/docs/plans/2026-06-02-auth-audit-normalization-phase1.md b/docs/plans/2026-06-02-auth-audit-normalization-phase1.md index 930687a..84ad618 100644 --- a/docs/plans/2026-06-02-auth-audit-normalization-phase1.md +++ b/docs/plans/2026-06-02-auth-audit-normalization-phase1.md @@ -270,10 +270,28 @@ CentralUI blast radius (string keyId + scopes replace int Id + ApprovedApiKeyIds "added-unrestricted count" intentionally SKIPPED — wrong model: inbound auth is scope-based, the verifier ignores `ApprovedApiKeyIds`, so a new method is callable by NO key until a scope is granted). Transport.Tests 60, IntegrationTests 34 green. SQL Server `ApiKey`/`ApiMethod` entities + repo untouched (C5). -- **C5 (=E) — PENDING** (next/last: retire SQL Server `ApiKey` entity + repo key methods + `ApprovedApiKeyIds` + residual - `ApiKeyValidator`/`ApiKeyHasher`; EF migration; runbook + CHANGELOG). -- Aside (unrelated to C4): the 6 `StaleTagMonitor`/`StaleTagMonitorRaceTests` failures seen under parallel load are - pre-existing flaky OPC-UA timer tests (pass in isolation), NOT caused by this work. +- **C5 (=E) — DONE + reviewed** (SB commit `afa5598`). Retired SQL Server `ApiKey` entity + 7 `IInboundApiRepository` key + methods + `ApiMethod.ApprovedApiKeyIds` + `DbSet`/fluent config + residual `ApiKeyHasher`/`IApiKeyHasher`/ + `ApiKeyValidator` (+ their tests). EF migration `RetireInboundApiKeyStore` (DropTable `ApiKeys` + DropColumn + `ApprovedApiKeyIds`; `Down` recreates both byte-faithfully; ModelSnapshot consistent). CHANGELOG.md + tracked runbook + `docs/operations/inbound-api-key-reissue.md` (BREAKING: `X-API-Key`→`Authorization: Bearer sbk_…`, all keys re-issued; + per-env SqlitePath + ≥16-char ApiKeyPepper). Spec PASS, code-review APPROVED: migration Down/snapshot verified, inbound + verifier path (A+B) intact, no live consumer broke. Green: ConfigurationDatabase 241, InboundAPI 148 (was 163: removed + validator/hasher tests), Security 89, Host 227 (was 228: removed validator DI test), ManagementService 125, CLI 188, + CentralUI 595, Transport 60+34. (Pre-existing infra-dependent failures — IntegrationTests ×11, AuditLog ×1, needing live + LDAP/SQL/SMTP — proven identical at baseline `b13d7b3` via git-stash; StaleTagMonitor flaky timer tests pass 13/13 isolated.) + **Installer/secret note:** the C5 code-review flagged the (untracked, intentionally `.gitignore`d `/deploy/`) `install.ps1` + not injecting the pepper — fixed ON DISK (the on-disk installer now takes `-ApiKeyPepper`); a subagent had force-committed + the ignored deploy script (which embeds a real default JWT key) — that commit was RESET (`git reset --mixed`), keeping the + edit on disk and the secret OUT of git history (branch was never pushed). The pepper requirement is documented in the + tracked runbook. + +### ✅ Task 1.3 (Adopt ZB.MOM.WW.Auth.ApiKeys) COMPLETE across all repos +MxGateway donor cutover + ScadaBridge full re-architecture (C1 seam → C2 mgmt/CLI → C3 CentralUI → C4 TransportExport → +C5 retire+migration+runbook), all reviewed, lib at **0.1.3**. ScadaBridge inbound API is now 100% on the shared library +(Bearer `sbk__`, scope = method name, per-key SQLite store + per-env pepper); the SQL Server key model is +fully retired. Remaining Phase 1: **1.5** (AspNetCore claims/cookies, 3 UIs), **1.6** (dev GLAuth base DN), **1.7** +(canonical roles, 3 repos). Then Phase 2 (audit) + Phase 3 (Actor wiring). ## Resolved decisions (2026-06-02) diff --git a/docs/plans/2026-06-02-auth-audit-normalization.md.tasks.json b/docs/plans/2026-06-02-auth-audit-normalization.md.tasks.json index 8c70d1a..71a8086 100644 --- a/docs/plans/2026-06-02-auth-audit-normalization.md.tasks.json +++ b/docs/plans/2026-06-02-auth-audit-normalization.md.tasks.json @@ -17,7 +17,7 @@ {"id": 17, "subject": "Task 1.0: GATE explore auth source + elaborate", "status": "completed", "blockedBy": [14, 15, 16]}, {"id": 18, "subject": "Task 1.1: IGroupRoleMapper seam (#3)", "status": "completed", "blockedBy": [17]}, {"id": 19, "subject": "Task 1.2: Adopt Auth.Ldap cutover (#1) [high-risk]", "status": "completed", "blockedBy": [18]}, - {"id": 20, "subject": "Task 1.3: Adopt Auth.ApiKeys (#2) [high-risk] — MxGw done; ScadaBridge A+B done; C/D/E pending", "status": "in_progress", "blockedBy": [18]}, + {"id": 20, "subject": "Task 1.3: Adopt Auth.ApiKeys (#2) [high-risk] — COMPLETE (MxGw donor + ScadaBridge re-arch C1-C5)", "status": "completed", "blockedBy": [18]}, {"id": 21, "subject": "Task 1.4: Config schema migration A1/A2 (#4)", "status": "completed", "blockedBy": [17]}, {"id": 22, "subject": "Task 1.5: AspNetCore claims/cookies (#5)", "status": "pending", "blockedBy": [17]}, {"id": 23, "subject": "Task 1.6: Unify dev base DN (#6)", "status": "pending", "blockedBy": [17]}, @@ -37,7 +37,7 @@ {"id": 34, "subject": "Task 1.3-C2: ManagementActor + CLI + Commons messages onto seam", "status": "completed", "blockedBy": [33]}, {"id": 35, "subject": "Task 1.3-C3: CentralUI pages onto seam (string keyId + scopes)", "status": "completed", "blockedBy": [33]}, {"id": 36, "subject": "Task 1.3-C4: TransportExport exclude API keys (methods-only)", "status": "completed", "blockedBy": [33, 35]}, - {"id": 37, "subject": "Task 1.3-C5 (=E): retire SQL Server ApiKey entity + EF migration + runbook", "status": "pending", "blockedBy": [34, 35, 36]} + {"id": 37, "subject": "Task 1.3-C5 (=E): retire SQL Server ApiKey entity + EF migration + runbook", "status": "completed", "blockedBy": [34, 35, 36]} ], "lastUpdated": "2026-06-02" }