docs: truth sweep — reconcile stale deferment/archreview/plan records with shipped state
v2-ci / build (push) Successful in 6m26s
v2-ci / unit-tests (push) Failing after 18m0s

- deferment.md: node ACLs no longer authored-but-inert (#520 shipped through stage 7, opt-in Security:Acl:Enabled); failure-visibility trio mostly closed (01/S-1 + 03/S4 fixed, 06/S-1 partial); bulkhead + WriteIdempotentAttribute closed by R2-02; Sql Postgres+Oracle dialects shipped (d54f3c83); akka-hosting partials verified superseded
- archreview/00-OVERALL.md: staleness banner on the carried-open block (04/C-1→R2-05, 03/S2+S3→R2-08, 03/P1→R2-07, driver fleet→R2-09/R2-11/#457, hygiene→R2-12, trio per above; what genuinely remains from theme 4)
- archreview/plans/STATUS.md: carved out the true exceptions to "every Round-2 live gate GREEN" (R2-03 T11/T12 deferred-live, R2-10 T10 breaker-OPEN never forced); #459 closed by mesh Phase 7 drill D4 (c50ebcf7)
- archreview/plans/INTEGRATION-SWEEP-STATUS.md: "follow-ups unstarted" → all 7 shipped as PRs #446–#452
- archreview/06-gateway-integrations.md: 06/S-1 STILL OPEN → PARTIAL (fail-closed advise + unconfirmed meter; residual cross-repo)
- 2026-07-31-apikey-acl-enforcement-design.md: status → implemented through stage 7, #520 CLOSED 2026-08-01
- 2026-07-21-per-cluster-mesh-design.md: "Phases 1–7 not started" → PROGRAM COMPLETE 2026-07-24 (Phase 7 c50ebcf7)
- 2026-07-20-localdb-phase2-live-gate.md: merged as 06b5d81b; open design question shipped by mesh Phase 6 (checks 3/4 still never re-run on the three-mesh topology)
- 2026-07-20-localdb-phase1-progress.md: Tasks 10–16 REMAIN → Phase 1 complete, live-gated 8/8, merged c957db52
- 2026-08-06-clusterclient-to-grpc-tracking.md: defect 4 OPEN → fixed by c0475f2d + e54883a8, merged @ b360239e
- 2026-08-06-clusterclient-to-grpc.md.tasks.json: Task 15 pending → completed (Phase 4 gate PASS 8/8 @ 0b194003, record d0ac6fc5)
- 2026-07-22-mesh-phase2-live-gate.md: DriverStatusPanel orphan → wired into /hosts by #546 (9420f8ef)
- 2026-07-21-issue-485-live-gate.md: pointer from the "NOT fixed here" finding to the #486 fix (DriverHostActor.cs:1696-1717 + FetchAndCache mirror)
- 2026-08-05-sql-postgres-oracle.md: chrome/AdminUI gate not deferred — PASSED 2026-08-05, found + fixed the Test-Connect provider gate (4e461951)
- v2-ga-lab-gates-plan.md / v2-release-readiness.md / live-hardware-validation-runbooks.md: FOCAS live-CNC smoke #54 RESOLVED on a real 31i-B 2026-06-25 (cnc_rdparam caveat preserved)
- Mqtt-Test-Fixture.md: STATE/DCMD "not implemented" → shipped + live-gated (#508 2a7d1167, #511 857a10b4)
- 2026-08-01-continuous-historization-live-gate.md: poison-tag FIFO pin "filed, not fixed" → #538 fixed same day (e7fbe977, gate 4bdce910; Capacity default now 500k)
- 2026-05-26-akka-hosting-alignment-plan.md.tasks.json: F8/F9/F10/F13/F14 partial → completed, superseded by the v3 address-space rework (Phase7Composer/ScriptedAlarmActor deleted; evaluators/SDK sinks/security policies production-wired)

Claude-Session: https://claude.ai/code/session_014WNM4vjoVksyyBraTXSZE1
This commit is contained in:
Joseph Doherty
2026-08-07 02:02:54 -04:00
parent 8b5c478c36
commit 290117660d
20 changed files with 128 additions and 29 deletions
+29 -8
View File
@@ -32,7 +32,7 @@ how much they should worry you:
| # | Theme | Why it matters | Now |
|---|---|---|---|
| **1** | **Three subsystems are fully authored, persisted, and shipped — and never executed.** Node ACLs, `IRediscoverable`/`IHostConnectivityProbe`, and `DriverTypeRegistry`. | An operator can author a rule, save it, deploy it green, and have it do **nothing**. §3 | ◐ **Two of three now settled**: `IRediscoverable` consumed (#518), `IHostConnectivityProbe` re-transported to telemetry (#521), `DriverTypeRegistry` + the tier machinery **deleted** (#522). Only **node ACLs** remain authored-but-inert, tracked as #520 |
| **1** | **Three subsystems are fully authored, persisted, and shipped — and never executed.** Node ACLs, `IRediscoverable`/`IHostConnectivityProbe`, and `DriverTypeRegistry`. | An operator can author a rule, save it, deploy it green, and have it do **nothing**. §3 | ✅ **All three settled**: `IRediscoverable` consumed (#518), `IHostConnectivityProbe` re-transported to telemetry (#521), `DriverTypeRegistry` + the tier machinery **deleted** (#522). Node ACLs are **now enforced** — #520 shipped through stage 7 (merges `fbe7403c` stages 1-2/4, `3a6b2a1d` stage 3, `1ccc7400`/`f692f6af` stage 5 write/alarms/HistoryRead, `d4389f57`/`00aa4866` stage 6 read/browse/subscribe, `3796c0bf` stage 7 authoring; wired at `Host/Program.cs:394-398` → `DataPlaneAuthorizer`). Enforcement is **opt-in**: `Security:Acl:Enabled` defaults `false` |
| **2** | **AdminUI authoring-dispatch gaps.** Calculation is offered in the driver picker but has no config form; three drivers have no device form; CSV + browse-commit dispatch maps miss the new drivers. | The "registered but unauthorable" class that has now bitten twice. §1.2 | ✅ **Closed** — G-1…G-6 fixed and guarded; G-7 remains |
| **3** | **17 open issues, all confirmed still open**, several broader than filed. | §2 | ◐ 6 resolved + closed, 6 new filed (one since closed) → **17 open**, none stale. Two of the six closures (#521, #522) resolved *differently from how they were filed* — see §3.2/§3.3 |
| **4** | **Bookkeeping drift.** 8 `.tasks.json` files show ~140 "pending" tasks for work that shipped; 5 CLAUDE.md status claims are stale. | Someone follows the tracker and rebuilds a shipped driver. §6, §7 | ✅ **Closed** — 13 plan files + 11 archreview gates written back |
@@ -56,9 +56,9 @@ So everything below is **untracked work**. Nothing in it is a data-loss or outag
| **4 live gates blocked on hardware/licence** — archreview R2-03 (VT Good→Bad on a data-fed rig), R2-10 (force breaker-OPEN), Galaxy `ScanStateProbeParityTests` (licence-gated), v2 GA exit criteria (FOCAS live-CNC smoke #54, OPC UA CTT pass, Ignition 8.3 cutover) | Cannot be closed from this box. Not decisions — inputs. | §5 |
| **1 deferred live-verify task** — `2026-06-14-driver-reconfigure-while-faulted` Task 3, subject literally "DEFERRED (skipped)" | Now runnable: docker-dev login is disabled, so `/run` verification needs no operator. | §5 |
| **G-7 residual** — Sql / MTConnect / Calculation / OpcUaClient have no Contracts-side `Inspect` | **The deploy gate is weaker than the authoring gate.** `TagConfigValidator` covers 11 of 12, so config arriving by **CSV import or API** — the paths that skip the UI — meets only the weaker gate. | §1.2 |
| **3 carried-open archreview findings** — the failure-visibility trio: 01/S-1 (`AddressSpaceApplier` swallows every sink failure; a deploy reports **Applied** while broken), 03/S4 (primary gate default-allows on unknown role), 06/S-1 (Galaxy optimistic write success) | No remediation branch ever targeted them. 01/S-1 is the sharpest: a green deploy that isn't. | §6.3 |
| ~~**3 carried-open archreview findings** — the failure-visibility trio~~ **Update 2026-08-07 (truth sweep): mostly CLOSED.** 01/S-1 **FIXED** — `AddressSpaceApplier.cs:95-97` tallies swallowed removal-pass failures into `AddressSpaceApplyOutcome.FailedNodes` (comment cites 01/S-1). 03/S4 **FIXED** — `PrimaryGatePolicy.cs` default-denies on unknown role when a driver peer exists (doc-comment "Fixes archreview 03/S4"), live-proven R2-04 T15. 06/S-1 **PARTIAL** — fail-closed advise path + `galaxy.writes.unconfirmed` meter shipped in `GatewayGalaxyDataWriter.cs`; residual = gateway-side WriteComplete correlation (cross-repo, mxaccessgw). | Residual is only the 06/S-1 cross-repo half. | §6.3 |
| **1 genuinely unexecuted plan** — `2026-05-29-adminui-followups`, **19 pending / 0 completed** | The only substantial engineering left. ⚠️ Its first step is an **overlap audit**, not code: several items look superseded by v3's `TagConfigEditorMap`. | §6.2 |
| **11 other open plan tasks** — 5 akka-hosting partials (likely v3-superseded), 4+1 followups-batch (open *by choice*), fixedtree Task 11, 1 manual smoke checklist | Small, and two of the groups are decisions already taken. | §6.2 |
| **11 other open plan tasks** — ~~5 akka-hosting partials (likely v3-superseded)~~ *(verified superseded 2026-08-07 — F8/F9/F10/F13/F14 marked completed; `Phase7Composer`/`ScriptedAlarmActor` deleted, evaluators/SDK sinks/security policies all production-wired)*, 4+1 followups-batch (open *by choice*), fixedtree Task 11, 1 manual smoke checklist | Small, and two of the groups are decisions already taken. | §6.2 |
| **Review-coverage gap** — 10 shipped projects never reviewed (Calculation, Historian.Gateway, Mqtt +Browser/Contracts, MTConnect +Contracts, Sql +Browser/Contracts) while **3 modules still review the retired Wonderware backend** | Re-verified 2026-08-04 against `code-reviews/`. Unchanged since the audit. | §6.3 |
| **`RawBrowseModal` stale-open race** (added 2026-08-05) — `OnParametersSetAsync` never re-checks staleness after its awaits, so a superseded open's late resolve can install the wrong device's browse config. The identical shape was found by review and **fixed** in `RawTagModal`/`RawManualTagEntryModal` (post-await staleness re-check; see `docs/plans/2026-08-05-raw-modal-picker-live-config-design.md` §6); the browse modal was deliberately left out of that branch's scope. | Lower stakes than the fixed pair (the modal resolves the device it was opened for and shows its own error banner), but the fix pattern is proven and cheap to port. | design doc §6 |
@@ -66,7 +66,10 @@ So everything below is **untracked work**. Nothing in it is a data-loss or outag
unknown role" — is the *same shape* as a decision deliberately taken on 2026-08-04 in
`PrimaryGatePolicy.ShouldRecordHistorizedValues`, where an unknown role **captures**. That is right for
historization (a duplicate sample beats a hole in the trend, and the duplicate is bounded by promotion)
and wrong for a write gate. Closing 03/S4 must not sweep both under one rule.
and wrong for a write gate. Closing 03/S4 must not sweep both under one rule. **Update 2026-08-07
(truth sweep): it didn't** — 03/S4 is closed with exactly this split preserved: `PrimaryGatePolicy.
ShouldServiceAsPrimary` default-denies on unknown role when a driver peer exists, while
`ShouldRecordHistorizedValues` still captures on unknown.
---
@@ -77,7 +80,7 @@ themes into tracked decisions. What remains:
| Item | Nature | Where |
|---|---|---|
| **#520** node ACLs authored + deployed but **never enforced** | Decision: wire it or retire the surface. Non-enforcement is now stated in docs and warned in the UI, so nobody can author a deny rule believing it works — but reads are still ungated. | §3.1 |
| **#520** node ACLs authored + deployed but **never enforced** ✅ **CLOSED 2026-08-01** *(truth-sweep note 2026-08-07: shipped through stage 7 — enforcement merges `fbe7403c`/`3a6b2a1d`/`1ccc7400`/`d4389f57`/`3796c0bf`; opt-in via `Security:Acl:Enabled`, default `false`)* | Decision: wire it or retire the surface. ~~Non-enforcement is now stated in docs and warned in the UI, so nobody can author a deny rule believing it works — but reads are still ungated.~~ It was wired: with the flag on, scoped grants decide every data-plane operation incl. read/browse/subscribe. | §3.1 |
| **#521** `IHostConnectivityProbe` / `DriverHostStatus` dead surface ✅ **CLOSED** `abda6f9e` | Resolved by changing the *transport*, not by either option as filed — the publisher as designed was unbuildable after Phase 4. Host status now rides `DriverHealthChanged` to `/hosts`; table dropped. | §3.2 |
| **#522** driver stability tiers inert ✅ **CLOSED** `abda6f9e` | Deleted. The inertness was broader than filed (nothing constructed `MemoryTracking` either), and the model's premise — an out-of-process Host to recycle — no longer exists. `DriverTier` kept. | §3.3 |
| ~~**#523** remove the periodic 5-min device re-browse~~ | ✅ **Done + closed on the tracker.** **AbCip and FOCAS now have no tag-change signal at all**; that is the accepted consequence, not an oversight. | §9 (2026-07-30, #523) |
@@ -242,6 +245,16 @@ subsystems are fully built and reachable by operators, but no production code pa
### 3.1 Node-level ACLs are authorable, deployed — and unenforced
> ✅ **Update 2026-08-07 (truth sweep): NO LONGER TRUE — #520 shipped through stage 7 and is CLOSED
> (2026-08-01).** Enforcement merges: `fbe7403c` (stages 1-2, 4: API-key identity + keys/ACLs in the
> artifact), `3a6b2a1d` (stage 3: variable-depth scope model), `1ccc7400`/`f692f6af` (stage 5: write,
> alarms, HistoryRead), `d4389f57`/`00aa4866` (stage 6: read, browse, subscribe), `3796c0bf` (stage 7:
> ACL authoring/scope picker). `TriePermissionEvaluator` is now wired at `Host/Program.cs:394-398` into
> `DataPlaneAuthorizer`, registered on every node. Enforcement is **opt-in** — `Security:Acl:Enabled`
> defaults `false`; with it off the two coarse server-wide gates remain the whole of data-plane
> authorization, with it on scoped `NodeAcl` grants decide every data-plane operation. The section
> below is preserved as the pre-#520 record.
> ◐ **Still true; now impossible to miss** (`53ede679`, Gitea **#520**). `docs/security.md`,
> `docs/ReadWriteOperations.md`, `docs/v2/acl-design.md` and `v2-release-readiness.md` corrected, and
> `ClusterAcls.razor` / `AclEdit.razor` carry a warning alert. The audit named
@@ -332,8 +345,8 @@ assigns Galaxy and FOCAS to Tier C.
| `IDriverConfigEditor` — interface, zero implementors, zero production consumers | `Core.Abstractions/IDriverConfigEditor.cs:9`; superseded by `TagConfigEditorMap` / `DriverConfigModal` |
| `GenericDriverNodeManager` — explicitly **not** a production dispatch path | `Core/OpcUa/GenericDriverNodeManager.cs:71` ("verified 07/#10: zero production references") |
| `IDriverSupervisor` — Tier-C recycle machinery has **zero implementations**, yet the parser still validates `RecycleIntervalSeconds` | archreview 01/U-2 |
| Resilience **bulkhead** — documented, defaulted, parsed, AdminUI-authorable; `Build` never adds a concurrency limiter | archreview 01/U-6 |
| `WriteIdempotentAttribute` — zero readers; write dispatch hardcodes `isIdempotent: true` | archreview 01/S-8 = 03/S12 |
| ~~Resilience **bulkhead** — documented, defaulted, parsed, AdminUI-authorable; `Build` never adds a concurrency limiter~~ **Update 2026-08-07 (truth sweep): closed by archreview R2-02** — the bulkhead knob was **deleted end-to-end** (migration-free; stored keys ignored) with an inertness guard test; see `archreview/plans/STATUS.md` R2-02 row | archreview 01/U-6 |
| ~~`WriteIdempotentAttribute` — zero readers; write dispatch hardcodes `isIdempotent: true`~~ **Update 2026-08-07 (truth sweep): closed by archreview R2-02** — dispatch flipped to `isIdempotent: false` (RED-first on the Runtime wiring test) and the attribute's false claim corrected; see `archreview/plans/STATUS.md` R2-02 row | archreview 01/S-8 = 03/S12 |
| ~60 lines of unreachable code retained behind #507's guard | `DriverHostActor.cs:1002`, `#pragma warning disable CS0162` |
| Three empty `Driver.Historian.Wonderware*` directories (0 `.cs`, no `.csproj`, absent from `.slnx`) | verified for this report — only stale `bin/`+`obj/` remain |
@@ -359,7 +372,7 @@ commented-out DI registrations.** Real deferred work lives in prose doc-comments
- **S7** — array **writes** unsupported entirely (`S7Driver.cs:1139`); several array *read* types unsupported (`:386,404,413,419,428,442,465,807,959`) — all fail fast at config-validation; legacy C-area counter reinterpretation live-hardware-gated (`:759`); Counter BCD on S7-300/400 undecoded.
- **AbCip** — ALMD-only alarm projection, ALMA deferred (`AbCipAlarmProjection.cs:16,324`); no CIP Template Object reader, UDT layouts declaration-driven (`AbCipDriverOptions.cs:172`); whole-UDT writer deferred (`LibplctagTagRuntime.cs:190`); `AckCmd` pulse must be wired client-side (`:30`).
- **Sql** — `SqlTagModel.Query` deferred to P3, **enforced end-to-end** across parser, validator, planner and editor (`SqlProvider.cs:22,37`; `SqlEquipmentTagParser.cs:24,103`; `SqlGroupPlanner.cs:44,249`; `SqlTagConfigModel.cs:114`) — exemplary deferral discipline. Postgres/ODBC dialects deferred behind `ISqlDialect`.
- **Sql** — `SqlTagModel.Query` deferred to P3, **enforced end-to-end** across parser, validator, planner and editor (`SqlProvider.cs:22,37`; `SqlEquipmentTagParser.cs:24,103`; `SqlGroupPlanner.cs:44,249`; `SqlTagConfigModel.cs:114`) — exemplary deferral discipline. ~~Postgres/ODBC dialects deferred behind `ISqlDialect`~~ *(update 2026-08-07, truth sweep: **PostgreSQL and Oracle dialects shipped 2026-08-05**, merge `d54f3c83` — managed Npgsql / Oracle.ManagedDataAccess.Core, live-gated; `MySql`/`Odbc` remain reserved enum names that fail at construction)*.
- **MTConnect** — `TIME_SERIES` vectors deferred to P1.5; `DATA_SET`/`TABLE` coded `BadNotSupported` with a null value rather than approximated (`MTConnectObservationIndex.cs:53,272`) — deliberately chosen over a Good-coded lie. `RawTagEntry.DeviceName` ignored for routing (two `/raw` Devices under one driver share an Agent connection) — "a design change, not a bug fix". No DataType-vs-blob validation at authoring.
- **MQTT** — `MaxPayloadBytes` is a constructor knob, not operator-facing (`MqttSubscriptionManager.cs:170`).
- **TwinCAT** — Flat-mode struct expansion carries a **LIVE RISK** note, unverified against a real TC3 target (`AdsTwinCATClient.cs:270`); VirtualTree-mode browse unverified; TC2 coverage, multi-hop AMS route and lab rig all hardware-blocked (`docs/v3/twincat-backlog.md`).
@@ -475,6 +488,11 @@ bookkeeping, not backlog.
targeted them" block. The largest coherent batch is the **failure-visibility trio**: 01/S-1
(`AddressSpaceApplier` swallows every sink failure, deploy reports Applied even when broken), 03/S4
(primary gate default-allow on unknown role), 06/S-1 (Galaxy optimistic write success).
**Update 2026-08-07 (truth sweep): the trio is mostly closed.** 01/S-1 fixed
(`AddressSpaceApplier.cs:95-97` → `AddressSpaceApplyOutcome.FailedNodes`); 03/S4 fixed
(`PrimaryGatePolicy.cs` default-deny on unknown role with a driver peer, live-proven R2-04 T15);
06/S-1 partial (fail-closed advise path + `galaxy.writes.unconfirmed` meter in
`GatewayGalaxyDataWriter.cs`; residual = gateway-side WriteComplete correlation, cross-repo).
- **`stillpending.md` does not exist** — the backlog is `docs/plans/2026-06-18-stillpending-backlog-audit.md`.
---
@@ -544,6 +562,9 @@ appear in §7.1 as well.
`docs/ReadWriteOperations.md` first; it is the one that could mislead a security review.~~
✅ **Done** — decided *make non-enforcement explicit*; wire-up tracked as Gitea **#520**. See §9.
(`docs/ReadWriteOperations.md` was **not** the sharpest one — `docs/security.md` was.)
**Update 2026-08-07 (truth sweep): the wire-up itself has since shipped** — #520 CLOSED 2026-08-01
through stage 7 (merges `fbe7403c`, `3a6b2a1d`, `1ccc7400`, `d4389f57`, `3796c0bf`); enforcement
opt-in via `Security:Acl:Enabled` (default `false`). See §3.1's banner.
2. ~~**#518 + #507 together** — neither fix is observable alone.~~ ✅ **Done.** The framing was right
that they had to be handled together, but wrong about the resolution: **#507 was not revivable**,
so it was deleted rather than fixed. See §9.