From 4de61d29f5e51e6eeae8bb7a90c3133bd3f46502 Mon Sep 17 00:00:00 2001 From: Joseph Doherty Date: Tue, 2 Jun 2026 15:42:23 -0400 Subject: [PATCH] =?UTF-8?q?docs:=20PROGRAM=20COMPLETE=20=E2=80=94=20Auth+A?= =?UTF-8?q?udit=20normalization=20adopted=20across=20all=203=20repos=20(Ph?= =?UTF-8?q?ases=200-3);=20mark=20exit-gate=20(CLAUDE.md=20Auth/Audit=20row?= =?UTF-8?q?s=20+=20components/{auth,audit}/GAPS.md=20adopted,=20local-only?= =?UTF-8?q?/not-pushed);=20tasks=20#10/#30/#31=20done?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CLAUDE.md | 27 ++++++++++++++----- components/audit/GAPS.md | 16 ++++++++--- components/auth/GAPS.md | 8 ++++++ ...-02-auth-audit-normalization.md.tasks.json | 8 +++--- 4 files changed, 45 insertions(+), 14 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index 01f89db..dd3dc65 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -120,12 +120,12 @@ each project's **code-verified current state**, and the **gaps** between. See | Component | Status | Goal | Design | Implementation | |---|---|---|---|---| -| Auth (login / identity / authz) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Auth` lib | [`components/auth/`](components/auth/) | [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) | +| Auth (login / identity / authz) | Adopted (lib `0.1.3`; all 3 apps, **local-only branches** `feat/adopt-zb-auth`) | Shared `ZB.MOM.WW.Auth` lib | [`components/auth/`](components/auth/) | [`ZB.MOM.WW.Auth/`](ZB.MOM.WW.Auth/) | | UI Theme (layout / tokens / components) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Theme` RCL | [`components/ui-theme/`](components/ui-theme/) | [`ZB.MOM.WW.Theme/`](ZB.MOM.WW.Theme/) | | Health (readiness / liveness / active-node) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Health` lib | [`components/health/`](components/health/) | [`ZB.MOM.WW.Health/`](ZB.MOM.WW.Health/) | | Observability (metrics / traces / logs) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Telemetry` lib + `.Serilog` | [`components/observability/`](components/observability/) | [`ZB.MOM.WW.Telemetry/`](ZB.MOM.WW.Telemetry/) | | Config + validation (options / startup validation) | Adopted (lib `0.1.0`; all 3 apps, local) | Shared `ZB.MOM.WW.Configuration` lib | [`components/configuration/`](components/configuration/) | [`ZB.MOM.WW.Configuration/`](ZB.MOM.WW.Configuration/) | -| Audit (event model + writer seam) | Built (lib `0.1.0`) | Shared `ZB.MOM.WW.Audit` lib | [`components/audit/`](components/audit/) | [`ZB.MOM.WW.Audit/`](ZB.MOM.WW.Audit/) | +| Audit (event model + writer seam) | Adopted (lib `0.1.0`; all 3 apps, **local-only branches** `feat/adopt-zb-audit`) | Shared `ZB.MOM.WW.Audit` lib | [`components/audit/`](components/audit/) | [`ZB.MOM.WW.Audit/`](ZB.MOM.WW.Audit/) | The auth component is fully populated: a normalized [`spec`](components/auth/spec/SPEC.md), a proposed [`shared-contract`](components/auth/shared-contract/ZB.MOM.WW.Auth.md), three @@ -137,7 +137,13 @@ The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Auth/`](ZB (its own nested git repo; .NET 10; 4 packages — `Abstractions`, `Ldap`, `ApiKeys`, `AspNetCore`; 172 tests; `dotnet pack` → 4 nupkgs @ 0.1.0). The implementation plan is at [`docs/plans/2026-06-01-zb-mom-ww-auth-shared-library.md`](docs/plans/2026-06-01-zb-mom-ww-auth-shared-library.md). -**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/auth/GAPS.md`](components/auth/GAPS.md) (#8). +**Adopted across all three apps on 2026-06-02** (auth GAPS #1–#8) on each repo's **local-only** `feat/adopt-zb-auth` +branch — committed + reviewed, **NOT merged to default and NOT pushed** to any remote. Cutover: shared `Auth.Ldap`, +`Auth.ApiKeys` (ScadaBridge inbound fully re-architected to the keyId/Bearer model), `IGroupRoleMapper` seam, +`Transport`-enum config, canonical `ZbClaimTypes`/`ZbCookieDefaults`, unified dev base DN `dc=zb,dc=local`, and the +canonical-six role vocabulary (with ScadaBridge's accepted auditor/admin SoD collapse). Consumer pins: OtOpcUa `0.1.1`, +MxGateway `0.1.2`, ScadaBridge `0.1.3`. Per-repo detail in [`components/auth/GAPS.md`](components/auth/GAPS.md) + +`docs/plans/2026-06-02-auth-audit-normalization*.md`. Build/test from `ZB.MOM.WW.Auth/`: `dotnet test`. Consumer matrix: OtOpcUa → Abstractions+Ldap+AspNetCore; MxAccessGateway & ScadaBridge → all four (ApiKeys not used by OtOpcUa). @@ -231,10 +237,19 @@ principal. `IAuditRedactor` is aligned with Telemetry's `ILogRedactor` seam conv The shared library is **built and lives in this repo** at [`ZB.MOM.WW.Audit/`](ZB.MOM.WW.Audit/) (.NET 10; 1 package — `ZB.MOM.WW.Audit`; only non-BCL dependency `Microsoft.Extensions.DependencyInjection.Abstractions`; 19 tests; `dotnet pack` → 1 nupkg @ 0.1.0). Repo: `https://gitea.dohertylan.com/dohertj2/zb-mom-ww-audit`. -**Not yet adopted** by the three apps — that's the follow-on tracked in [`components/audit/GAPS.md`](components/audit/GAPS.md). +**Adopted across all three apps on 2026-06-02** (audit GAPS #1–#6) on each repo's **local-only** `feat/adopt-zb-audit` +branch (stacked on `feat/adopt-zb-auth`) — committed + reviewed, **NOT merged to default and NOT pushed**. Depth = +**DEEP adopt** (the canonical 9-field `AuditEvent` is the record everywhere; domain fields ride in `DetailsJson`). +OtOpcUa: canonical record + `AuditWriterActor : IAuditWriter` + `Outcome` column/migration + `ClusterAudit` fix. +MxGateway: new canonical SQLite `audit_event` store + `IAuditWriter` + `IApiKeyAuditStore`→canonical adapter. +**ScadaBridge: a full audit-subsystem re-architecture** (the program's largest task) — canonical record everywhere via a +deterministic codec; site SQLite split into `audit_event` + an `audit_forward_state` forwarding sidecar; central +partitioned `dbo.AuditLog` collapsed to 10 canonical cols + persisted computed cols (`CollapseAuditLogToCanonical` +migration, MSSQL-verified). Phase 3 wires `Actor` from the Auth principal at authenticated emit sites (per-app +`IAuditActorAccessor`). Per-repo detail in [`components/audit/GAPS.md`](components/audit/GAPS.md) + +`docs/plans/2026-06-02-auth-audit-normalization-phase2-deep.md` + `…-scadabridge-audit-rearch.md`. Build/test from `ZB.MOM.WW.Audit/`: `dotnet test`. Consumer matrix: all three apps consume the single -`ZB.MOM.WW.Audit` package (OtOpcUa, MxAccessGateway, ScadaBridge each map their own audit record/seam -onto the canonical type at the emit boundary). +`ZB.MOM.WW.Audit` package (OtOpcUa, MxAccessGateway, ScadaBridge — DEEP-adopted as the canonical record). ## Per-project primary commands diff --git a/components/audit/GAPS.md b/components/audit/GAPS.md index cb82e30..4fe8c73 100644 --- a/components/audit/GAPS.md +++ b/components/audit/GAPS.md @@ -3,10 +3,18 @@ Divergence of each project from [`spec/SPEC.md`](spec/SPEC.md), and the ordered backlog to reach the shared `ZB.MOM.WW.Audit` library. Status legend: ⛔ gap · 🟡 partial · ✅ matches. -> **Adoption is deferred this round.** The library is being designed (shared contract in -> [`shared-contract/ZB.MOM.WW.Audit.md`](shared-contract/ZB.MOM.WW.Audit.md)) but is not yet -> wired into any app — exactly where `ZB.MOM.WW.Auth` and `ZB.MOM.WW.Theme` sit today. -> The items below are the follow-on work; each lands as a separate PR per project. +> **✅ ADOPTED 2026-06-02 (local-only) — DEEP.** The backlog (#1–#6) was implemented across all three apps on each repo's +> **`feat/adopt-zb-audit`** branch (stacked on `feat/adopt-zb-auth`) — committed + spec/code-reviewed, **NOT merged to +> default and NOT pushed**. The user chose **DEEP adopt**: the canonical 9-field `AuditEvent` is the record EVERYWHERE +> (domain fields ride in `DetailsJson`), so the §1 "keep own record" framing below was superseded. OtOpcUa: canonical +> record + `AuditWriterActor : IAuditWriter` + `Outcome` col/migration + `ClusterAudit` fix. MxGateway: canonical SQLite +> `audit_event` store + `IAuditWriter` + `IApiKeyAuditStore`→canonical adapter. **ScadaBridge: a full audit-subsystem +> re-architecture** (codec + site `audit_event`/`audit_forward_state` sidecar + central partitioned-table collapse to +> 10 canonical + persisted computed cols, MSSQL-verified). §5 (Actor→Auth principal) wired via per-app +> `IAuditActorAccessor` (Phase 3). The Task 2.0 gate found this doc's pre-adoption framing was partly stale (MxGateway's +> store had moved into the lib; OtOpcUa's structured path was dormant; ScadaBridge's filter was typed to its own record). +> Detail: `docs/plans/2026-06-02-auth-audit-normalization-phase2-deep.md` + `…-scadabridge-audit-rearch.md`. The +> ⛔/🟡 cells below describe the PRE-adoption divergence (kept for history). ## Divergence vs spec diff --git a/components/auth/GAPS.md b/components/auth/GAPS.md index 0cae63a..8d57e99 100644 --- a/components/auth/GAPS.md +++ b/components/auth/GAPS.md @@ -3,6 +3,14 @@ Divergence of each project from [`spec/SPEC.md`](spec/SPEC.md), and the ordered backlog to reach the shared `ZB.MOM.WW.Auth` library. Status legend: ⛔ gap · 🟡 partial · ✅ matches. +> **✅ ADOPTED 2026-06-02 (local-only).** The full backlog (#1–#8) was implemented across all three apps on each repo's +> **`feat/adopt-zb-auth`** branch — committed + spec/code-reviewed, **NOT merged to default and NOT pushed**. Shared +> `Auth.Ldap` + `Auth.ApiKeys` (ScadaBridge inbound re-architected to keyId/Bearer), `IGroupRoleMapper`, +> `Transport`-enum config, canonical `ZbClaimTypes`/`ZbCookieDefaults`, unified dev base DN `dc=zb,dc=local`, and the +> canonical-six roles (with ScadaBridge's accepted auditor/admin SoD collapse). Consumer pins: OtOpcUa `0.1.1`, +> MxGateway `0.1.2`, ScadaBridge `0.1.3`. Detail: `docs/plans/2026-06-02-auth-audit-normalization*.md`. The ⛔/🟡 cells +> below describe the PRE-adoption divergence (kept for history). + ## Divergence vs spec ### §1 LDAP config schema 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 f11c1a6..203e31f 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 @@ -5,7 +5,7 @@ {"id": 7, "subject": "Phase 0 umbrella — publish + feed-map", "status": "completed", "blockedBy": [11, 12, 13, 14, 15, 16]}, {"id": 8, "subject": "Phase 1 umbrella — adopt ZB.MOM.WW.Auth — COMPLETE (all of 1.0-1.7 across 3 repos, reviewed, local-only)", "status": "completed", "blockedBy": [7, 17, 18, 19, 20, 21, 22, 23, 24]}, {"id": 9, "subject": "Phase 2 umbrella — adopt ZB.MOM.WW.Audit — COMPLETE (OtOpcUa 2.1/2.2, MxGateway 2.3, ScadaBridge 2.5 full re-arch C1-C7; all reviewed, local-only)", "status": "completed", "blockedBy": [7, 8, 25, 26, 27, 28, 29]}, - {"id": 10, "subject": "Phase 3 umbrella — wire Actor from Auth principal", "status": "pending", "blockedBy": [8, 9, 30, 31]}, + {"id": 10, "subject": "Phase 3 umbrella — wire Actor from Auth principal — COMPLETE (IAuditActorAccessor per app + emit-site wiring; all reviewed, local-only)", "status": "completed", "blockedBy": [8, 9, 30, 31]}, {"id": 11, "subject": "Task 0.1: Add push.sh for ZB.MOM.WW.Audit", "status": "completed", "blockedBy": []}, {"id": 12, "subject": "Task 0.2: Build+test both libs green", "status": "completed", "blockedBy": []}, @@ -29,8 +29,8 @@ {"id": 28, "subject": "Task 2.3: MxGateway store→IAuditWriter adapter (#2,#6) [re-scoped high-risk] — DONE a5944bb+7ea8358 (canonical SQLite store+adapter; spec+code reviewed)", "status": "completed", "blockedBy": [25]}, {"id": 29, "subject": "Task 2.5: ScadaBridge audit DEEP full-rearch to 9-col canonical (#3) [high-risk] — DONE C1-C7 (3d77dc0,adfb4d3/5aaf9e2,db707bb/c27b2c3,946d3e2/1737d15,68a6bd1,C6-subsumed,635461c/bc0e5bf); all spec+code reviewed, MSSQL-verified", "status": "completed", "blockedBy": [25]}, - {"id": 30, "subject": "Task 3.1: Introduce IAuditActorAccessor seam", "status": "pending", "blockedBy": [9]}, - {"id": 31, "subject": "Task 3.2-3.4: Wire emit sites to Auth principal (#4)", "status": "pending", "blockedBy": [30]}, + {"id": 30, "subject": "Task 3.1: IAuditActorAccessor seam (per-app HTTP accessor) — DONE (OtOpcUa 075c0e6, MxGw 0859d47, SB b3de840)", "status": "completed", "blockedBy": [9]}, + {"id": 31, "subject": "Task 3.2-3.4: Wire emit sites to Auth principal (#4) — DONE (MxGw dashboard Actor=operator/Target=keyId; SB inbound Actor from principal w/ auth-fail-null; OtOpcUa seam forward-looking) — reviewed", "status": "completed", "blockedBy": [30]}, {"id": 32, "subject": "Task 1.3-L: Extend Auth.ApiKeys admin store (SetScopes/SetEnabled) -> lib 0.1.3 (PUBLISHED)", "status": "completed", "blockedBy": []}, {"id": 33, "subject": "Task 1.3-C1: ScadaBridge re-pin 0.1.3 + IInboundApiKeyAdmin seam (additive) + baseline reds fixed", "status": "completed", "blockedBy": [32]}, @@ -39,5 +39,5 @@ {"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": "completed", "blockedBy": [34, 35, 36]} ], - "lastUpdated": "2026-06-02 (Phase 2 COMPLETE: OtOpcUa+MxGateway+ScadaBridge audit done; ScadaBridge was DEEP full-rearch C1-C7. Next = Phase 3 Actor->principal wiring, tasks #30/#31)" + "lastUpdated": "2026-06-02 — PROGRAM COMPLETE (Phases 0-3 done across 3 repos: Auth + Audit normalized, Actor wired from principal). All local-only on feat/adopt-zb-auth + feat/adopt-zb-audit; NOTHING pushed/merged. Remaining = exit-gate doc updates + user merge/push decision." }