diff --git a/.claude/skills/add-background-job/SKILL.md b/.claude/skills/add-background-job/SKILL.md index e3cabd29..15adcc3a 100644 --- a/.claude/skills/add-background-job/SKILL.md +++ b/.claude/skills/add-background-job/SKILL.md @@ -50,7 +50,7 @@ Use [implement-task](../implement-task/SKILL.md) as the substantive entry point. ### 1. Check the delivered boundary Read the feature roadmap and current -[P02b-4 record](../../../docs/roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15). +[P02b-4 record](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15). P02b-4 intentionally carries no production business definitions or recurrence manifests. The first feature must explicitly reconcile that infrastructure-only census when its own accepted phase delivers real definitions. diff --git a/.claude/skills/add-frontend-route/SKILL.md b/.claude/skills/add-frontend-route/SKILL.md index e0101fb5..38442f38 100644 --- a/.claude/skills/add-frontend-route/SKILL.md +++ b/.claude/skills/add-frontend-route/SKILL.md @@ -135,7 +135,7 @@ entry before rebuilding downstream request headers. The caller verifies the envelope again. G35 and G36 are recorded in [Phase 02d's decision register](../../../docs/roadmap/phase-02d-walking-skeleton.md#the-decision-register). Don't read `host` directly inside a page. The -[public entry matrix](../../../docs/roadmap/phase-02d-walking-skeleton.md#public-entry-matrix) +[public entry matrix](../../../docs/roadmap/phase-02d-delivery-log.md#public-entry-matrix) is authoritative: bootstrap the live host before locale/redirect decisions; enabled-locale membership precedes `courses` shorthand and exact `/studio` or `/portal` scaffold handling. Disabled/malformed/unknown prefixes fail closed; @@ -148,7 +148,7 @@ through bootstrap and the configured caller; Phase 11 owns participation/samplin requires native GET/HEAD admission on every HTTP callback path, including middleware-exempt health/assets/scaffolds, with masked no-store refusal of other methods and bodyless HEAD. Production upgrades close; development retains only -validated GET HMR. The [remediation record](../../../docs/roadmap/phase-02d-walking-skeleton.md#remediation-step-2--native-ingress-and-url-boundary) +validated GET HMR. The [remediation record](../../../docs/roadmap/phase-02d-delivery-log.md#remediation-step-2--native-ingress-and-url-boundary) owns validation and both independent review rounds. Do not add Server Actions/write routes or WebSocket consumers without an explicit owning Phase 02b/Phase 06 @@ -238,9 +238,9 @@ locale, document language and actual resolved-label language. The guarded frontend suite supplies ICU, argument and callsite checks. No `lint:i18n` command or screenshot/axe tooling exists. The -[Step 1 delivery record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[Step 1 delivery record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns foundation validation; the -[packet closeout](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +[packet closeout](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records the delivered product proof and scoped manual accessibility checks. ### Step 8: Public-site SSR caching @@ -296,7 +296,7 @@ document, one per fixed status/scaffold document and three per followed missing document. Metadata/layout/page/UI share the admitted snapshot without another bootstrap or cross-request cache. HEAD/RSC/prefetch and Flight fallback require separately proven counts. The -[Step 3 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../../../docs/roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) records passing production replacement proofs, completed reviews and verified fixes. ### Step 10: Tests @@ -319,7 +319,7 @@ records passing production replacement proofs, completed reviews and verified fi catalog/course/lesson routes under [ADR-0056](../../../docs/decisions/0056-public-demo-browser-and-lighthouse-enforcement.md). Preserve its production-page admission, hard budgets and owned cleanup. The - [P7 Step 4 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) + [P7 Step 4 record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns completed G44/G45 enforcement; Phase 06 still owns broader Playwright/axe coverage. diff --git a/.claude/skills/add-i18n-key/SKILL.md b/.claude/skills/add-i18n-key/SKILL.md index 6ca14750..a09bcb78 100644 --- a/.claude/skills/add-i18n-key/SKILL.md +++ b/.claude/skills/add-i18n-key/SKILL.md @@ -24,9 +24,9 @@ Manage user-facing translations in `apps/web` consistently per > [ADR-0027](../../../docs/decisions/0027-frontend-i18n.md) selects exact > `next-intl` 4.14.9 and the catalogue home below. Step 1 installs the runtime, > complete English/Turkish catalogues and guarded ICU/callsite checks. Its -> [delivery record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +> [delivery record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) > owns foundation validation; the -> [packet closeout](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +> [packet closeout](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) > records the scoped product and manual accessibility evidence. No > `pnpm lint:i18n`, `no-literal-strings`, `_deprecated.json`, screenshot or > `axe-core` task exists today; do not claim those checks run. diff --git a/.claude/skills/add-integration-event/SKILL.md b/.claude/skills/add-integration-event/SKILL.md index eed91c00..99516ea8 100644 --- a/.claude/skills/add-integration-event/SKILL.md +++ b/.claude/skills/add-integration-event/SKILL.md @@ -30,14 +30,14 @@ owns immediate producer admission, completion and payload policy. P02b-1 Steps 2/3 implement immediate enqueue, payload admission, successful-save collection and the completed-provisioning publisher. Step 4 implements the production censuses and catalogue enforcement; the -[delivery record](../../../docs/roadmap/phase-02b-events-auth.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) +[delivery record](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns final verification and review status. Accepted [ADR-0046](../../../docs/decisions/0046-durable-event-delivery-and-recovery.md) owns dispatcher recovery, subscription readiness and the shared inbox contract. P02b-2 implements producer dispatch; P02b-3 Steps 1–4 implement durable acceptance, shared inbox/ledger storage, independent execution and scheduling. Step 5 supplies the real default subscriptions and semantic Seeder handoff; the -[delivery record](../../../docs/roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +[delivery record](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns validation/review status. ## When to use diff --git a/.claude/skills/add-page-block/SKILL.md b/.claude/skills/add-page-block/SKILL.md index 6ef66a7d..6c61d7c4 100644 --- a/.claude/skills/add-page-block/SKILL.md +++ b/.claude/skills/add-page-block/SKILL.md @@ -66,7 +66,7 @@ and [17-page-builder.md](../../../docs/architecture/17-page-builder.md). > and no active URL sink. The wider registry and component sketches below remain > Phase 04/05 and Phase 06 targets. The existing key lists in > `src/lib/customization/` are not renderer implementations. See the -> [accepted package](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-accepted-answers). +> [accepted package](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-accepted-answers). `RegisterPrimitive`, `BlockRenderer`, `resolver.registerPrimitive` and `useContentEntries` below are illustrative future APIs, not existing symbols to @@ -216,7 +216,7 @@ the page. planted controls, localized product-page semantics and real manual keyboard, focus, reflow, contrast and screen-reader evidence. Step 3 implements the applicable lint controls and synchronous lesson semantics. The - [Step 4 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) + [Step 4 record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) records product proofs and the scoped manual browser/screen-reader checks. - [Performance Standards](../../../docs/standards/15-performance.md) governs pages embedding the block. P02d-7's shared `make demo DEMO_MODE=ci` proof supplies diff --git a/.claude/skills/code-review/SKILL.md b/.claude/skills/code-review/SKILL.md index 136c3ed7..ada41747 100644 --- a/.claude/skills/code-review/SKILL.md +++ b/.claude/skills/code-review/SKILL.md @@ -83,7 +83,7 @@ Walk every change against the project's | **Authn / authz** | Every new endpoint has `[Authorize(Policy=…)]` or `[AllowAnonymous]` with a comment. Policy keys exist in the permission registry. Resource-scope handlers (`instructor` edits own course only) present where needed. | | **Tenant id from the resolved context only** | Resolved per [ADR-0036](../../../docs/decisions/0036-tenant-resolution-trusted-inputs.md): from the host lookup of the effective host, or on a platform host from validated claims confirmed by live membership; off HTTP, from the validated authoritative job row or the integration-event envelope. Never from a request body, query string, cookie or tenant header — `X-Tenant-Id` and `X-Organization-Id` are assertions that can only reject, on every hop. Check command and DTO surfaces. | | **SQL injection** | EF Core LINQ or `FromSqlInterpolated`; never raw string concatenation. Raw SQL has parameters. | -| **XSS** | No `dangerouslySetInnerHTML` outside a sanitisation wrapper; CSP nonces in place; markdown via allowlist. Nothing sets a CSP today: the [standards index](../../../docs/standards/README.md#honest-status-today) row for Security Standards carves § HTTP Headers out to [Phase 11](../../../docs/roadmap/phase-11-production-hardening.md#security), so a missing nonce is not a Blocker until that phase sets one. Accepted P02d-6 G42 requires atomic four-color validation and a fixed style element, with whole-palette fallback; output must be safe without CSP. [The accepted package](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-accepted-answers) owns its proof obligations; acceptance alone is not delivery. | +| **XSS** | No `dangerouslySetInnerHTML` outside a sanitisation wrapper; CSP nonces in place; markdown via allowlist. Nothing sets a CSP today: the [standards index](../../../docs/standards/README.md#honest-status-today) row for Security Standards carves § HTTP Headers out to [Phase 11](../../../docs/roadmap/phase-11-production-hardening.md#security), so a missing nonce is not a Blocker until that phase sets one. Accepted P02d-6 G42 requires atomic four-color validation and a fixed style element, with whole-palette fallback; output must be safe without CSP. [The accepted package](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-accepted-answers) owns its proof obligations; acceptance alone is not delivery. | | **CSRF** | Server Actions / Auth.js session check; non-Action mutating fetches carry CSRF tokens. | | **Secrets** | No secret in source / appsettings / env-file-committed; reads through `ISecretProvider`. No log of token / password / national id. | | **PII redaction** | `[PiiSensitive]` fields carry `SensitiveTokenCatalog.RedactedValue` in audit snapshots — the property stays, so the diff still records *that* it changed; logs don't carry raw PII. | diff --git a/.claude/skills/implement-task/SKILL.md b/.claude/skills/implement-task/SKILL.md index c26bfb10..e4bf9dc5 100644 --- a/.claude/skills/implement-task/SKILL.md +++ b/.claude/skills/implement-task/SKILL.md @@ -171,7 +171,8 @@ match the change: for prerequisites, artifact review and cleanup. The Playwright library proof covers nine seeded pages and 27 audits; Phase 06 owns the full Playwright Test/ axe suite. There is no `pnpm test:a11y` or `pnpm test:e2e` script. -- Documentation-only → broken-link sweep + `docs/analysis/` residual scan +- Documentation-only → `make lint-docs` (whole-tree fragment audit and roadmap + structure guard) + broken-link sweep + `docs/analysis/` residual scan (see Step 7's link audit). A failing test is the work telling you to keep going. Fix the underlying issue; @@ -187,7 +188,14 @@ list, update what applies, leave nothing stale: - **Roadmap.** Did this phase deliver something new? Update the phase doc's Deliverables / Completion Criteria. Did this complete a phase exit - criterion? Note it. + criterion? Note it. A packet's decision package, step record, review round, + correction or closeout is a dated `###` entry under its packet in the phase's + `phase--delivery-log.md`, never a section of the phase doc; the phase + doc changes only the packet's Status row. Read a log through the generated + index at its top, never whole, and run `make docs-index` after adding an + entry. Do not narrate packet status in + `CLAUDE.md`, the repository README or the roadmap index + ([ADR-0069](../../../docs/decisions/0069-phase-documents-and-delivery-logs.md)). - **Standards.** Did the change introduce a new rule or refine an existing one? Update the relevant standard + cite the ADR (use [write-adr](../write-adr/SKILL.md) if the rule deserves one). diff --git a/.claude/skills/local-dev-setup/SKILL.md b/.claude/skills/local-dev-setup/SKILL.md index 06857e0d..67795a5e 100644 --- a/.claude/skills/local-dev-setup/SKILL.md +++ b/.claude/skills/local-dev-setup/SKILL.md @@ -313,7 +313,7 @@ state. ## Validation [ADR-0053](../../../docs/decisions/0053-trusted-public-server-rendering.md) -and the [P5 package](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-5-decision-package-2026-10-08) +and the [P5 package](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-5-decision-package-2026-10-08) own the accepted host/TLS/transport contract. P02d-7 supplies foreground `make demo` and CI browser/audit mode. Follow README Quickstart for production-build launch, owned cleanup, retained local data and stale-lock handling. The packet's Step 4 diff --git a/.claude/skills/run-tests-locally/SKILL.md b/.claude/skills/run-tests-locally/SKILL.md index 7b40aecc..592487aa 100644 --- a/.claude/skills/run-tests-locally/SKILL.md +++ b/.claude/skills/run-tests-locally/SKILL.md @@ -173,7 +173,7 @@ an existing user process. P6 adds separate production product modes for foundati pagination, presentation, concurrent isolation and freshness/failure states. Those HTTP/HTML/RSC proofs do not claim browser or screen-reader execution; P6's manual accessibility closeout is recorded with its tested scope in the -[packet closeout](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10). +[packet closeout](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10). New UI changes require their own applicable manual checks; P7 supplies the narrow seeded browser demo described below. @@ -188,7 +188,7 @@ to its certificate's public-key fingerprint; it does not use a personal profile. Browser observations cover a refused Flight followed by stock Next's fresh document navigation and separately counted API calls. HMR controls cover source recompilation and a fresh live site snapshot in the same development process. The -[Step 3 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../../../docs/roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns actual execution, completed reviews and verified fixes. This probe remains separate from P7's browser demo/Lighthouse and Phase 06's full Playwright Test/axe. @@ -221,6 +221,25 @@ It runs nine linked product pages and 27 cold Lighthouse audits over one unchang API/build/database, with real admission pacing and certificate-specific trust. Missing browser installation fails the proof rather than skipping it. +The hosted workflow bounds APT mirror acquisition with one retry and 15-second +HTTP/HTTPS timeouts in an exclusively created temporary configuration fragment. +It checks the effective settings as root without evaluation, then removes only +that fragment on shell exit. Sources, package verification, the complete +Playwright dependency set and the five-minute installation limit stay intact. +This is hosted setup handling, not a workstation prerequisite or a guarantee of +total setup duration. The actual workflow-shell controls live in +`frontend/apps/web/src/test/public-demo-ci.test.ts`. + +The workflow's outer setup/proof allowance ends at minute 17 from its first +step, reserving three minutes within the same 20-minute job ceiling. The native +proof and cleanup retain their separate 12-minute and 30-second caps. Sandbox +cleanup and workflow-receipt commands receive TERM after 15 seconds and KILL +after five more; artifact upload retains its one-minute step limit. The nominal +35 + 20 + 20 + 60-second tail leaves 45 seconds for runner/post overhead, not a +worst-case scheduling guarantee. A forced stop or unconfirmed cleanup fails. +This job restores the existing NuGet cache without a save post-hook; cache +misses still use ordinary dependency restoration. + On GitHub-hosted Linux runners, run `node scripts/ci-public-chromium.mjs prepare` after installation and before the lifecycle, then run `node scripts/ci-public-chromium.mjs cleanup` in an always-running cleanup step. @@ -242,7 +261,7 @@ screenshots. Proof and owned cleanup must both pass. Archive only this sanitized artifact directory; private configuration, certificates, keys, profiles and raw process logs are excluded. Existing artifacts must be moved aside before another run so stale evidence cannot pass. The -[P7 delivery record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) +[P7 delivery record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) owns local proof/review evidence; the packet's Step 4 record and [branch protection](../../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) own real CI receipts and required-check activation. Local success alone does not @@ -365,7 +384,7 @@ record and CONTRIBUTING; do not infer them from a local audit. applicable `jsx-a11y` rules and localized page-semantics checks, plus manual keyboard, focus, reflow, contrast and screen-reader evidence. Acceptance does not claim those controls pass; implementation records their actual results in - [Phase 02d](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-accepted-answers). + [Phase 02d](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-accepted-answers). ## Common pitfalls @@ -386,6 +405,6 @@ record and CONTRIBUTING; do not infer them from a local audit. standard does not prove implementation. Accepted P02d-6/G43 requires earlier failing lint/semantics controls and actual manual assistive-technology evidence; DOM assertions cannot substitute for a screen reader. Delivery is recorded in - [Phase 02d](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-accepted-answers). + [Phase 02d](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-accepted-answers). - **CI-only failures.** Usually a race or timing assumption. Use `--blame-hang` + `--blame-crash` locally. diff --git a/.claude/skills/seed-tenant/SKILL.md b/.claude/skills/seed-tenant/SKILL.md index a7e9f7f3..342f9969 100644 --- a/.claude/skills/seed-tenant/SKILL.md +++ b/.claude/skills/seed-tenant/SKILL.md @@ -13,17 +13,17 @@ description: > ## Purpose and current scope -The [P02d-2 accepted package](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) +The [P02d-2 accepted package](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-2-decision-package-2026-10-02) records the decisions. Step 4 delivers the complete inventory and contextual verification; both implementation review rounds and final verification passed. P02d-2 is merged, and P02d-4 supplies public API reads. The accepted -[P02b-3 package](../../../docs/roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13) +[P02b-3 package](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13) adds shared create-only defaults and the semantic built-in handoff; its -[Step 5 record](../../../docs/roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +[Step 5 record](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns current validation/review status. Server ingress/transport belongs to P02d-5; P02d-6 pages and P02d-7's shared foreground/CI demo are delivered. Step 3 supplies the narrow browser/Lighthouse proof; its -[delivery record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) +[delivery record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) owns local execution and reviews. The packet's Step 4 record owns real CI receipts and activation. Do not claim a rendered demo from seed alone. @@ -100,7 +100,7 @@ Fixed tenant, organization, host and authored curriculum IDs are preserved. P02b-3 discovers built-ins by semantic key/version and verifies their complete Active shape while retaining the stored ID; new built-ins mint owner UUIDv7 IDs. English's host remains tenant-wide; Yoga's host maps to Studio One. The exact -[accepted inventory](../../../docs/roadmap/phase-02d-walking-skeleton.md#seed-inventory-and-ownership) +[accepted inventory](../../../docs/roadmap/phase-02d-delivery-log.md#seed-inventory-and-ownership) and `SeedData` own the choices; this skill does not keep a second literal list. The inventory includes enabled/default locales, unchanged Active `card`/`plain`, @@ -189,7 +189,7 @@ demo-literal source fence across backend/frontend/scripts, dirty/clean controls the backend production-project Seeder-reference ban. The bounded schema-replacement companion checks data-driven behavior. These controls do not prove the absence of every possible computed-identity branch; the -[Step 2 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-2--genericity-and-exit-foundations-2026-10-11) +[Step 2 record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-2--genericity-and-exit-foundations-2026-10-11) owns their delivered scope and review evidence. ### 6. Reach the hosts @@ -244,9 +244,9 @@ phase's platform-feature decision; it cannot be hidden inside seed orchestration P02b-6 Step 1 declares development authentication personas in `SeedData.IdentityUsers` and exposes credential-free `--identity-manifest`; that mode opens no data source. Fresh Keycloak accounts come from the checked realm import. The accepted -[P02b-6 package](../../../docs/roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) +[P02b-6 package](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) owns the separate development reconciler, awaited by both combined seed/demo entries after application seed convergence. Its -[Step 4 record](../../../docs/roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) +[Step 4 record](../../../docs/roadmap/phase-02b-delivery-log.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) owns real account/API qualification and the completed independent reviews. Direct .NET seeding creates no provider account or application membership. diff --git a/.claude/skills/standards-check/SKILL.md b/.claude/skills/standards-check/SKILL.md index 46925f6d..380285c8 100644 --- a/.claude/skills/standards-check/SKILL.md +++ b/.claude/skills/standards-check/SKILL.md @@ -68,7 +68,7 @@ What does the diff touch? | `.md` under `docs/architecture/` | Architecture doc. | | `.md` under `docs/decisions/` | ADR. | | `.md` under `docs/standards/` | Standards doc. | -| `.md` under `docs/roadmap/` | Phase doc. | +| `.md` under `docs/roadmap/` | Phase doc (the plan), delivery log (`*-delivery-log.md`, dated packet records) or exit evidence index (`*-exit-evidence.md`) — [ADR-0069](../../../docs/decisions/0069-phase-documents-and-delivery-logs.md). | | `.md` at the root | CLAUDE.md / AGENTS.md / README.md / glossary. | | `infra/` | Operational infra (compose, Dapr components, APISIX). | | `.claude/skills/` | Skill catalogue. | @@ -407,6 +407,10 @@ checklist: - [ ] Architecture doc changed → cross-references to standards + ADRs refreshed. - [ ] Phase deliverable changed → `docs/roadmap/phase-NN-*.md` updated. +- [ ] Packet record written → a dated entry in the phase's delivery log, the + packet's Status row updated, and no status narrative added to the phase doc, + `CLAUDE.md`, the README or the roadmap index; `make docs-index` was run and + `make lint-docs` passes. - [ ] Module added / module spec changed → `docs/modules//audit.md` and `docs/modules//permissions.md` updated. - [ ] Frontend i18n key changed → `I18n:` commit trailer present. diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 9e17fea2..bb0dab56 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -29,7 +29,7 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule > the current `meta` name and `backend integration (Testcontainers)`. A fresh API > read verified all five check names and their GitHub Actions attribution, with > strict up-to-date checking and every other protection setting preserved. -> [P02d-1's delivery record](../docs/roadmap/phase-02d-walking-skeleton.md#step-3--packet-completion-2026-09-14) +> [P02d-1's delivery record](../docs/roadmap/phase-02d-delivery-log.md#step-3--packet-completion-2026-09-14) > carries the dated verification. - **Require a pull request before merging** @@ -58,8 +58,10 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule aggregates independently verify current-attempt job/API/artifact evidence, exact assigned case unions and complete TRX. Base retains normal Release build, format and Hangfire distribution/source/replacement gates. A filter - alone exits 0 when nothing matches. Use **Re-run all jobs**; successful - siblings from earlier attempts cannot satisfy the current aggregate. + alone exits 0 when nothing matches. Use **Re-run all jobs** while the PR + remains open; successful siblings from earlier attempts cannot satisfy + the current aggregate. Finish qualification before merging: a closed PR + may lose the API projection required for its aggregate identity. The [testing standard](../docs/standards/06-testing.md#complete-bounded-ci-assignments) owns assignment, authority and qualification requirements. All seven context names, GitHub Actions app binding and strict up-to-date checking @@ -69,7 +71,7 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule first-baseline proof. Its real PR run passed before activation. API read-back verifies all six GitHub Actions contexts, strict up-to-date checking and every other protection setting unchanged. The - [packet delivery record](../docs/roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) + [packet delivery record](../docs/roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) records the successful job and activation proof. - `public demo + lighthouse` — **required since P02d-7, 2026-10-11.** The first complete [real PR run](https://github.com/HodeTech/LearnStack/actions/runs/38106505383) @@ -77,9 +79,9 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule 27 audits and owned cleanup. Full API read-back confirms seven GitHub Actions contexts, strict up-to-date checking, all six previous contexts retained and every unrelated protection setting unchanged. The - [CI and exit closeout](../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) + [CI and exit closeout](../docs/roadmap/phase-02d-delivery-log.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) records execution, artifact validation and activation proof. - The separate [reviewed-head verification](../docs/roadmap/phase-02d-walking-skeleton.md#reviewed-implementation-head-verification-2026-10-11) + The separate [reviewed-head verification](../docs/roadmap/phase-02d-delivery-log.md#reviewed-implementation-head-verification-2026-10-11) identifies the exact implementation head inspected after activation; subsequent heads still require all seven passing checks. - P02d-5 keeps the existing check names. The frontend job uses the guarded @@ -98,7 +100,7 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule The fixture uses an isolated disposable profile and certificate-specific public-key trust. Its Flight-to-document navigation and fresh HMR admission scope does not deliver P7's browser demo, full Playwright/axe or Lighthouse. - The [Step 3 record](../docs/roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) + The [Step 3 record](../docs/roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns completed implementation, reviews and execution evidence. - P02d-7 replaces the disabled Lighthouse placeholder with the always-running `public demo + lighthouse` job under ADR-0056. It installs the locked browser @@ -109,11 +111,11 @@ Configure these in **GitHub → Settings → Branches → Branch protection rule sanitized receipts are uploaded; raw logs, profiles and private TLS/env files are excluded. The authorized seventh-context activation followed the complete successful real PR run on 2026-10-11. The - [Step 4 record](../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) + [Step 4 record](../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns the actual run and verified activation/read-back. GitHub matches required checks **by name**. The - [current CI and exit record](../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) + [current CI and exit record](../docs/roadmap/phase-02d-delivery-log.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) owns execution and dated API read-back; a workflow edit alone is not a protection-setting change. - **Require conversation resolution before merging**: on. diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5ed8185d..c677fc1a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -670,10 +670,10 @@ jobs: runs-on: ubuntu-latest timeout-minutes: 20 steps: - # Start before checkout. Reserve four minutes for the shared 30-second - # teardown, owned sandbox-policy cleanup and bounded receipt/artifact steps. + # Start before checkout. Reserve three minutes: 35s owner stop grace, + # 20s sandbox cleanup, 20s receipt, 60s upload and 45s runner/post margin. - name: Reserve demo cleanup and artifact time - run: echo "PUBLIC_DEMO_DEADLINE=$(( $(date +%s) + 16 * 60 ))" >> "$GITHUB_ENV" + run: echo "PUBLIC_DEMO_DEADLINE=$(( $(date +%s) + 17 * 60 ))" >> "$GITHUB_ENV" - name: Checkout timeout-minutes: 2 @@ -702,7 +702,7 @@ jobs: - name: Cache NuGet packages timeout-minutes: 1 - uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 + uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830 # v4 with: path: ~/.nuget/packages key: nuget-${{ runner.os }}-${{ hashFiles('backend/**/*.csproj', 'backend/Directory.Packages.props') }} @@ -714,7 +714,10 @@ jobs: working-directory: frontend run: | pnpm install --frozen-lockfile - pnpm exec playwright install --with-deps chromium + # The hosted image already carries every Chromium shared library. + # --with-deps only added CJK/Thai/X fonts through the runner's APT + # mirror, whose slow downloads repeatedly exhausted this budget. + pnpm exec playwright install chromium - name: Prepare sandbox-enabled managed Chromium timeout-minutes: 1 @@ -741,7 +744,7 @@ jobs: - name: Remove only the owned Chromium sandbox profile if: always() timeout-minutes: 1 - run: node scripts/ci-public-chromium.mjs cleanup + run: timeout --signal=TERM --kill-after=5s 15s node scripts/ci-public-chromium.mjs cleanup - name: Record bounded workflow outcome if: always() @@ -752,7 +755,7 @@ jobs: SOURCE_HEAD_SHA: ${{ github.event.pull_request.head.sha }} RUN_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} run: | - python3 - <<'PY' + timeout --signal=TERM --kill-after=5s 15s python3 - <<'PY' import json, os from pathlib import Path output = Path('artifacts/public-demo-ci') @@ -880,12 +883,12 @@ jobs: # Template values from `github.event.*` are passed through `env:` so # they expand into shell variables AT THE SHELL'S quoting boundary, # never as raw substitution inside the `run:` block. This is the - # GHA-documented script-injection defense — even though `base.ref` - # and `before` are not user-controlled here, defense-in-depth keeps + # GHA-documented script-injection defense — even though the event commit + # IDs are not user-controlled here, defense-in-depth keeps # the pattern consistent across every step that consumes context. env: EVENT_NAME: ${{ github.event_name }} - PR_BASE_REF: ${{ github.event.pull_request.base.ref }} + PR_BASE_SHA: ${{ github.event.pull_request.base.sha }} PUSH_BEFORE_SHA: ${{ github.event.before }} run: | # Walk every relative-path link in the changed Markdown files of @@ -897,8 +900,9 @@ jobs: # [x](docs/foo.md) — bare repo-relative (CLAUDE.md convention) # Anchors (#frag) are stripped before the file-existence check. if [[ "$EVENT_NAME" == "pull_request" ]]; then - base="origin/${PR_BASE_REF}" - git fetch --no-tags --depth=1 origin "${PR_BASE_REF}" + # A rerun keeps its original event even after a squash merge. + # Compare that immutable base, not the base branch's later tip. + base="${PR_BASE_SHA}" else base="${PUSH_BEFORE_SHA}" fi @@ -914,7 +918,8 @@ jobs: base="" fi if [[ -n "$base" ]]; then - changed=$(git diff --name-only "$base"...HEAD -- '*.md') + # Link existence compares snapshots; it needs no merge base. + changed=$(git diff --name-only "$base" HEAD -- '*.md') else changed=$(git ls-files -- '*.md') fi @@ -954,8 +959,11 @@ jobs: # `NNNN-related.md` placeholders and ADR-0041's erratum shape. # Working around it in the documents made both templates worse # at being templates, which is the sign the check was the thing - # that was wrong. + # that was wrong. Code spans are stripped for the same reason: + # `[x](y)` between backticks is sample text too (ADR-0069 names + # the link shapes its fragment audit reads that way). done < <(awk '/^[[:space:]]*```/ { fence = !fence; next } !fence' "$f" \ + | sed -E 's/`[^`]*`//g' \ | grep -oE '\]\(([^)#][^)]*)\)' \ | sed -E 's/^\]\((.+)\)$/\1/') done <<< "$changed" @@ -964,6 +972,37 @@ jobs: exit 1 fi + - name: Markdown link audit regression controls + timeout-minutes: 1 + run: python3 scripts/test-markdown-link-audit.py + + - name: Markdown fragment audit (whole tree) + # ADR-0069: the step above strips `#fragment` and reads changed files only, so a + # renamed or moved heading broke every link into it silently. This resolves + # every fragment link in the tree, since an edit in one file breaks links in + # files the change never touched. + timeout-minutes: 1 + run: python3 scripts/markdown-fragment-audit.py + + - name: Roadmap structure (plan, delivery log, status carriers) + # ADR-0069: a phase document holds the plan, its delivery log the dated + # records, and packet status lives once. + timeout-minutes: 1 + run: python3 scripts/roadmap-structure.py + + - name: Delivery log indexes are current + # ADR-0069, 2026-10-23: each delivery log opens with an index generated from + # its headings; a stale or hand-edited one fails here. Fix: `make docs-index`. + timeout-minutes: 1 + run: python3 scripts/delivery-log-index.py + + - name: Documentation guard controls + timeout-minutes: 1 + run: | + python3 scripts/test-markdown-fragment-audit.py + python3 scripts/test-roadmap-structure.py + python3 scripts/test-delivery-log-index.py + - name: ADR lifecycle parser controls run: python3 scripts/test-adr-status.py diff --git a/CLAUDE.md b/CLAUDE.md index 518c6fdd..34e6ef61 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -39,470 +39,38 @@ repository holds only LearnStack's side of the boundary, in ## What state this is in -**Phase 01 and [Phase 02a](docs/roadmap/phase-02a-kernel-tenancy.md) complete — -every packet 0–10 shipped; packets 3b–10 were re-scoped on 2026-08-08 -after a four-report audit of the corpus. -[Packet 9](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-9) — -audit infrastructure and the entitlement socket, decided by -[ADR-0044](docs/decisions/0044-audit-write-path.md) and -[ADR-0045](docs/decisions/0045-entitlement-and-feature-flag-socket.md) — shipped the -lit audit write path, the `audit` health check, and the entitlement socket: -`IEntitlementProvider` with `NullEntitlementProvider` registered in every deployment -mode, `IFeatureFlags` composing over it, the three typed key registries, and -`platform_killswitches` **read-only** — every toggle runs inside -`EnterPlatformAdminScope`, whose gate refuses everyone until -[Phase 03](docs/roadmap/phase-03-identity-admin.md) brings the Platform-scope -permission. -[Packet 10](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-10) closed -the phase against its own exit decision: thirty catalogue entries name it as the packet -that implemented them — module boundaries in all four legs, domain genericity across names, -schema, slugs, keys and the frontend tree, the port and entitlement-key bans, ADR-0040's -two behavioural properties, and three named isolation proofs as `learnstack_app`. The -standards were re-stated against enforcement at Packet 10 closeout (nineteen -`Active`, three `Adopted`), and four guards now hold the corpus to its own claims, -so a status header, a -catalogue entry, a published count or a planted `Skip` fails the build rather than a -reader. The whole .NET suite runs with **zero skips**, which the runner now refuses to -let change. -**[Phase 02d](docs/roadmap/phase-02d-walking-skeleton.md) is complete and merged** -through PR #28 on 2026-10-11. Its kickoff -shipped the packet table and the decision register, and every later packet opens with -its decision pass. **P02d-1 is complete and merged** through -[PR #22](https://github.com/HodeTech/LearnStack/pull/22) on 2026-09-14. Education's -domain, schema and isolation proofs pass; all three steps completed two independent -agent review rounds. The [merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#merge-and-closeout-2026-09-14) -records verification of the final PR head and merge commit. **P02d-2's decision pass -is Accepted — 2026-10-02**: its [decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) -and ADR-0050/0051 establish protected content, exact write contracts and four -implementation steps. Implementation resumed on development: Step 1 supplies the -access-policy migration, exact-definition/locale contracts, presentation validation -and contextual seed verification queries; both review rounds passed. Step 2 adds -locale/branding writers and whole-value setting audit redaction; both review rounds -passed. -Step 3 adds Education writers; both review rounds and a fresh focused fix review -passed. Step 4 completes convergent seed execution after both review rounds. -**P02d-2 is complete and merged** through -[PR #23](https://github.com/HodeTech/LearnStack/pull/23) on 2026-10-02; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-2-merge-and-closeout-2026-10-02) -records the accepted head and merge verification. P02d-3 read internals are implemented; -its [decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) -is Accepted — 2026-10-02. Step 1 implements typed settings and locale resolution; -both review rounds passed. Step 2 implements batched definition reads; both review -rounds passed. Step 3 -adds generation caching and scope-safe bypass; both review rounds passed. -**P02d-3 is complete and merged** through -[PR #24](https://github.com/HodeTech/LearnStack/pull/24) on 2026-10-03; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-3-merge-and-closeout-2026-10-03) -records final verification. Public reads stay with P02d-4. -Its [decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) -and ADR-0052 are Accepted — 2026-10-03. The approved four-step implementation and -two-round review loop run on development; delivery evidence is recorded per step. -Step 1 implements immutable host provenance and physical read-only transactions; -both review rounds and the focused fix review pass. Step 2 implements live site -configuration and GET/HEAD with no-store; both review rounds and focused fix -verification pass. Step 3 implements Education GET/HEAD reads, exact-locale -marketing/content projections and scoped seek cursors; both independent review -rounds pass. Step 4 implements served/snapshot contract controls, the injected typed -SDK and always-running OpenAPI compatibility CI. Both independent review rounds -and fresh fix verification pass. All six real CI jobs pass; the approved sixth -required check is active with all other live settings preserved. **P02d-4 is complete -and merged** through [PR #25](https://github.com/HodeTech/LearnStack/pull/25) on -2026-10-08; its [merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-4-merge-and-closeout-2026-10-08) -records final verification. P02d-5 delivers trusted public server rendering under -Accepted ADR-0053 and ADR-0054: native HTTPS ingress, coordinated visitor/peer -admission, the configured bounded server caller, live-host/locale entry and -source/runtime proof controls. The [remediation and closeout record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) -owns implementation steps, independent reviews and validation. **P02d-5 is complete -and merged** through [PR #26](https://github.com/HodeTech/LearnStack/pull/26) on -2026-10-09. Its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) -records final verification. -Work stays on development. **P02d-6's decision pass is Accepted — 2026-10-09**: -[ADR-0027](docs/decisions/0027-frontend-i18n.md) and its -[decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) -authorize four implementation steps and two independent review rounds per step. -Step 1 implements the pinned i18n and document foundation, verified request-local -admission/content loaders, atomic color theming, chrome and controlled status/error/ -loading components. Its -[delivery record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) -owns its validation and review evidence. Step 2 adds actual catalog/course pages, -independent pagination and metadata from the shared resource loader. Its -[delivery record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-2-catalog-and-course-pages) -owns current verification and review status. Step 3 adds the ordered plain-text -lesson page, eligible lesson metadata and 31 blocking JSX accessibility rules -with actual-config planted controls. Its -[delivery record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-3-ordered-lesson-presentation) -owns verification and review status. Step 4 adds concurrent host/locale, theme, -freshness and content-fault product proofs; its -[delivery record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) -records both completed review rounds. **P02d-6 is complete and merged** through -[PR #27](https://github.com/HodeTech/LearnStack/pull/27) on 2026-10-10; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) -records final verification. The -[packet closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) -records passing manual browser checks and the maintainer's VoiceOver smoke. -ADR-0055 remediation delivers -single-bootstrap admission and passing production replacement proofs. All three -steps completed both independent review rounds; -the [Step 3 record](docs/roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) -owns completed Step 3 reviews, verified fixes and delivery evidence. The five new -catalogue rules are Implemented. -P02d-7's demo, Lighthouse and phase-exit -[decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-decision-package-2026-10-10) -was approved on 2026-10-11, including bounded seventh-check activation after real -success. ADR-0056 was accepted on the same date. Steps 1 and 2 completed both -independent review rounds; the -[Step 3 record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) -owns browser/audit implementation, passing complete local reruns and both -completed Step 3 review rounds. The -[Step 4 record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) -owns CI enforcement, completed reviews and individual exit reconciliation. Its -[CI and exit closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) -verifies all seven real PR jobs, complete artifacts and live seventh-check -activation with all other protection settings preserved. All four steps completed -both review rounds. [PR #28](https://github.com/HodeTech/LearnStack/pull/28) is merged; -the [merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) -owns final verification. P02b-0's -[entry audit](docs/roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) -is complete; P02b-1's [producer decision package](docs/roadmap/phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12) -and ADR-0057 are Accepted — 2026-10-12. The four implementation steps are -authorized. Step 1 implements the shared snapshot/producer/audit lifecycle; its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) -records passing verification and both completed independent review rounds. -Step 2 implements immediate outbox production; its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-1-step-2--immediate-outbox-production-2026-10-12) -records passing verification and both completed review rounds. -Step 3 implements successful-save collection, owner-only completion and the -completed-provisioning publisher; its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) -records passing verification and both completed review rounds. Step 4 adds -production-census guards and catalogue enforcement; its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) -records passing full backend verification and both completed review rounds. -**P02b-1 is complete and merged** through -[PR #29](https://github.com/HodeTech/LearnStack/pull/29) on 2026-10-12. The -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-1-merge-and-closeout-2026-10-12) -owns final verification. **P02b-2's revised decision package and ADR-0046 are -Accepted — 2026-10-12.** The four implementation steps and two independent review -rounds per step are authorized on development. The -[Step 1 record](docs/roadmap/phase-02b-events-auth.md#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) -records both completed Step 1 reviews. Step 2 implements fenced transitions and -row-bound terminal MUST audit; both independent review rounds pass. -Step 3 implements hosted execution and observation; its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) -owns verification and both completed review rounds. Step 4 enforcement and local -closeout are complete; all four steps completed both independent review rounds. -**P02b-2 is complete and merged** through -[PR #30](https://github.com/HodeTech/LearnStack/pull/30) on 2026-10-13. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) -owns final source/merge verification and CI evidence. -Acceptance registers six new catalogue rules; the Step 4 record owns their -delivery evidence. P02b-2 claims no inbox or subscriber delivery. P02b-3's -[decision package](docs/roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13) -is Accepted — 2026-10-13. Six implementation steps, each with commit and two -independent review rounds, deliver durable acceptance, shared inbox/ledger, -independent retries, both real defaults and Seeder handoff. Implementation is -complete and merged through PR #31 on 2026-10-15. Step 1 implements shared -storage and privilege proofs; both independent review rounds are complete. Its -[delivery record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-1--shared-storage-and-privileges-2026-10-13) -owns verification and review status. Step 2 implements durable acceptance and -inbox primitives; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-2--durable-acceptance-and-inbox-primitives-2026-10-13) -owns validation and both completed review rounds. Step 3 implements the closed -business owner and completion gate; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-3--business-owner-and-completion-gate-2026-10-13) -owns validation and both completed review rounds. Step 4 adds independent -subscriber scheduling, terminal audit, replay and bounded observation; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13) -owns validation and both completed review rounds. Step 5 implements useful -defaults and semantic seed handoff; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) -owns validation and both completed independent review rounds. Both real default -subscriptions are Active. Step 6 implements production-census enforcement and -full packet closeout; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) -owns completed validation/review receipts and PR/CI handoff. All six steps -completed both independent review rounds. The -[external review follow-up](docs/roadmap/phase-02b-events-auth.md#p02b-3-external-review-follow-up-2026-10-15) -records verified corrections and two further independent review rounds; the -[second follow-up](docs/roadmap/phase-02b-events-auth.md#p02b-3-second-external-review-follow-up-2026-10-15) -records subsequent runtime/proof corrections and their completed reviews. The -[P02b-3 merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) -owns final source/merge and CI verification. -**P02b-4 is complete and merged** through -[PR #32](https://github.com/HodeTech/LearnStack/pull/32) on 2026-10-19. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) -records all nine job-runtime steps, three CI steps, independent reviews and both -complete final-source hosted assignments. Production business and recurrence -definitions remain empty. **P02b-5's decision package and ADR-0064 are Accepted -— 2026-10-19**; their -[decision pass](docs/roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19) -authorizes five implementation steps, each with commit and two fresh independent -review rounds. Step 1 completes acceptance disclosures and the isolated token -foundation after both independent review rounds; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-5-step-1--token-foundation-2026-10-19) -owns the verified metric-privacy correction. Step 2 completes the real read-only -subject after both independent review rounds; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-5-step-2--real-read-only-application-subject-2026-10-19) -owns validation. Step 3 completes attributed reconciliation and subject admission -after both independent reviews; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-5-step-3--attributed-reconciliation-and-subject-admission-2026-10-19) -owns verified log-emission and default-window test corrections. Step 4 installs -the complete HTTP boundary and typed contract after both review rounds; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) -owns validation and completed reviews. Step 5 completes production enforcement -and both independent review rounds; its -[local closeout](docs/roadmap/phase-02b-events-auth.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) -separates source-bound CI receipts from live PR-head qualification and merge. -All five steps are complete. A subsequent -[review remediation](docs/roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) -verifies external findings. ADR-0065 is Accepted on 2026-10-20 after maintainer -review. Its implementation and local proofs are delivered; the remediation -record retains completed independent correction reviews and pre-merge receipts. -BFF sessions and phase exit remain P02b-7–8; P02b-6's current record follows below. -The [second external-review follow-up](docs/roadmap/phase-02b-events-auth.md#p02b-5-second-external-review-follow-up-2026-10-20) -owns subsequent runtime/proof corrections and their source-bound reviews. -[ADR-0066](docs/decisions/0066-bounded-tenant-subject-admission.md) is Accepted — -2026-10-20. Its retained-subject bound, cleanup ownership and closed fault/refusal -signals are implemented with local runtime/exported proofs. The -[implementation record](docs/roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) -retains source-bound validation and independent reviews; the merge closeout below -owns final-source qualification. -The [systematic correction record](docs/roadmap/phase-02b-events-auth.md#p02b-5-systematic-proof-and-document-corrections-2026-10-20) -owns subsequent proof/diagnostic, document and measured CI timing reconciliation; -all three correction steps and both independent review rounds are complete. -**P02b-5 is complete and merged** through -[PR #33](https://github.com/HodeTech/LearnStack/pull/33) on 2026-10-20. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) -owns exact final-head CI, unchanged-plan A/B qualification and identical merge -trees. P02b-6's realm/TTL -[decision pass](docs/roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) -is Accepted — 2026-10-21. The maintainer approved the package at `6d75e532` -and its four implementation steps. G12's realm/reconciliation/callback choices -and G13's issuance-TTL part are Accepted; G13's session part stays Open. -The dedicated issuance follow-up, -[ADR-0067](docs/decisions/0067-development-tenant-access-token-issuance.md), is -Accepted — 2026-10-21 after separate maintainer approval. It formalizes the -existing issuance choice without changing runtime or G13's Open session portion. -P02b-6 Step 1 is complete locally after both review rounds; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-1--executable-realm-and-identity-declaration-2026-10-21) -owns implementation, fresh-provider qualification and review status. -P02b-6 Step 2 is complete locally after both review rounds and fresh fix -reviews; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-2--owned-warm-realm-reconciliation-2026-10-21) -owns the Accepted server-information response allowance and current proofs. -Step 3 is complete locally after both review rounds and fresh correction -verification; its -[record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21) -owns actual seed/demo and cancellation evidence. Step 4's -[record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) -owns completed local implementation/reviews and source-bound qualification receipts. -The correction record below owns source-bound hosted qualification; merge is -separate. -All four implementation steps and their recorded correction reviews are complete -locally. The subsequent systematic correction pass retains its own review and -current-head hosted qualification gates in the -[correction record](docs/roadmap/phase-02b-events-auth.md#p02b-6-systematic-corrections-and-hosted-qualification-2026-10-21). -PR review and merge remain separate. -The [additional correction record](docs/roadmap/phase-02b-events-auth.md#p02b-6-additional-verification-and-correction-pass-2026-10-22) -owns the current verified findings. -[ADR-0068](docs/decisions/0068-development-warm-realm-qualification.md) -is Accepted — 2026-10-22 under the maintainer's conditional approval after verified -review corrections. Its first correction step is complete locally after both -review rounds; the [stock qualification record](docs/roadmap/phase-02b-events-auth.md#adr-0068-step-1--qualified-stock-assignment-implementation-2026-10-22) -owns evidence. Its [second correction step](docs/roadmap/phase-02b-events-auth.md#adr-0068-step-2--owned-visibility-preparation-2026-10-22) -completes owned preparation and fresh complete planning after both independent -review rounds. Its [third correction step](docs/roadmap/phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) -completes local historical entry, credential/MFA, signed API and self-service -proof after both independent review rounds. That record owns exact source-bound -hosted assignments and their evidence limits; merge remains separate. -P02b-7–8 remain pending; -Phase 02b remains in progress. -Phase 06 retains the full +**Phase 01, Phase 02a and Phase 02d are complete; Phase 02b is the live phase.** +[Phase 02d](docs/roadmap/phase-02d-walking-skeleton.md), the two-tenant walking +skeleton and the first user-visible milestone, merged through PR #28 on +2026-10-11: two hosts, two tenants, two education sites, one binary and one +database. In [Phase 02b](docs/roadmap/phase-02b-events-auth.md), P02b-0 through +P02b-5 are complete and P02b-1–5 merged through PRs #29–#33 — transactional event +production, durable dispatch, subscriber delivery, background jobs and tenant API +authentication — and P02b-6's realm and identity implementation is merged through +PR #34, with post-merge CI corrections continuing on `development`. P02b-7 (BFF +session) and P02b-8 (exit enforcement) are pending, and G13's session part stays +Open, so browser sign-in is not implemented. Phase 06 retains the full renderer/Studio expansion. -**Phase 01** shipped the .NET 10 solution scaffold under `backend/` -(core + 7 modules × 4 projects + 4 test projects including the -non-skippable `LearnStack.Tests.Architecture`), the `pnpm` frontend -monorepo under `frontend/` (`apps/web` Next.js App Router + -`packages/{config,ui,sdk}`), the local-dev compose stack at -`infra/compose/dev.yml`, and the DX + CI surround (repo-root `Makefile`, -`.env.example` single source of truth, `.githooks/pre-commit` formatter + -Leakwatch, `infra/compose/e2e.yml` ephemeral overlay, -`.github/workflows/ci.yml` with backend + frontend + meta + secret-scan -required checks, `scripts/seed.sh`). - -**Phase 02a packets 0–3** shipped the decision set (Vogen, API -versioning, audit partition management), the shared kernel core -(`Result` + `LocalizedMessage`, `Entity` / `AuditableEntity`, -domain events, cursor pagination, `IClock` / `IRandom` / `IGuidFactory`), -and the [ADR-0032](docs/decisions/0032-exception-handling-logging-and-observability.md) -cross-cutting foundation (L1 `IExceptionHandler`, the eight-step MediatR -pipeline, Serilog → OTLP, `TenantContextSpanProcessor`, -`IErrorTrackingProvider`, `IProviderResilience`, the `LS0001` -analyzer). Those records are frozen delivery history. - -**Packet 3b** repaired what the audit found before the first consumer -existed: `Results.Unit` renamed to `None`, `Entity` given one typed -equality body and `IStronglyTypedId` an `IsInitialized()`, the corpus's -non-compiling examples and mis-prefixed localization keys corrected, and -the Phase 01 development loop made to work — `make seed` exits 0, the e2e -overlay boots, and compose ports bind loopback. Its record is -[Delivery Record (Packet 3b)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-3b), -kept separate from the frozen packets 0–3 record. - -**Packet 4** shipped the API conventions: `/api/v{N}` routing with startup -guards for the escapes a route rule cannot see, one RFC 7807 shape on every -error including the three the framework used to produce without one, cursor -pagination and the sort grammar, the -[ADR-0036](docs/decisions/0036-tenant-resolution-trusted-inputs.md) tenancy -edge (host normalization, the trusted hop, headers as assertions, the anonymous -rate limiter, a required `Deployment:Mode`), idempotency keys and ETag -concurrency under -[ADR-0037](docs/decisions/0037-idempotency-key-contract.md), a request-body -limit that a test can actually assert, the first working SDK generation, and -the OpenAPI mapping for strongly-typed identifiers that ADR-0023 had assigned -to it. Its record — -[Delivery Record (Packet 4)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-4) -— lists the six defects the packet introduced and caught in its own review -rounds alongside what it built, because most of them answered a **success** the -client had no way to question — and the two that did not were worse: one handed -back a truncated body under a `200`, the other a `500` per request that an -anonymous caller could trigger at will. - -**Packet 5** shipped the foundation ports with the implementations that -actually run today — `ICacheService` / `InMemoryCacheService`, `IEventBus` / -`InProcessEventBus`, and Packet 3's `ISecretProvider` / -`ConfigurationSecretProvider` — each selected at a single composition-root site -so Phase 11's adapter is one line rather than a search. With them: `CacheKey` -and `EnsureValid`, because there is no query filter and no RLS policy in front -of a dictionary, so the key *is* the isolation boundary; the -[ADR-0038](docs/decisions/0038-cross-cutting-port-and-event-contracts.md) port -and event contracts, including `IntegrationEventEnvelope` and the non-generic -`PublishAsync`; and the compose `gated` profile that took Kafka, Valkey, Vault, -APISIX and the two Dapr containers out of `make dev`. `IHostToTenantResolver` -and `IEntitlementProvider` are **not** here — they need the tenancy schema and -belong to Packets 7 and 9. Its record, -[Delivery Record (Packet 5)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-5), -is long because several of its defects were introduced by the *fix* for an -earlier one, and because three tests were caught agreeing with the code instead -of constraining it — the packet's most repeated lesson. - -**Packet 7** shipped what a request does with a tenant: host classification and -resolution, `EffectiveHost` normalization, the negative host cache, the -four-origin `TenantContextFactory`, and `TenantContextBehavior`'s two-gate -authority ceiling with `[AllowsUnresolvedTenantContext]` and `[PublicSurface]` as -enumerated holes. With them: `ProvisionTenantCommand`, the one operation -[ADR-0042](docs/decisions/0042-tenant-provisioning-cross-aggregate-transaction.md) -sanctions to write two aggregate roots on one transaction; `CreateOrganizationCommand` -and `MapHostToTenantCommand`, both taking their tenant from the context and never -from the request; `LearnStack.Tools.Seeder` and the two seed tenants -(`demo-english`, `demo-yoga`) written through those commands, so `make seed` exercises -the request path rather than a second one; and the request-level isolation suite — -the first fixture pairing the real middleware chain with a real database. Its record, -[Delivery Record (Packet 7)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-7), -is long for the reason Packets 5 and 6's were: eleven steps, each reviewed twice, -and the second round repeatedly found the first round's fix. The sharpest finding -was a test that asserted an anonymous POST failed and therefore passed against a -deleted endpoint. - -**Packet 6** shipped the tenancy schema: the four database roles, ten tables in -two independent migration chains, and every one of them under `ENABLE` **and** -`FORCE ROW LEVEL SECURITY` with the corrected -[ADR-0003 Amendment 3](docs/decisions/0003-tenant-isolation-defense-in-depth.md) -template — one `AND`-ed policy per table, in the four table classes. With them: -`TenantId` / `OrganizationId` as Vogen value objects, the `Tenant` and -`Organization` aggregates, the repository's first module spec at -[docs/modules/tenancy/](docs/modules/tenancy/README.md), and -[ADR-0040](docs/decisions/0040-ambient-unit-of-work.md)'s ambient unit of work — -one connection per scope, every module `DbContext` enlisted on it, and -`TransactionBehavior`'s body replacing the Packet 3 shell. Its record, -[Delivery Record (Packet 6)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-6), -is long for the reason Packet 5's was: the packet's own review rounds found that -`make migrate` could not apply the migration the packet exists to ship, that a -structural sweep is only as wide as the schema it runs on — a second permissive -policy on `outbox_messages` passed the whole suite — and that the transaction -boundary was wrong in the two places it is hardest to see. - -**Packet 8** shipped the Tenant Customization foundation — the module that makes -the genericity claim true. Two aggregates a tenant declares as data, -`TenantContentType` and `TenantLevelTaxonomy`; the payload gate -[ADR-0043](docs/decisions/0043-customization-payload-validation.md) decides, with -`JsonSchema.Net` pinned behind `IJsonSchemaValidator` and four ordered gates a -tenant document passes before a row is written; four tables in a third migration -chain under the corrected RLS template; four commands and the generation counter -that every cache key will embed; and a built-in seed so a tenant that has authored -nothing still has something to render. Its record, -[Delivery Record (Packet 8)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-8), -is long for the reason Packets 5, 6 and 7's were: the defects are its own review -rounds' findings, and the sharpest was a term added by one round that the next -round found had no test — removing it left all 1390 cases green. - -**Packet 9** shipped the audit write path and the entitlement socket. Audit first, -because everything else commits through it: the `audit_log` / `audit_config` schema -with its three append-only layers, the change-tracker capture, `PostgresAuditStore`'s -four writes, the merged `IAuditCatalog`, and the two pipeline steps that use them — -`AuditLogBehavior` classifies and parks intents at step 3 and reconciles in its -`finally`, `TransactionBehavior` flushes the MUST-class rows on the owning frame -immediately before `COMMIT`. With them the observable half of the fail-closed rule -([ADR-0033 Amendment 3](docs/decisions/0033-audit-durability-model.md)): the `audit` -health check, two counters and a `Critical` line. Two non-pipeline writers land too — -`PlatformAdminScope.EnterAsync` records its own `security-event` row before the -operation runs, and `AuditingTenantAssertionRecorder` audits a rejected tenant -assertion per occurrence when a principal is attached and as a **burst** when none is. -Then the socket [ADR-0045](docs/decisions/0045-entitlement-and-feature-flag-socket.md) -decides: `IEntitlementProvider` with `NullEntitlementProvider` registered in every -deployment mode, `IFeatureFlags` composing over the port rather than reading -`platform_entitlement_cache`, the three typed key registries carrying the Hub's own -spellings, and `platform_killswitches` with its policies, its overlay and its cache -family — and **no writer**, because every toggle runs inside a scope whose gate refuses -everyone. Its record, -[Delivery Record (Packet 9)](docs/roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-9), -carries something the earlier ones did not: four **decisions**, because three of them -are readings of an Accepted ADR rather than applications of it — and a reading inferred -from a diff is one nobody can disagree with later. The lesson the rounds kept -repeating was narrower than Packet 8's and sharper: a rule that cannot tell *clean* -from *blind*. Three separate guards passed because nothing in the repository violated -them and their mechanism was never exercised; each now ships with a companion that -proves it can fail. - -**The 2026-08-08 restructure** re-scoped packets 3b–10 along three lines, -all recorded in the Phase 02a Status block: - -- *Correctness moved earlier.* The Row Level Security template that four - documents carried produced two **permissive** policies, which - PostgreSQL combines with `OR` — leaking every tenant-wide row across - tenants. [ADR-0003 Amendment 3](docs/decisions/0003-tenant-isolation-defense-in-depth.md) - corrects it, and [ADR-0033](docs/decisions/0033-audit-durability-model.md) - makes MUST-class audit a durable intent inside the business - transaction — which is also what stops the corrected policy from - rejecting every audit insert. -- *Additive infrastructure moved later.* Per - [ADR-0035](docs/decisions/0035-demand-gated-infrastructure.md), Packet 5 - ships the foundation **ports and their default implementations**; the - Dapr, Kafka, APISIX and Vault adapters land in - [Phase 11](docs/roadmap/phase-11-production-hardening.md) against - written triggers. -- *Proof moved earlier.* Two seed tenants in unrelated domains land in - Packet 7, and [Phase 02d](docs/roadmap/phase-02d-walking-skeleton.md) - renders both of them in a browser. - -**[Phase 02d: Two-Tenant Walking Skeleton](docs/roadmap/phase-02d-walking-skeleton.md) -is the first delivered user-visible milestone** — the first phase whose output -someone who does not read C# can evaluate: two hosts, two tenants, two -education sites, one binary and one database. - -**Four modules hold domain code**, as of P02d-1 Step 2: Tenancy — the `Tenant` -and `Organization` aggregates and `TenancyDbContext`; Customization — -`TenantContentType`, `TenantLevelTaxonomy`, their generation counter and -`CustomizationDbContext`; Audit — `AuditEntry`, `AuditConfig` and `AuditDbContext`; -and Education — separate `Course` and `Lesson` roots, their contained translations -and `EducationDbContext`. Content, Identity and Media remain scaffolded. -P02d-1 is merged; its implementation, agent reviews and required PR checks are complete. -P02d-2 supplies unrouted authoring commands and seeded content; public reads belong -to P02d-4. Other module-level references -in the docs (e.g. `ILiveClassProvider`, `ITenantSearch`) still describe intended -shape owned by their named phases. +**Status lives in one place.** Each phase document's Status block owns packet +state and its decision register owns gate state; the phase's delivery log +(`docs/roadmap/phase--delivery-log.md`) owns the dated decision packages, step +records, reviews and closeouts +([ADR-0069](docs/decisions/0069-phase-documents-and-delivery-logs.md)). This +section stays a pointer: it links phase documents, never a delivery log, and does +not restate a packet's history. + +**What the kernel already guarantees** — tenancy and Row Level Security +isolation, the audit write path, the entitlement socket, the API conventions and +the foundation ports — is recorded packet by packet in +[Phase 02a](docs/roadmap/phase-02a-kernel-tenancy.md), whose delivery records are +frozen history, together with the 2026-08-08 restructure that moved correctness +earlier, additive infrastructure later and proof earlier. + +**Four modules hold domain code:** Tenancy, Customization, Audit and Education. +Content, Identity and Media remain scaffolded. Module-level references in the docs +to types such as `ILiveClassProvider` or `ITenantSearch` describe intended shape +owned by their named phases. ## Where to start @@ -517,38 +85,17 @@ For any task, read in this order: Then read the phase that is live and the one it stands on: -- [docs/roadmap/phase-02b-events-auth.md](docs/roadmap/phase-02b-events-auth.md) - — **the live phase**. P02b-0 entry verification is complete; P02b-1 is complete - and merged through PR #29 on 2026-10-12. Its four steps deliver the producer - runtime and production-census enforcement. P02b-2's revised package/ADR-0046 are - Accepted. Steps 1–2 completed both review rounds; Step 3 implements hosted - dispatch and observation, with both independent review rounds complete. Step 4 - enforcement and local closeout are complete; all four steps completed both - independent review rounds. P02b-2 is complete and merged through PR #30 on - 2026-10-13; its merge closeout above owns final verification. P02b-3 is complete - and merged through PR #31 on 2026-10-15; all six steps and correction bundles - completed both review rounds. Its merge closeout above owns final verification. - P02b-4 is complete and merged through PR #32 on 2026-10-19; its merge closeout - above owns final verification. P02b-5's decision package and ADR-0064 are Accepted; - all five implementation steps and correction reviews are complete and merged - through PR #33 on 2026-10-20. Its merge closeout above owns verification. - P02b-6's realm/TTL decision package and four-step plan above are Accepted — - 2026-10-21. Its [Step 1 record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-1--executable-realm-and-identity-declaration-2026-10-21) - owns the executable fresh import and provider proofs. Step 2's record above - owns the completed local reconciler and Accepted response-budget decision; - Step 3 is complete locally after both review rounds and fresh corrections; - its record above owns actual lifecycle evidence. Step 4's record above owns - local implementation and source-bound qualification receipts; the correction - record above owns final hosted qualification and its evidence limits. - P02b-7–8 retain their - own decision passes; G13's session part stays Open. -- [docs/roadmap/phase-02d-walking-skeleton.md](docs/roadmap/phase-02d-walking-skeleton.md) - — complete and merged; the delivered public-site baseline and P02b-0 handoff. - `02d` sorts after `02b`/`02c` but runs **before** them; the roadmap dependency - map is authoritative for order, filename order is not. -- [docs/roadmap/phase-02a-kernel-tenancy.md](docs/roadmap/phase-02a-kernel-tenancy.md) - — complete, with a dated Status block and a delivery record per packet. It is - the authority on what the kernel already guarantees, not on what to build next. +- [docs/roadmap/phase-02b-events-auth.md](docs/roadmap/phase-02b-events-auth.md) — + **the live phase**. Its Status block owns packet state; its decision register owns + gate state and links each Accepted decision package in the delivery log, which is + normative — read it before writing the code its gate governs. Navigate a delivery + log by the generated index at its top; never read the whole file. +- [docs/roadmap/phase-02d-walking-skeleton.md](docs/roadmap/phase-02d-walking-skeleton.md) — + complete; the delivered public-site baseline. It sorts after `02b`/`02c` but runs + **before** them: the roadmap dependency map, not filename order, is authoritative. +- [docs/roadmap/phase-02a-kernel-tenancy.md](docs/roadmap/phase-02a-kernel-tenancy.md) — + complete; the authority on what the kernel already guarantees, not on what to + build next. Once the high-level reading is done, pick **exactly one** skill entry point based on the user's intent. The entry point dispatches the rest internally; do not @@ -574,7 +121,7 @@ let the entry point pick it. | `docs/architecture/` | Conceptual descriptions of what we are building. Numbered `NN-topic.md` linearly. | Editable as the system evolves. | | `docs/decisions/` | ADRs — one-time decisions with status, context, decision, consequences. Redirect / superseded ADRs live under `_redirects/`. | Accepted ADRs are immutable except for dated Amendments and the two bounded corrections in [Documentation Standards § Correcting and Amending ADRs](docs/standards/13-documentation.md) ([ADR-0041](docs/decisions/0041-correcting-false-statements-in-accepted-adrs.md)). | | `docs/standards/` | Engineering rules (`NN-topic.md`, 00 – 21). Each anchored standard carries a `**Derives from:** ADR-NNNN` header. | Editable as the team learns; standard changes cite an ADR. | -| `docs/roadmap/` | Phased plan (`phase-NN-topic.md`, 00 – 12 with 02a/02b/02c/**02d**, 08a/08b/08c, and 09/09b splits). Every phase doc carries the same six sections — Goal, Scope, Deliverables, Completion Criteria, Risks, Phase Exit Decision — with three declared exceptions listed in [the roadmap index](docs/roadmap/README.md): Phase 09b and Phase 12 are pointer documents into the Hub repository, and Phase 01 predates the convention. | Editable per phase; the Status block of a shipped packet is a dated delivery record and is not rewritten. | +| `docs/roadmap/` | Phased plan (`phase-NN-topic.md`, 00 – 12 with 02a/02b/02c/**02d**, 08a/08b/08c, and 09/09b splits). Every phase doc carries the same six sections — Goal, Scope, Deliverables, Completion Criteria, Risks, Phase Exit Decision — with three declared exceptions listed in [the roadmap index](docs/roadmap/README.md): Phase 09b and Phase 12 are pointer documents into the Hub repository, and Phase 01 predates the convention. A phase with packets keeps its dated records — decision packages, step records, reviews, closeouts — in a sibling `phase-NN-delivery-log.md` ([ADR-0069](docs/decisions/0069-phase-documents-and-delivery-logs.md)); Phase 02a keeps its legacy single-file shape. | Phase doc editable per phase, its Status block holding packet state only. The delivery log is append-only: a shipped packet's records are not rewritten, and an Accepted decision package there is normative. | | `docs/modules/` | Per-module specifications (`/README.md` + `permissions.md` + `audit.md`), one directory per module, created with the first spec — [Tenancy](docs/modules/tenancy/README.md), Phase 02a Packet 6, [Customization](docs/modules/customization/README.md), Packet 8, and [Audit](docs/modules/audit/README.md), Packet 9. The ten sections are fixed by [Documentation Standards](docs/standards/13-documentation.md). | Editable with the module. | | `docs/glossary.md` | Terminology source of truth. | Editable; new term goes here first, then used. | @@ -688,6 +235,14 @@ rules: material moves by secret-store replication and is referenced by path from `PUT /api/internal/tenants/{id}/host-mappings`, never by value through a payload LearnStack caches, logs, audits and mirrors. +- **Append a dated packet record to a phase document, or narrate packet status + anywhere but its Status block.** Decision packages, step records, reviews, + corrections and closeouts are entries in the phase's delivery log. This file and + the repository README point at the phase document and link no delivery log, and + the roadmap index's § Phases links none either + ([ADR-0069](docs/decisions/0069-phase-documents-and-delivery-logs.md)). + `scripts/roadmap-structure.py` fails the build otherwise, and + `scripts/markdown-fragment-audit.py` fails it on any anchor a move leaves broken. - Copy the RLS template into a second document. It lives only in [Database Standards](docs/standards/05-database.md); everywhere else links to it. The last duplication shipped a broken policy into four @@ -790,8 +345,7 @@ rules: rows directly — use `IAuditStore`, `IEntitlementProvider.RefreshAsync`, `IOutbox`. Only ADR-0046's confined dispatcher writes outbox status through fenced parameterized SQL; its terminal UPDATE and narrow witness-bound audit INSERT - share one transaction. P02b-2 Step 2 implements that accepted exception; both - independent review rounds passed. + share one transaction. - Write `inbox_messages` or `event_deliveries` from a module or Seeder. ADR-0046's transport-owned acceptance, inbox/business owner and confined scheduler alone write their granted columns. diff --git a/Makefile b/Makefile index 919e5ec4..62e03277 100644 --- a/Makefile +++ b/Makefile @@ -261,7 +261,7 @@ test-frontend: ## Guarded workspace Vitest run (nonempty, zero skips/todos). # ─── Lint / format ──────────────────────────────────────────────────────── .PHONY: lint -lint: lint-backend lint-frontend ## Run linters (backend dotnet-format check + frontend ESLint). +lint: lint-backend lint-frontend lint-docs ## Run linters (backend dotnet-format check + frontend ESLint + documentation guards). .PHONY: lint-backend lint-backend: ## `dotnet format` verify (no changes — fails on diff). @@ -271,6 +271,16 @@ lint-backend: ## `dotnet format` verify (no changes — fails on diff). lint-frontend: ## `pnpm -r lint` (Next/ESLint). (cd frontend && pnpm -r lint) +.PHONY: lint-docs +lint-docs: ## Whole-tree Markdown fragment audit, roadmap structure and current delivery log indexes (ADR-0069). + python3 scripts/markdown-fragment-audit.py + python3 scripts/roadmap-structure.py + python3 scripts/delivery-log-index.py + +.PHONY: docs-index +docs-index: ## Regenerate the index that opens each delivery log (ADR-0069). + python3 scripts/delivery-log-index.py --write + .PHONY: format format: ## Apply formatters in place (backend dotnet-format + frontend prettier). (cd backend && dotnet format LearnStack.slnx --no-restore) diff --git a/README.md b/README.md index 82aa0f9b..06a3136b 100644 --- a/README.md +++ b/README.md @@ -64,108 +64,13 @@ items, rules, custom fields and notification templates; their delivery is tracke ## Where it is today -**Phase 01, Phase 02a and Phase 02d are complete.** Phase 02d is merged through -PR #28 on 2026-10-11. P02b-0's -[entry audit](docs/roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) -is complete. **P02b-1 is complete and merged** through -[PR #29](https://github.com/HodeTech/LearnStack/pull/29) on 2026-10-12. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-1-merge-and-closeout-2026-10-12) -records transactional event production, enforcement, completed reviews and final -CI verification under Accepted ADR-0057. **P02b-2 is complete and merged** through -[PR #30](https://github.com/HodeTech/LearnStack/pull/30) on 2026-10-13. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) -records hosted dispatch, terminal audit, observation/enforcement, completed -reviews and final CI verification under Accepted ADR-0046. **P02b-3 is complete -and merged** through [PR #31](https://github.com/HodeTech/LearnStack/pull/31) on -2026-10-15. It delivers -durable subscriber acceptance, shared inbox/delivery ledger, both real default -subscriptions and Seeder handoff. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) -owns final verification. -**P02b-4 is complete and merged** through -[PR #32](https://github.com/HodeTech/LearnStack/pull/32) on 2026-10-19. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) -records all nine job-runtime steps, three CI steps, independent reviews and both -complete final-source hosted assignments. Production business and recurrence -definitions remain empty. **P02b-5 API authentication is complete and merged** -through [PR #33](https://github.com/HodeTech/LearnStack/pull/33) on 2026-10-20, -under Accepted ADR-0064/0065/0066. All five steps and verified correction bundles -completed their independent review rounds. Its -[merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) -records final-source CI, unchanged-plan A/B qualification and identical merge trees. -P02b-6 implements real issuance, protected profiles and safe shared seed/demo -reconciliation. Its -[Step 4 record](docs/roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) -retains completed implementation/review evidence and source-bound qualification -receipts. ADR-0068's -[three correction steps](docs/roadmap/phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) -complete local historical upgrade/credential/API/self-service proof and both -independent review rounds. Qualification applies to the recorded source and scope; -the correction record owns exact hosted assignments and merge remains separate. -BFF sessions and phase exit remain P02b-7–8; browser sign-in is not implemented. -Phase 02b remains in progress. -[P02d-1](docs/roadmap/phase-02d-walking-skeleton.md#merge-and-closeout-2026-09-14) is -**complete and merged**: Education domain, schema and isolation proofs. -**P02d-2's decision package and ADR-0050/0051 are Accepted** as of 2026-10-02, -with four implementation steps. Step 1 implements the access policy, exact -definition/locale readers, text-card metadata validation and seed verification queries. -Both Step 1 review rounds passed. Step 2 adds locale/branding writers and JSON audit -redaction; both review rounds passed. Step 3 adds Education writers; both review -rounds and the focused fix review passed. Step 4 completes convergent seed -execution after both review rounds. **P02d-2 is complete and merged** through -[PR #23](https://github.com/HodeTech/LearnStack/pull/23) on 2026-10-02; the -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-2-merge-and-closeout-2026-10-02) -records verification. P02d-3 read internals are implemented; the -[decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) -is Accepted — 2026-10-02, with Step 1 implemented and both review rounds passed. -Step 2 implements batched definition reads; both review rounds passed. Step 3 adds -generation caching and scope-safe bypass; both review rounds passed. -**P02d-3 is complete and merged** through -[PR #24](https://github.com/HodeTech/LearnStack/pull/24) on 2026-10-03; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-3-merge-and-closeout-2026-10-03) -records final verification. -**P02d-4 is complete and merged** through -[PR #25](https://github.com/HodeTech/LearnStack/pull/25) on 2026-10-08; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-4-merge-and-closeout-2026-10-08) -records final verification. -Its four steps deliver the read-only host boundary, anonymous site/Education -GET/HEAD reads and OpenAPI/SDK/CI controls. Every step completed both review -rounds; final fix verification and all six real required CI jobs pass. The sixth -required OpenAPI check is active, with all other live protection settings preserved. -Trusted server rendering is delivered by P02d-5. P02d-6 implements localized -catalog/course/lesson pages, ordered text fields, safe themes and metadata; its -[product closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) -records automated verification/reviews and scoped browser/VoiceOver observations. -The original P02d-6 implementation is complete. ADR-0055 remediation delivers -single-bootstrap admission and passing production replacement proofs; all three -steps completed both independent review rounds, and -the [Step 3 record](docs/roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) -owns completed Step 3 reviews, verified fixes and delivery evidence. **P02d-6 is -complete and merged** through [PR #27](https://github.com/HodeTech/LearnStack/pull/27) -on 2026-10-10; its -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) -records final verification. P02d-7's demo, Lighthouse and phase-exit -[decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-decision-package-2026-10-10) -and ADR-0056 were approved on 2026-10-11. All four steps completed both independent -review rounds. The shared demo, genericity fences and seeded browser/Lighthouse -proof pass real CI; the seventh required context is active. The -[Step 4 record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) -owns CI enforcement, reviews and the positive phase-exit verdict. -[PR #28](https://github.com/HodeTech/LearnStack/pull/28) is merged; the -[merge closeout](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) -owns final verification. P02b-0 through P02b-5 are complete. P02b-0 has an entry -verification; P02b-1–5 have the merge closeouts above for final source/merge -verification. P02b-3 Steps 1–5 implement durable -acceptance, shared inbox/ledger, independent subscriber scheduling and both -useful defaults with semantic Seeder handoff. Its -[Step 6 record](docs/roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) -records completed enforcement/regression and both review rounds for all six steps. -Its [merge closeout](docs/roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) -also records the verified external-review corrections. The -[P02d-4 decision package](docs/roadmap/phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) -is Accepted — 2026-10-03. All four implementation steps and their review loops -are complete. P02d-5 supplies trusted server rendering; P02d-6 supplies public -page consumers and P02d-7 the two-host browser demo. +**Phase 01, Phase 02a and Phase 02d are complete; Phase 02b is in progress.** +Phase 02d, the two-tenant walking skeleton, merged through PR #28 on 2026-10-11. In +Phase 02b, P02b-0 through P02b-5 are complete, P02b-1–5 merged through PRs #29–#33, +and P02b-6's realm and identity implementation is merged through PR #34; BFF +sessions and phase exit remain P02b-7–8, so browser sign-in is not implemented. +Packet state lives in the [Phase 02b](docs/roadmap/phase-02b-events-auth.md) +document's Status block; the [roadmap](docs/roadmap/README.md) lists every phase. | Area | Delivered now | Next milestone | |---|---|---| @@ -277,9 +182,7 @@ For separate development/watch terminals, retain `make public-api` and configuration through `make demo DEMO_MODE=ci`. Install its locked managed browser first with `cd frontend && pnpm exec playwright install --with-deps chromium`. The CI mode requires a fresh checkout configuration and artifact directory; use -local `make demo` for an existing workstation. The -[Step 4 record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) -owns actual CI and protection receipts. +local `make demo` for an existing workstation. Readiness is for the API and for the web listener. `pnpm dev/start` also use @@ -296,15 +199,10 @@ validated without contacting Keycloak at startup. Credential-free public reads remain available when Keycloak is stopped. P02b-6 owns current realm issuance/ reconciliation qualification; browser sessions remain P02b-7. -**P02d-5 is complete: ingress, visitor budgets and public entry.** The web -bootstraps the captured host through the API, redirects using enabled/default -locales and refuses unavailable scope. The server caller enforces no-store, -deadline/body limits and the closed authenticated hop. All four steps completed -both independent review rounds and fix verification. Source fences, the no-skip -test runner and real-API production HTML/RSC proofs pass. The -[remediation and closeout record](docs/roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) -owns current review/CI evidence. P02d-6 implements public pages; -P02d-7 supplies `make demo` and the seeded browser/Lighthouse proof. See +**Ingress, visitor budgets and public entry.** The web bootstraps the captured +host through the API, redirects using enabled/default locales and refuses +unavailable scope. The server caller enforces no-store, deadline/body limits and +the closed authenticated hop. See [local setup](.claude/skills/local-dev-setup/SKILL.md) and [Compose documentation](infra/compose/README.md) for troubleshooting. diff --git a/backend/openapi/policy/README.md b/backend/openapi/policy/README.md index 566d4eb3..4eb931e3 100644 --- a/backend/openapi/policy/README.md +++ b/backend/openapi/policy/README.md @@ -1,7 +1,7 @@ # OpenAPI compatibility controls [ADR-0024](../../../docs/decisions/0024-api-versioning-policy.md) owns the policy. -[P02d-4 G31](../../../docs/roadmap/phase-02d-walking-skeleton.md#openapi-sdk-and-required-check-plan) +[P02d-4 G31](../../../docs/roadmap/phase-02d-delivery-log.md#openapi-sdk-and-required-check-plan) owns pins, severity overrides, artifact contents and required-check rollout. `fixtures/base.json` and `fixtures/cases.json` cover each representable policy row diff --git a/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHandoff.cs b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHandoff.cs new file mode 100644 index 00000000..ebbca8ce --- /dev/null +++ b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHandoff.cs @@ -0,0 +1,190 @@ +using System.Runtime.ExceptionServices; +using FluentAssertions; +using LearnStack.Infrastructure.Jobs; +using LearnStack.Infrastructure.Messaging; +using LearnStack.Infrastructure.Persistence; +using LearnStack.SharedKernel.Identifiers; +using LearnStack.SharedKernel.Time; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.DependencyInjection.Extensions; +using Npgsql; +using Xunit; + +namespace LearnStack.Tests.Integration.Database; + +public sealed partial class BackgroundJobPositiveSdkTests +{ + [Fact] + public async Task Native_fixture_start_waits_for_previous_actual_cleanup_before_one_same_generation_hint() + { + await using var database = await DisposableSchemaDatabase.CreateAsync(schema.Postgres); + await BackgroundJobSchemaSeed.SeedTenantsAsync(database.AppConnectionString); + await using var provider = await BackgroundJobProviderJournalDatabase.CreateAsync(schema.Postgres); + var construction = new BackgroundJobPositiveProviderConstructionProbe(hold: true); + var bounds = new BackgroundJobRuntimeOptions { RenewalInterval = TimeSpan.FromSeconds(1) }; + await using var host = Fixture.Host(database, provider.Settings, construction, services => + { + services.RemoveAll(); + services.AddSingleton(bounds); + }); + await using var source = new PrivilegedDataSource(() => OutboxDispatcherDataSource.Build(database.OutboxConnectionString)); + using var globals = new NativeSdkGlobalFilterSnapshot(); + var time = new NativeHandoffCleanupTime(bounds.TransactionTimeout); + var runtime = NativeSdkRuntime(host.Services, source, bounds, time); + BackgroundJobBridge? bridge = null; + using var startup = new CancellationTokenSource(TimeSpan.FromSeconds(30)); + using var pulseStop = new CancellationTokenSource(); + var observed = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + var releaseHelper = new TaskCompletionSource(TaskCreationOptions.RunContinuationsAsynchronously); + NpgsqlConnection? blocker = null; + NpgsqlTransaction? transaction = null; + Task? pulse = null, helper = null; + ExceptionDispatchInfo? failure = null; + try + { + var submitted = await Fixture.SubmitAsync(host.Services, Fixture.Parameters(Guid.CreateVersion7(), + OrganizationId.From(Guid.CreateVersion7()), OrganizationId.From(Guid.CreateVersion7()))); + submitted.IsSuccess.Should().BeTrue(); + var job = submitted.Value; + var storage = HangfireStorageBootstrap.Create(source, Fixture.Registry.Infrastructure, new HangfireBoundedLogProvider()); + bridge = new BackgroundJobBridge(new PostgresBackgroundJobBridgeStore(source, Fixture.Registry, + bounds, new SystemGuidFactory()), new HangfireWakeupClient(storage, HangfireRuntimeFilters.Create()), bounds, TimeProvider.System); + (await bridge.RunQuantumAsync(startup.Token)).Should().BeTrue(); + while (bridge.Snapshot.Outstanding != 0) await Task.Delay(10, startup.Token); + bridge.Snapshot.Acknowledged.Should().Be(1); + await bridge.StopAsync(startup.Token); + blocker = await source.OpenConnectionAsync(startup.Token); + transaction = await blocker.BeginTransactionAsync(startup.Token); + string original; + await using (var command = new NpgsqlCommand("SELECT vendor_job_id FROM background_jobs WHERE id=@id FOR UPDATE", blocker, transaction) { CommandTimeout = 5 }) + { + command.Parameters.AddWithValue("id", job.Value); + original = (string)(await command.ExecuteScalarAsync(startup.Token))!; + } + pulse = KeepNativeHandoffLockAsync(blocker, transaction, pulseStop.Token); + await runtime.StartAsync(startup.Token); + var entered = await Task.WhenAny(time.Entered, pulse).WaitAsync(startup.Token); + entered.Should().BeSameAs(time.Entered, "a failed keepalive cannot silently release the controlled lock"); + await time.Entered; + // The first real empty acquisition now retains its own actual timer + // cleanup and local recovery identity. Release the DB lock before + // testing hint assistance, so it cannot explain the second refusal. + pulseStop.Cancel(); + await pulse; + await transaction.CommitAsync(startup.Token); + await transaction.DisposeAsync(); + transaction = null; + ((BackgroundJobControl)NativeSdkField(runtime, "_jobs")).CanRoute(job).Should().BeFalse(); + runtime.Snapshot.Control!.Executions.Should().Be(1); + (await NativeSdkVendorStateAsync(source, original, startup.Token)).Should().Be("Processing"); + helper = EnsureNativeSdkStartAsync(runtime, source, job, construction.Entered, startup.Token, async () => + { + observed.TrySetResult(); + await releaseHelper.Task.WaitAsync(startup.Token); + }); + (await Task.WhenAny(observed.Task, helper).WaitAsync(startup.Token)).Should().BeSameAs(observed.Task); + long nativeCount; + string newest; + await using (var read = await source.OpenConnectionAsync(startup.Token)) + await using (var count = new NpgsqlCommand("SELECT count(*),max(id)::text FROM public.job", read) { CommandTimeout = 5 }) + await using (var row = await count.ExecuteReaderAsync(startup.Token)) + { + (await row.ReadAsync(startup.Token)).Should().BeTrue(); + nativeCount = row.GetInt64(0); + newest = row.GetString(1); + } + if (nativeCount > 1) + { + // Counterfactual: the premature real extra hint is consumed + // while the prior local identity remains held; no fake work + // result or fabricated cleanup signal makes it succeed. + while (await NativeSdkVendorStateAsync(source, newest, startup.Token) != "Succeeded") + await Task.Delay(10, startup.Token); + ((BackgroundJobControl)NativeSdkField(runtime, "_jobs")).CanRoute(job).Should().BeFalse(); + } + construction.Calls.Should().Be(0); + (await BackgroundJobRuntimeRows.ReadAsync(database.AppConnectionString, job))!.NormalAttempts.Should().Be(0); + nativeCount.Should().Be(1, "no extra native hint may be consumed before preceding private cleanup joins"); + time.Release(); + await time.Joined.WaitAsync(startup.Token); + releaseHelper.TrySetResult(); + await helper; + await construction.Entered.WaitAsync(startup.Token); + construction.Calls.Should().Be(1); + (await BackgroundJobRuntimeRows.ReadAsync(database.AppConnectionString, job))!.NormalAttempts.Should().Be(1); + (await GenerationAsync(database, job)).Should().Be(1); + runtime.Snapshot.Bridge!.PriorHintRepairsAcknowledged.Should().Be(0); + } + catch (Exception error) when (NativeWaitCatchable(error)) { failure = ExceptionDispatchInfo.Capture(error); } + finally + { + runtime.RequestStop(); + startup.Cancel(); + time.Release(); + releaseHelper.TrySetResult(); + construction.Release(); + pulseStop.Cancel(); + async Task ObserveCleanupAsync(Func operation) + { + try { await operation(); } + catch (Exception error) when (NativeWaitCatchable(error)) { failure ??= ExceptionDispatchInfo.Capture(error); } + } + try { if (helper is not null) await helper; } + catch (OperationCanceledException) when (startup.IsCancellationRequested) { } + catch (Exception error) when (NativeWaitCatchable(error)) { failure ??= ExceptionDispatchInfo.Capture(error); } + if (pulse is not null) await ObserveCleanupAsync(() => pulse); + if (transaction is not null) await ObserveCleanupAsync(() => transaction.DisposeAsync().AsTask()); + if (blocker is not null) await ObserveCleanupAsync(() => blocker.DisposeAsync().AsTask()); + using var cleanup = new CancellationTokenSource(TimeSpan.FromSeconds(40)); + if (bridge is not null) await ObserveCleanupAsync(() => bridge.StopAsync(cleanup.Token)); + await ObserveCleanupAsync(() => runtime.StopAsync(cleanup.Token)); + await ObserveCleanupAsync(() => runtime.Completion.WaitAsync(cleanup.Token)); + } + failure?.Throw(); + } + + private static async Task KeepNativeHandoffLockAsync(NpgsqlConnection connection, NpgsqlTransaction transaction, + CancellationToken stopping) + { + while (!stopping.IsCancellationRequested) + { + await using var command = new NpgsqlCommand("SELECT 1", connection, transaction) { CommandTimeout = 5 }; + // Join an issued bounded command before touching the transaction; cancel only pacing. + (await command.ExecuteScalarAsync(CancellationToken.None)).Should().Be(1); + try { await Task.Delay(200, stopping); } + catch (OperationCanceledException) when (stopping.IsCancellationRequested) { } + } + } + + private sealed class NativeHandoffCleanupTime(TimeSpan frameworkWait) : TimeProvider + { + private readonly TaskCompletionSource _entered = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _release = new(TaskCreationOptions.RunContinuationsAsynchronously); + private readonly TaskCompletionSource _joined = new(TaskCreationOptions.RunContinuationsAsynchronously); + private int _captured; + public override long TimestampFrequency => System.TimestampFrequency; + public override long GetTimestamp() => System.GetTimestamp(); + public override DateTimeOffset GetUtcNow() => System.GetUtcNow(); + internal Task Entered => _entered.Task; + internal Task Joined => _joined.Task; + internal void Release() => _release.TrySetResult(); + public override ITimer CreateTimer(TimerCallback callback, object? state, TimeSpan dueTime, TimeSpan period) + { + var actual = System.CreateTimer(callback, state, dueTime, period); + return state is HangfireGenerationWork.Invocation && dueTime == frameworkWait + && Interlocked.CompareExchange(ref _captured, 1, 0) == 0 ? new HeldTimer(actual, this) : actual; + } + private sealed class HeldTimer(ITimer actual, NativeHandoffCleanupTime owner) : ITimer + { + public bool Change(TimeSpan dueTime, TimeSpan period) => actual.Change(dueTime, period); + public void Dispose() => actual.Dispose(); + public async ValueTask DisposeAsync() + { + await actual.DisposeAsync(); + owner._entered.TrySetResult(); + await owner._release.Task; + owner._joined.TrySetResult(); + } + } + } +} diff --git a/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHistory.cs b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHistory.cs index acb84aaf..7b2c81e4 100644 --- a/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHistory.cs +++ b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeHistory.cs @@ -170,34 +170,88 @@ private async Task NativeCheckpointHistoryAsync(string kind, int passedCommits, } private static async Task EnsureNativeSdkStartAsync(BackgroundJobRuntime runtime, PrivilegedDataSource source, - BackgroundJobId job, Task started, CancellationToken cancellationToken) + BackgroundJobId job, Task started, CancellationToken cancellationToken, Func? afterObservation = null) { - // Execution/cleanup subjects do not measure the bridge's repair grace. - // A native hint can skip the ACK-locked row, including recovery. Observe - // entry or its committed handoff before sending one real external hint. + // These isolated execution/cleanup fixtures do not measure the bridge's + // repair grace. Handoff ACK and native Succeeded alone do not prove the + // preceding hint's private work has actually released its ownership. + long? generation = null; + string? previous = null; + object? capturedGeneration = null; while (!started.IsCompleted) { cancellationToken.ThrowIfCancellationRequested(); - long? generation; + long current; + bool eligible; + string vendor; await using (var connection = await source.OpenConnectionAsync(cancellationToken)) await using (var command = new NpgsqlCommand(""" - SELECT wake_generation FROM background_jobs WHERE id=@id AND vendor_job_id IS NOT NULL + SELECT wake_generation, vendor_job_id, + ownership_token IS NULL AND processed_at IS NULL AND dead_lettered_at IS NULL + AND terminal_reason IS NULL AND original_due_at <= clock_timestamp() + AND ((phase IN ('pending','finalize_pending') AND available_after <= clock_timestamp()) + OR (phase='reconciling' AND probe_after IS NOT NULL AND probe_after <= clock_timestamp())) + FROM background_jobs WHERE id=@id AND vendor_job_id IS NOT NULL """, connection) { CommandTimeout = 5 }) { command.Parameters.AddWithValue("id", job.Value); - generation = await command.ExecuteScalarAsync(cancellationToken) as long?; + await using var row = await command.ExecuteReaderAsync(cancellationToken); + if (!await row.ReadAsync(cancellationToken)) + { + await Task.Delay(25, cancellationToken); + continue; + } + current = row.GetInt64(0); + vendor = row.GetString(1); + eligible = row.GetBoolean(2); } - cancellationToken.ThrowIfCancellationRequested(); - if (started.IsCompleted) return; - if (generation is { } current) + generation ??= current; + current.Should().Be(generation.Value, "fixture hints cannot reset the durable generation"); + previous ??= vendor; + var state = await NativeSdkVendorStateAsync(source, previous, cancellationToken); + state.Should().NotBe("Failed").And.NotBe("Deleted", "fixture startup never retries failed native work"); + var pool = NativeSdkExternalPool(runtime); + HangfirePoolOwnerSnapshot snapshot; + object? currentGeneration; + lock (NativeSdkField(pool, "_sync")) + { + snapshot = pool.Snapshot; + currentGeneration = pool.GetType().GetField("_generation", + System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic)?.GetValue(pool); + } + if (snapshot.State != HangfirePoolOwnerState.Running || snapshot.Work is null || currentGeneration is null) + { + await Task.Delay(25, cancellationToken); + continue; + } + capturedGeneration ??= currentGeneration; + ReferenceEquals(capturedGeneration, currentGeneration).Should().BeTrue(); + if (state == "Succeeded" && snapshot.State == HangfirePoolOwnerState.Running + && snapshot.Work is { Running: 0, Retained: 0, Closed: false } + && ((BackgroundJobControl)NativeSdkField(runtime, "_jobs")).CanRoute(job) && eligible) { + cancellationToken.ThrowIfCancellationRequested(); + if (started.IsCompleted) return; _ = NativeSdkWakeup(runtime, job, current); - return; + if (afterObservation is not null) await afterObservation(); + return; // One fixture hint, only after the preceding native operation actually released its ownership. } - await Task.Delay(TimeSpan.FromMilliseconds(25), cancellationToken); + if (afterObservation is not null) + { + await afterObservation(); + afterObservation = null; + } + await Task.Delay(25, cancellationToken); } } + private static HangfirePoolOwner NativeSdkExternalPool(BackgroundJobRuntime runtime) + { + lock (NativeSdkField(runtime, "_sync")) + return ((IEnumerable)NativeSdkField(runtime, "_pools")) + .Single(pool => pool.Snapshot.Pool == "external"); + } + private static string NativeSdkWakeup(BackgroundJobRuntime runtime, BackgroundJobId job, long generation) { var provider = (PostgreSqlStorage)NativeSdkField(NativeSdkField(runtime, "_bootstrap"), "_provider"); @@ -214,11 +268,11 @@ private static string NativeSdkWakeup(BackgroundJobRuntime runtime, BackgroundJo finally { CultureInfo.CurrentCulture = culture; CultureInfo.CurrentUICulture = uiCulture; } } - private static async Task NativeSdkVendorStateAsync(PrivilegedDataSource source, string vendor) + private static async Task NativeSdkVendorStateAsync(PrivilegedDataSource source, string vendor, CancellationToken cancellationToken = default) { - await using var connection = await source.OpenConnectionAsync(); + await using var connection = await source.OpenConnectionAsync(cancellationToken); await using var command = new NpgsqlCommand("SELECT statename FROM public.job WHERE id=@id", connection) { CommandTimeout = 5 }; command.Parameters.AddWithValue("id", long.Parse(vendor, CultureInfo.InvariantCulture)); - return await command.ExecuteScalarAsync() as string; + return await command.ExecuteScalarAsync(cancellationToken) as string; } } diff --git a/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeWait.cs b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeWait.cs index 0994cd77..64dad489 100644 --- a/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeWait.cs +++ b/backend/tests/LearnStack.Tests.Integration/Database/BackgroundJobPositiveSdkTests.NativeWait.cs @@ -1,4 +1,5 @@ using System.Reflection; +using System.Runtime.ExceptionServices; using FluentAssertions; using LearnStack.Infrastructure.Jobs; using LearnStack.Infrastructure.Messaging; @@ -38,16 +39,24 @@ public async Task Native_stop_returns_the_wrapper_before_a_held_external_constru submitted.IsSuccess.Should().BeTrue(); var job = submitted.Value; HangfireGenerationWork.Invocation? owned = null; + Task? wrapper = null; + Task? actual = null; + ExceptionDispatchInfo? failure = null; + var boundary = "start"; try { using var startup = new CancellationTokenSource(TimeSpan.FromSeconds(30)); await runtime.StartAsync(startup.Token); + boundary = "handoff"; await EnsureNativeSdkStartAsync(runtime, source, job, construction.Entered, startup.Token); + boundary = "constructor"; await construction.Entered.WaitAsync(startup.Token); + boundary = "capture"; owned = NativeSdkInvocation(runtime); var framework = (HangfireInvocationContract.BoundInvocation)NativeSdkField(owned, "_framework"); - var wrapper = (Task)NativeSdkField(framework, "_wrapperWait"); - var actual = (Task)NativeSdkField(framework, "_operationObserver"); + wrapper = (Task)NativeSdkField(framework, "_wrapperWait"); + actual = (Task)NativeSdkField(framework, "_operationObserver"); + boundary = "cancel"; if (reason == "host_stop") runtime.RequestStop(); else { @@ -59,8 +68,11 @@ public async Task Native_stop_returns_the_wrapper_before_a_held_external_constru expire.Parameters.AddWithValue("id", job.Value); (await expire.ExecuteNonQueryAsync()).Should().Be(1); } + boundary = "return"; await owned.ReturnRequested.WaitAsync(TimeSpan.FromSeconds(15)); + boundary = "wrapper"; (await wrapper.WaitAsync(TimeSpan.FromSeconds(10))).Should().BeFalse(); + boundary = "held"; actual.IsCompleted.Should().BeFalse("the actual synchronous constructor is still held, despite the native wrapper's return"); owned.Token.IsCancellationRequested.Should().BeTrue(); owned.Token.WaitHandle.Should().NotBeNull(); @@ -72,14 +84,37 @@ public async Task Native_stop_returns_the_wrapper_before_a_held_external_constru (await BackgroundJobRuntimeRows.CountOrganizationAsync(database.AppConnectionString, prepared.Value)).Should().Be(1); (await BackgroundJobRuntimeRows.CountOrganizationAsync(database.AppConnectionString, finalized.Value)).Should().Be(0); } + catch (Exception error) when (NativeWaitCatchable(error)) + { + failure = ExceptionDispatchInfo.Capture(error); + WriteNativeWaitObservation("failure", boundary, construction, owned, wrapper, actual, runtime); + } finally { construction.Release(); - runtime.RequestStop(); using var cleanup = new CancellationTokenSource(TimeSpan.FromSeconds(40)); - await runtime.StopAsync(cleanup.Token); - await runtime.Completion.WaitAsync(cleanup.Token); + boundary = "cleanup_request"; + try + { + runtime.RequestStop(); + boundary = "cleanup_stop"; + await runtime.StopAsync(cleanup.Token); + boundary = "cleanup_completion"; + await runtime.Completion.WaitAsync(cleanup.Token); + boundary = "cleanup_complete"; + } + catch (Exception error) when (NativeWaitCatchable(error)) + { + if (failure is null) + { + failure = ExceptionDispatchInfo.Capture(error); + WriteNativeWaitObservation("failure", boundary, construction, owned, wrapper, actual, runtime); + } + } + if (failure is not null) + WriteNativeWaitObservation("cleanup", boundary, construction, owned, wrapper, actual, runtime); } + failure?.Throw(); runtime.Snapshot.Control!.Executions.Should().Be(0); runtime.Snapshot.RetainedInvocations.Should().Be(0); var handle = () => owned!.Token.WaitHandle; @@ -102,6 +137,63 @@ public async Task Native_stop_returns_the_wrapper_before_a_held_external_constru row.GetInt64(1).Should().Be(1, "lease/host cancellation does not prove no intent or release occupancy"); } + // Pure diagnostic projection: no SQL, provider call, cancellation or completion + // capability is issued here. A failed cleanup never replaces the first failure. + private void WriteNativeWaitObservation(string kind, string boundary, + BackgroundJobPositiveProviderConstructionProbe construction, HangfireGenerationWork.Invocation? owned, + Task? wrapper, Task? actual, BackgroundJobRuntime runtime) + { + static object? Field(object owner, string name) => owner.GetType() + .GetField(name, BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(owner); + static string State(Task? task) => task?.Status switch + { + null => "not_issued", + TaskStatus.RanToCompletion => "succeeded", + TaskStatus.Canceled => "cancelled", + TaskStatus.Faulted => "faulted", + _ => "pending", + }; + try + { + var jobs = (BackgroundJobControl)NativeSdkField(runtime, "_jobs"); + HangfirePoolOwner[] pools; + lock (NativeSdkField(runtime, "_sync")) + pools = ((IEnumerable)NativeSdkField(runtime, "_pools")).ToArray(); + var shared = Field(runtime, "_shared") as HangfireSharedComponents; + var snapshot = runtime.Snapshot; + var runtimeState = snapshot.State switch + { + BackgroundJobRuntimeState.NotStarted => "not_started", + BackgroundJobRuntimeState.Bootstrapping => "bootstrapping", + BackgroundJobRuntimeState.Starting => "starting", + BackgroundJobRuntimeState.Running => "running", + BackgroundJobRuntimeState.Stopping => "stopping", + BackgroundJobRuntimeState.Retained => "retained", + BackgroundJobRuntimeState.Stopped => "stopped", + _ => "unknown", + }; + var poolStates = pools.Length == 0 ? "not_issued" : string.Join(',', pools.Select(pool => State(pool.Completion))); + output.WriteLine("Native wait " + kind + ";boundary=" + boundary + + ";constructor=" + (construction.Entered.IsCompleted ? "entered" : "pending") + + ";invocation=" + (owned is null ? "not_issued" : "captured") + + ";wrapper=" + State(wrapper) + ";actual=" + State(actual) + + ";runtime=" + runtimeState + ";completion=" + State(runtime.Completion) + + ";control=" + State(jobs.Completion) + ";pools=" + poolStates + + ";shared=" + State(shared?.Completion) + + ";bridgeLoop=" + State(Field(runtime, "_bridgeLoop") as Task) + + ";bridgeStop=" + State(Field(runtime, "_bridgeStop") as Task) + "."); + } + catch (Exception error) when (NativeWaitCatchable(error)) + { + // Diagnostic failure is not authority to replace the test failure. + try { output.WriteLine("Native wait " + kind + ";boundary=" + boundary + ";snapshot=unavailable."); } + catch (Exception outputError) when (NativeWaitCatchable(outputError)) { } + } + } + + private static bool NativeWaitCatchable(Exception error) => error.GetType() != typeof(OutOfMemoryException) + && error.GetType() != typeof(StackOverflowException); + [Fact] public async Task Native_external_constructor_uses_the_long_external_wait_after_short_Prepare_finishes() { diff --git a/backend/tests/LearnStack.Tests.Integration/Database/OutboxProcessorTests.cs b/backend/tests/LearnStack.Tests.Integration/Database/OutboxProcessorTests.cs index 99edfa7d..4cfc03d0 100644 --- a/backend/tests/LearnStack.Tests.Integration/Database/OutboxProcessorTests.cs +++ b/backend/tests/LearnStack.Tests.Integration/Database/OutboxProcessorTests.cs @@ -33,7 +33,7 @@ namespace LearnStack.Tests.Integration.Database; /// [Trait(RequiresDocker.Key, RequiresDocker.Value)] [Collection(SharedSchema.Name)] -public sealed class OutboxProcessorTests(SchemaFixture schema) +public sealed class OutboxProcessorTests(SchemaFixture schema, Xunit.Abstractions.ITestOutputHelper output) { private const string Traceparent = "00-11111111111111111111111111111111-2222222222222222-01"; private const string SensitiveCanary = "private-outbox-canary-84e315"; @@ -203,17 +203,40 @@ public async Task Actual_host_startup_rejects_invalid_credentials_without_provid }; await using var factory = new WorkerApiFactory(test, credential); - var failure = await Record.ExceptionAsync(() => Task.Run(() => _ = factory.Services).WaitAsync(ProofDeadline)); - - failure.Should().NotBeNull(); - failure.Should().BeAssignableTo(); - failure!.ToString().Should().NotContain(SensitiveCanary).And.NotContain(credential == string.Empty ? "Password=" : credential); - if (invalid == "missing") - failure.Message.Should().Contain("ConnectionStrings:OutboxDispatcher") - .And.Contain("Npgsql key/value").And.Contain("learnstack_outbox_admin"); - test.Logs.Text.Should().NotContain(SensitiveCanary); + var startup = Task.Run(() => _ = factory.Services); + try + { + var failure = await Record.ExceptionAsync(() => startup.WaitAsync(ProofDeadline)); + output.WriteLine($"Outbox startup result;outcome={StartupOutcome(failure)};startup={StartupState(startup)}."); + failure.Should().NotBeNull(); + failure.Should().BeAssignableTo(); + failure!.ToString().Should().NotContain(SensitiveCanary).And.NotContain(credential == string.Empty ? "Password=" : credential); + if (invalid == "missing") + failure.Message.Should().Contain("ConnectionStrings:OutboxDispatcher") + .And.Contain("Npgsql key/value").And.Contain("learnstack_outbox_admin"); + test.Logs.Text.Should().NotContain(SensitiveCanary); + } + finally + { + // WaitAsync expiry does not stop or join WebApplicationFactory startup. + // Observe its actual result before either await-using owner disposes it. + var actual = await Record.ExceptionAsync(() => startup); + output.WriteLine($"Outbox startup completion;outcome={StartupOutcome(actual)};startup={StartupState(startup)}."); + } } + private static string StartupOutcome(Exception? failure) => failure switch + { + null => "succeeded", + TimeoutException => "timeout", + OperationCanceledException => "cancelled", + InvalidOperationException => "refused", + _ => "other", + }; + + private static string StartupState(Task startup) => startup.IsCompletedSuccessfully ? "succeeded" + : startup.IsCanceled ? "cancelled" : startup.IsFaulted ? "faulted" : "pending"; + [Fact] public async Task Real_provisioning_rows_remain_Pending_across_hosted_polls_without_construction_or_mutation() { @@ -814,6 +837,8 @@ private sealed class WorkerApiFactory(WorkerDatabase database, string? credentia protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.UseEnvironment(Environments.Development); + // Outbox proofs own PostgreSQL and their captured logger, not a collector. + builder.UseSetting("Telemetry:OtlpEndpoint", string.Empty); builder.UseSetting("ConnectionStrings:Default", database.AppConnectionString); builder.UseSetting("ConnectionStrings:PlatformAdmin", database.PlatformConnectionString); builder.UseSetting("ConnectionStrings:OutboxDispatcher", credential); diff --git a/backend/tests/LearnStack.Tests.JobLifecycleProbe/README.md b/backend/tests/LearnStack.Tests.JobLifecycleProbe/README.md index c5c44e72..9322f6e5 100644 --- a/backend/tests/LearnStack.Tests.JobLifecycleProbe/README.md +++ b/backend/tests/LearnStack.Tests.JobLifecycleProbe/README.md @@ -37,7 +37,7 @@ base/Architecture have no Docker or collector authority. Rerun all jobs when retrying; previous-attempt siblings cannot supply current proof. Their offline controls run in `meta`; actual hosted qualification is recorded in the -[CI implementation record](../../../docs/roadmap/phase-02b-events-auth.md#adr-0062-acceptance-and-ci-implementation-2026-10-18). +[CI implementation record](../../../docs/roadmap/phase-02b-delivery-log.md#adr-0062-acceptance-and-ci-implementation-2026-10-18). This does not change the fixture's independent collector/resource checks or authorize host changes on local, shared, self-hosted or production machines. diff --git a/docs/architecture/03-module-boundaries.md b/docs/architecture/03-module-boundaries.md index 1cfe39c3..24777f9a 100644 --- a/docs/architecture/03-module-boundaries.md +++ b/docs/architecture/03-module-boundaries.md @@ -239,7 +239,7 @@ Owns external provider credentials, webhooks, API keys, LTI/xAPI readiness, inte | Subscribe to another module's **integration event** — delivered from the outbox through `IEventBus` (`InProcessEventBus` today, Dapr pub/sub on its trigger). | Cross-module EF navigation properties. | | Read another module's **public read model** (projection table). | Joining across module-owned tables in SQL. | | Use the **shared kernel** (ids, audit fields, errors, pagination, base types, `ICacheService`, `ISecretProvider`, `IFeatureFlags`). | Importing another module's `Domain` namespace. | -| Publish an integration event by enqueueing it in the **outbox** through `IOutbox`, implemented by [P02b-1](../roadmap/phase-02b-events-auth.md#p02b-1-step-2--immediate-outbox-production-2026-10-12). | Holding `IEventBus`: direct publication bypasses the transactional producer outbox (`Modules_Do_Not_Inject_IEventBus_Directly`). | +| Publish an integration event by enqueueing it in the **outbox** through `IOutbox`, implemented by [P02b-1](../roadmap/phase-02b-delivery-log.md#p02b-1-step-2--immediate-outbox-production-2026-10-12). | Holding `IEventBus`: direct publication bypasses the transactional producer outbox (`Modules_Do_Not_Inject_IEventBus_Directly`). | | Provide an **adapter implementation** at the composition root. | Domain-specific names (`CEFR`, `Asana`, `Kyu`, …) anywhere in a core module — those belong to tenant customization data, not code. | | Ask **`IFeatureFlags`** for an entitlement and **`IHostToTenantResolver`** for a host — the two ports over the Hub-mirrored projections. | Reading `platform_entitlement_cache` or `platform_host_to_tenant` directly: the entitlement provider and the host resolver are their only readers — not `IFeatureFlags`, and not the Tenancy module that maps both tables (`Modules_Do_Not_Read_Entitlement_Cache_Directly`). Direct HTTPS calls to Hub from anywhere except the `IEntitlementProvider` / `IUsageReporter` / `IHubTenantSync` adapter implementations; resolving a host by calling the Hub at all — `IHostToTenantResolver` reads `platform_host_to_tenant` and nothing else ([ADR-0034](../decisions/0034-hub-contract-surface-invariant.md)). | | Reference the `LearnStack.Modules.Audit` module via integration events (Audit subscribes to events from other modules). | Writing to `audit_log` directly from outside the Audit infrastructure pipeline. | diff --git a/docs/architecture/04-technical-architecture.md b/docs/architecture/04-technical-architecture.md index f5f37e3c..819867df 100644 --- a/docs/architecture/04-technical-architecture.md +++ b/docs/architecture/04-technical-architecture.md @@ -195,7 +195,7 @@ flowchart LR through `IEventBus`. P02b-2 Step 3 implements hosted execution, with both independent review rounds complete. P02b-3 Steps 1–5 implement durable acceptance and independent subscriber execution with both real defaults Active. - The [packet record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) + The [packet record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current enforcement, validation and review status. - Publication is at-least-once. The transport-owned shared inbox and business completion commit together for ordinary database effects; external effects need @@ -242,10 +242,10 @@ Application projects run **outside** containers during active development for fa P02d-5 delivers G33's paired loopback API and native TLS web ingress, with isolated real-API production-rendering fixtures. The -[accepted local setup](../roadmap/phase-02d-walking-skeleton.md#local-setup-and-ingress-details) +[accepted local setup](../roadmap/phase-02d-delivery-log.md#local-setup-and-ingress-details) owns host, certificate and private configuration preparation. P02d-7 delivers G45's `make demo` lifecycle and browser evidence; the -[Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +[Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns completed reviews, CI enforcement and phase-exit verification. ## Observability diff --git a/docs/architecture/09-tenant-isolation.md b/docs/architecture/09-tenant-isolation.md index 9b136bb5..5e5da5a0 100644 --- a/docs/architecture/09-tenant-isolation.md +++ b/docs/architecture/09-tenant-isolation.md @@ -54,7 +54,7 @@ eligibility and contract proofs; | EF Core | Global query filter `e.TenantId == currentTenantId` | Global query filter `e.OrganizationId == null OR e.OrganizationId == currentOrgId` | | PostgreSQL | The tenant term of the single policy: `tenant_id = NULLIF(current_setting('app.tenant_id', true), '')::uuid` | The organization term `AND`-ed into that **same** policy, plus the restrictive `UPDATE` / `DELETE` write guards. Canonical SQL in [Database Standards](../standards/05-database.md) | | Identity | Single-realm `learnstack` with `tenant_id` JWT claim (default per [ADR-0004](../decisions/0004-authentication-strategy.md); realm-per-tenant is an opt-in for enterprise isolation only) | `organization_id` JWT claim populated from active org membership | -| Cache | The caller composes `{tenant_id}:{module}:{logical-name}` with `CacheKey.ForTenant`; every `ICacheService` implementation validates the key and prefixes nothing | `{tenant_id}:{org_id}:{module}:{logical-name}` with `CacheKey.ForOrganization`, for a value scoped to one organization. Settings reads are uncached in P02d-2/3 under [Accepted G23](../roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02); no settings cache key is active | +| Cache | The caller composes `{tenant_id}:{module}:{logical-name}` with `CacheKey.ForTenant`; every `ICacheService` implementation validates the key and prefixes nothing | `{tenant_id}:{org_id}:{module}:{logical-name}` with `CacheKey.ForOrganization`, for a value scoped to one organization. Settings reads are uncached in P02d-2/3 under [Accepted G23](../roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02); no settings cache key is active | | Files (SeaweedFS) | Object key prefix `tenants/{tenant_id}/...` | `tenants/{tenant_id}/organizations/{org_id}/...` for org-scoped assets | | Search | `tenant_id` as a mandatory filter composed **inside** `ITenantSearch` — callers pass criteria, never filter strings. Until Meilisearch's demand gate fires ([ADR-0035](../decisions/0035-demand-gated-infrastructure.md)), search runs on PostgreSQL full-text over tenant-owned tables and inherits Row Level Security; the engine-enforced per-request tenant token arrives with the Meilisearch adapter in [Phase 09](../roadmap/phase-09-billing-integrations-analytics.md) | `organization_id = X OR organization_id IS NULL` clause when org context | | Jobs (ADR-0047) | Trusted submission stamps the authoritative row; `JobExecutor` restores its validated `TenantId` | The row carries nullable `OrganizationId`; opaque Hangfire hints supply no scope | @@ -176,7 +176,7 @@ and owner-only completion. P02b-2 Step 3 implements confined hosted dispatch; both independent review rounds are complete. P02b-3 Steps 1–5 supply durable acceptance, shared tenant/org-protected delivery storage, app-role business scopes, independent scheduling and both real defaults. Its -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current validation and review status. The scheduler cannot read payload or inbox columns; business execution retains the ordinary tenant/org RLS boundary. diff --git a/docs/architecture/10-cross-module-contracts.md b/docs/architecture/10-cross-module-contracts.md index d30f3219..356cf11c 100644 --- a/docs/architecture/10-cross-module-contracts.md +++ b/docs/architecture/10-cross-module-contracts.md @@ -24,12 +24,12 @@ not delivered subscriber machinery. **2026-10-13 implementation note.** P02b-3 Steps 1–4 deliver shared storage, durable acceptance, transport-owned inbox/business completion and independent subscriber scheduling, terminal audit and internal replay. The -[Step 4 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13) +[Step 4 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13) owns passing proofs and both completed review rounds. Production default subscriptions activated together in Step 5 with the shared initializer/Seeder -handoff; its [record](../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +handoff; its [record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) records that step's validation and reviews. The -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current enforcement, validation and review/PR status. ## Allowed Contract Types diff --git a/docs/architecture/12-localization.md b/docs/architecture/12-localization.md index c1aa3f1f..1371cde6 100644 --- a/docs/architecture/12-localization.md +++ b/docs/architecture/12-localization.md @@ -58,7 +58,7 @@ CREATE TABLE tenant_locales ( ``` No public no-row fallback is implemented. The -[accepted P02d-2 G13 answer](../roadmap/phase-02d-walking-skeleton.md#p02d-2-accepted-answers) +[accepted P02d-2 G13 answer](../roadmap/phase-02d-delivery-log.md#p02d-2-accepted-answers) admits no content locale when rows are absent and refuses disabled membership. This replaces the earlier unimplemented platform-`en` proposal. Writer enforcement is delivered in P02d-2. P02d-4's accepted public contract returns site `404` for an @@ -213,7 +213,7 @@ Pattern B is cheaper for short fields where joining a translation table is overk **G24 Accepted — 2026-10-02.** This section owns display fallback under [ADR-0008](../decisions/0008-localization-schema.md); the standard links here. -[P02d-3's decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) +[P02d-3's decision package](../roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) records acceptance. Step 1 implements locale-carrying resolution; both review rounds passed. P02d-4 Step 3 supplies public response fields; P02d-6 delivers language attributes. @@ -342,10 +342,10 @@ proves RTL content with English fallback UI, without altering seed inventory or claiming an Arabic catalogue. Pattern A content never gains cross-locale fallback. Step 1 implements the pinned dependency/plugin, catalogues, request runtime and key/ICU/callsite controls. The -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns foundation verification and review evidence. Step 2 adds catalog/course consumers; Step 3 adds ordered lesson labels and metadata. The -[Step 4 closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[Step 4 closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) records product proof and scoped manual accessibility evidence. Phase 04 inherits the foundation for CMS/Studio; Phase 06 owns the full Studio/portal consumers. diff --git a/docs/architecture/13-identity-and-auth.md b/docs/architecture/13-identity-and-auth.md index 0de7fd39..b6c6e757 100644 --- a/docs/architecture/13-identity-and-auth.md +++ b/docs/architecture/13-identity-and-auth.md @@ -8,24 +8,24 @@ This document covers what lives where: in Keycloak vs in LearnStack, how multi-t existed, but API JWT validation, tenant claim mappers, a BFF session and mirrored users/memberships had not shipped. Public sites used host-based anonymous admission without forwarding cookies or credentials. -[Phase 02b's entry verification](../roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) +[Phase 02b's entry verification](../roadmap/phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) records that baseline. The P02b-5/P02b-6 delivery records below supersede its API validation and realm-issuance status. BFF sessions remain P02b-7; Phase 03 owns the application identity domain. Undelivered flows below remain target architecture. **P02b-5 decision Accepted — 2026-10-19.** [ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md) and its -[decision package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19) +[decision package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) authorize scalar identity claims, one closed authenticated read and additional subject accounting. All five implementation steps and their two independent review rounds are complete and merged through PR #33 on 2026-10-20; the -[merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) +[merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns delivery, correction reviews and final-source qualification. Authentication and authorization registration activate together with the closed surface in Step 4. P02b-6 supplies realm reconciliation as recorded below; BFF sessions remain P02b-7. **P02b-6 decision Accepted — 2026-10-21.** The -[accepted package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) +[accepted package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) authorizes four implementation steps for real issuance, protected seed attributes, account-preserving development reconciliation, exact callbacks and issuance TTL. Steps 1–3 supply the committed fresh-import scopes/profile/client definition, @@ -33,7 +33,7 @@ typed identity manifest, bounded warm reconciliation and shared seed/demo entry. Their local reviews and actual lifecycle qualification are complete. Step 4 delivers the approved account capability and complete provider/API security proofs after both independent review rounds and verified corrections; its -[record](../roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) +[record](../roadmap/phase-02b-delivery-log.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) owns local implementation, review closure and source-bound qualification receipts. The correction record below owns exact hosted assignments; merge is separate. G13's BFF session part @@ -58,18 +58,18 @@ all tenants/hosts, bounded idle-only cleanup and distinct quota/capacity/fault signals. Occupied live slots can deny other tenants' new subjects; there is no reserved share or end-to-end throughput promise. Its implementation has local runtime/exported proofs; the -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. ADR-0065 also ratifies process-wide native HTTP/DNS metric projection and ordinary dependency-attribution loss while preserving ordinary traces/logs. Acceptance precedes dependent budget implementation; the -[2026-10-20 remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[2026-10-20 remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns current implementation and proof status. **API activation — P02b-5 Step 4, 2026-10-19.** The production API now installs that strict bearer boundary and exposes exact `GET /api/v1/account/site`. -The [Step 4 record](../roadmap/phase-02b-events-auth.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) +The [Step 4 record](../roadmap/phase-02b-delivery-log.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) owns validation and review status. This updates the API-validation part of the 2026-10-12 baseline above; P02b-6 owns the realm's issuance changes, P02b-7 the BFF session and Phase 03 the application identity model. Public transport stays @@ -284,18 +284,18 @@ provisions `demo-english` and `demo-yoga` through the request path ([Phase 02a Packet 7](../roadmap/phase-02a-kernel-tenancy.md#delivery-record-packet-7)), and a re-run is idempotent. -G12's [accepted package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) +G12's [accepted package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) owns the account-preserving warm upgrade and its named account-console adjustment. [ADR-0068](../decisions/0068-development-warm-realm-qualification.md), Accepted — 2026-10-22, adds bounded profile preparation and three qualified stock-console assignment detachments. This deletes named assignment edges, while preserving -accounts and global definitions. Its [implementation record](../roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22) +accounts and global definitions. Its [implementation record](../roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22) tracks all three locally completed steps and their independent review rounds. The preparation owner reuses identity-independent qualifiers, verifies the exact profile and discards its projections before complete planning. A later identity conflict retains a fixed metadata-progress notice and permits no ordinary write. The -[third correction step](../roadmap/phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) +[third correction step](../roadmap/phase-02b-delivery-log.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) owns actual historical lifecycle, usable credential/MFA, signed API and stored self-service proof, with source-bound hosted assignments and evidence limits. The realm guide owns the exact local procedure and refusal boundaries. G10 is diff --git a/docs/architecture/14-frontend-architecture.md b/docs/architecture/14-frontend-architecture.md index 8c83be10..b861db3c 100644 --- a/docs/architecture/14-frontend-architecture.md +++ b/docs/architecture/14-frontend-architecture.md @@ -20,7 +20,7 @@ optional per-organization override, rendering strategies, data fetching, the ten block resolver, entitlement-aware UI, custom-domain handling, and the path to extracting independent apps when warranted. -The [P02d-5 external-review remediation](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) +The [P02d-5 external-review remediation](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) tracks verified gaps. [ADR-0054](../decisions/0054-bounded-public-renderer-admission.md) is **Accepted — 2026-10-09**. P02d-5 delivers coordinated anonymous accounting, native method/upgrade admission and pinned URL controls. The remediation record @@ -29,7 +29,7 @@ owns execution and independent review evidence; the ongoing rules live in **P02d-6 decisions Accepted — 2026-10-09; Steps 1–4 implemented.** [ADR-0027](../decisions/0027-frontend-i18n.md) selects the UI foundation; the -[decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +[decision package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) selects pages, status/navigation, safe theme and product/accessibility proofs. Step 1 installs the pinned runtime and supplies shared request-local loaders, document language/direction, atomic theme injection, chrome and controlled @@ -37,7 +37,7 @@ status/error/loading components. Step 2 adds actual catalog/course pages, independent opaque pagination and metadata. Step 3 adds ordered lesson fields, language attribution and eligible metadata. Step 4 adds concurrent host/locale, theme, freshness and content-fault product proofs. The -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) owns validation, completed reviews and passing manual accessibility closeout. [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md) is @@ -45,10 +45,10 @@ owns validation, completed reviews and passing manual accessibility closeout. it replaces the duplicate RSC bootstrap with one middleware-owned live read and an immutable same-request snapshot, preserving exact bootstrap 429/503 before rendering. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns passing production replacement proofs and completed Step 3 reviews. Both review rounds for all three steps and focused fix verification are complete. The -[review decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-systematic-review-decision-package-2026-10-10) +[review decision package](../roadmap/phase-02d-delivery-log.md#p02d-6-systematic-review-decision-package-2026-10-10) separately records approval for Open Graph projection and bounded Next security maintenance. The isolated context-propagation experiment establishes feasibility; it is not production security/lifecycle proof or runtime delivery. @@ -57,7 +57,7 @@ it is not production security/lifecycle proof or runtime delivery. > Steps 3–4 deliver Education and contract/SDK controls; P02d-5 owns the server consumer. > [ADR-0052](../decisions/0052-anonymous-public-read-boundary.md) selects host-resolved > site bootstrap in place of public edge ID lookup. Its -> [approval package](../roadmap/phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) +> [approval package](../roadmap/phase-02d-delivery-log.md#p02d-4-decision-package-2026-10-03) > records public DTOs, locale and cache rules, read-only execution and implementation > steps. Runtime delivery is recorded by the packet; P02d-5 owns server transport. @@ -179,12 +179,12 @@ so a claim cannot enlarge what the host serves. **P02d-5 Accepted — 2026-10-08.** [ADR-0053](../decisions/0053-trusted-public-server-rendering.md) accepts native socket provenance, a server-only configured transport and uncached institution rendering. -Its four-step [delivery plan](../roadmap/phase-02d-walking-skeleton.md#p02d-5-implementation-plan) +Its four-step [delivery plan](../roadmap/phase-02d-delivery-log.md#p02d-5-implementation-plan) records all four completed steps and both independent review rounds per step. Frontend fences, no-skip outcomes and real-API production HTML/RSC proofs pass; P02d-5 and its external-review remediation are complete and merged through [PR #26](https://github.com/HodeTech/LearnStack/pull/26); the -[merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) +[merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) records final verification. P02d-6 owns public page consumers. ADR-0054 retains API-owned tenant authority and membership-first locale entry. @@ -444,7 +444,7 @@ Studio and Portal have higher budgets because they are authenticated apps and be P02d-7's always-running `public demo + lighthouse` job exercises nine seeded public pages under ADR-0056. Performance Standards owns its hard budgets and advisory timing scope; the -[Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +[Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns real CI and required-check receipts. ## Accessibility @@ -460,7 +460,7 @@ owns real CI and required-check receipts. contrast and real screen-reader evidence for catalog → course → lesson names commit, environment and both hosts/locales. Automated product proofs and blocking lint controls are implemented; the - [packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) + [packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records passing manual browser checks and maintainer-reported VoiceOver evidence. See [Testing Standards](../standards/06-testing.md#frontend-test-types); HTTP/RSC diff --git a/docs/architecture/15-event-and-outbox.md b/docs/architecture/15-event-and-outbox.md index e8b06000..5ec28b4a 100644 --- a/docs/architecture/15-event-and-outbox.md +++ b/docs/architecture/15-event-and-outbox.md @@ -26,10 +26,10 @@ not land together. |---|---|---| | `outbox_messages` table, its schema, and its LearnStack ownership | [Phase 02a Packet 6](../roadmap/phase-02a-kernel-tenancy.md) | Schema and ownership shipped in Packet 6; producer dispatch is implemented in P02b-2 Step 3 | | `IEventBus` port + `InProcessEventBus` | [Phase 02a Packet 5](../roadmap/phase-02a-kernel-tenancy.md) | The only registered implementation | -| `IOutbox` and `TenantCreatedIntegrationEventV1` | [P02b-1](../roadmap/phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12) | Implemented immediate transactional production; P02b-3 delivers the two independent default effects | -| `OutboxProcessor` and the producer claim protocol | [P02b-2](../roadmap/phase-02b-events-auth.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) | Producer runtime and enforcement complete and merged; all four steps completed both independent review rounds; CI/merge status: [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) | +| `IOutbox` and `TenantCreatedIntegrationEventV1` | [P02b-1](../roadmap/phase-02b-delivery-log.md#p02b-1-decision-package-2026-10-12) | Implemented immediate transactional production; P02b-3 delivers the two independent default effects | +| `OutboxProcessor` and the producer claim protocol | [P02b-2](../roadmap/phase-02b-delivery-log.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) | Producer runtime and enforcement complete and merged; all four steps completed both independent review rounds; CI/merge status: [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) | | Shared ledger/inbox and durable acceptance | [P02b-3](../roadmap/phase-02b-events-auth.md) | Steps 1–4 implement schema, acceptance/inbox, transactional business execution and independent scheduling/terminalization/replay; Step 5 activates both real defaults and semantic Seeder handoff | -| Domain events collected and dispatched in-process, inside the ambient transaction | [P02b-1](../roadmap/phase-02b-events-auth.md#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) | Successful-save collection and owner-only completion implemented | +| Domain events collected and dispatched in-process, inside the ambient transaction | [P02b-1](../roadmap/phase-02b-delivery-log.md#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) | Successful-save collection and owner-only completion implemented | | `DaprEventBus` → Dapr pub/sub → Kafka | [Phase 11](../roadmap/phase-11-production-hardening.md) | Demand-gated; trigger: a second process needs to consume an integration event, or event volume / replay / cross-process ordering is required ([ADR-0035](../decisions/0035-demand-gated-infrastructure.md)) | **`InProcessEventBus` is a first-class transport.** P02b-3 Step 2 changes publish @@ -39,43 +39,43 @@ supplies the shared ledger/inbox schema; Step 2 declares `IInboxGuard` and its transaction-bound claim primitive. Step 3 implements the business owner and completion gate; Step 4 adds independent scheduling, terminalization, replay and bounded observation. Step 5 activates both real defaults and semantic Seeder handoff. -[Phase 02b's entry verification](../roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) +[Phase 02b's entry verification](../roadmap/phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) records the earlier immediate-invocation baseline. The producer/consumer diagrams and examples below describe the delivered ADR-0046 runtime. The -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) records production enforcement, validation and reviews. P02b-3 is complete and merged through PR #31; its -[merge closeout](../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) +[merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. -The [P02b-1 decision package](../roadmap/phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12) +The [P02b-1 decision package](../roadmap/phase-02b-delivery-log.md#p02b-1-decision-package-2026-10-12) and [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) authorize immediate enqueue, owner-only completion and produced-work refusal protection. P02b-1 Steps 1–3 implement shared execution, immediate enqueue, successful-save collection and the completed-provisioning publisher. Step 4 implements production-census guards and catalogue enforcement; its -[delivery record](../roadmap/phase-02b-events-auth.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) +[delivery record](../roadmap/phase-02b-delivery-log.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns final verification and review status. ADR-0046 accepts dispatcher/inbox contracts; producer dispatch is implemented through P02b-2 Step 3 and shared inbox/consumer execution through P02b-3 Steps 1–5. -The [P02b-2 decision package](../roadmap/phase-02b-events-auth.md#p02b-2-decision-package-2026-10-12) +The [P02b-2 decision package](../roadmap/phase-02b-delivery-log.md#p02b-2-decision-package-2026-10-12) and [Accepted ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md) authorize fenced producer recovery, atomic terminal audit and the coupled shared inbox/subscriber contract. Steps 1–2 implement schema/composition, fenced transitions and atomic terminal audit; each completed both review rounds. Step 3 implements hosted execution and observation, with both independent review rounds complete in its -[delivery record](../roadmap/phase-02b-events-auth.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12). +[delivery record](../roadmap/phase-02b-delivery-log.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12). Step 4 enforcement and local closeout are complete; all four steps completed both -independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. P02b-3 implements consumer execution through Step 3 and independent scheduling, terminalization, replay and bounded observation in Step 4. Its production default subscriptions are Active with Step 5 initialization and semantic Seeder handoff. The -[Step 5 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +[Step 5 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) records that step's validation and reviews; the -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) records enforcement, validation and reviews; the merge closeout above owns final CI/merge verification. Numerical runtime bounds live in the package, canonical DDL/grants in Standards 05 and @@ -173,7 +173,7 @@ implemented for transition-witness construction and terminal audit in Step 2; both independent review rounds passed. Step 3 implements hosted execution and observation, with both independent review rounds complete. Step 4 implements credential/publication censuses and planted controls; all four steps completed -both independent review rounds and local closeout. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +both independent review rounds and local closeout. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. @@ -361,7 +361,7 @@ until actual completion. Acceptance and execution use separate serializer lanes; a held subscriber never queues new durable acceptance behind its callback/cleanup. Shutdown uses one finite wait shared with the host token. Numerical bounds and validation/review evidence belong to the -[accepted package and Step 4 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13). +[accepted package and Step 4 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13). ### Audit rides this outbox for fan-out, never for the audit row @@ -410,7 +410,7 @@ concurrent live owners; crash recovery and lease expiry can still redeliver. ### The claim protocol **ADR-0046 producer runtime and enforcement complete and merged in P02b-2; all four -steps completed both independent review rounds.** The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +steps completed both independent review rounds.** The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. The processor admits a construction-free manifest policy before acquisition. Any required Pending subscription holds the contract and all aliases unchanged, even if stored payload is malformed. Active @@ -727,10 +727,10 @@ below four retained overruns after storage recovery; healthy other pools remain independent subject to shared dependencies. The exact two-clause supersession is disclosed in [ADR-0047 Amendment 2](../decisions/0047-transactional-background-job-runtime.md#amendment-2--owned-server-lifecycle-and-bounded-availability-supersession-2026-10-16); [ADR-0058 Amendment 2](../decisions/0058-bounded-stock-hangfire-maintenance.md#amendment-2--independent-shared-component-ownership-2026-10-16) -adds ownership navigation only. The [Step 4 adaptation](../roadmap/phase-02b-events-auth.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) +adds ownership navigation only. The [Step 4 adaptation](../roadmap/phase-02b-delivery-log.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) is delivered with both full review rounds and verified corrections. P02b-4 is complete and merged through PR #32; its -[merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) +[merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) owns final qualification of the shipped lifecycle/API composition. **Accepted exceptional boundary — 2026-10-16.** @@ -742,7 +742,7 @@ Step 4 delivers implementation; the merge closeout above records actual worker and native crash qualification separately from decision acceptance. Accepted [ADR-0062](../decisions/0062-native-crash-proof-ci-provisioning.md) adds only the named disposable native CI provisioning/partition authority; -[its CI record](../roadmap/phase-02b-events-auth.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) +[its CI record](../roadmap/phase-02b-delivery-log.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) owns implementation, reviews and hosted qualification. The closed CI launcher requires complete complementary case results behind the existing integration aggregate; a successful native partition alone cannot pass it. Native children retain @@ -763,7 +763,7 @@ Unknown durable work remains visible with empty local registries, and failed refresh retains the last sample with explicit unhealthy freshness. Observation supplies no source release, business completion or external-quiescence authority. The [metric inventory](../standards/10-observability.md#required-metrics) and -[Step 9 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +[Step 9 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) record the implemented observable, stage, trace, lease-loss and control signals, their source-specific qualification and full review status; the merge closeout above records final packet/CI verification. @@ -782,21 +782,21 @@ remain distinct; a locked header precedes a fresh attempt-ledger read. The stable lazy application source now has a single disposal owner, sharing the job/messaging release witnesses. Job main/auxiliary operation bounds retain abandoned loaders and failed cleanup; independent HTTP/delivery headroom is not -implied. The [Step 5 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-5--transactional-owner-and-terminal-audit-2026-10-16) +implied. The [Step 5 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-5--transactional-owner-and-terminal-audit-2026-10-16) owns implementation, qualification and review status. Step 6 adds tenant/group capacity admission and atomic reservation release. A failed transactional invocation must positively join its original source and private callbacks before the exact same-source cleanup checkpoint; distinct recovery authority is required. Missing local cleanup parks unresolved occupancy for paced probes. Its -[record](../roadmap/phase-02b-events-auth.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) +[record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) owns passing local qualification and both completed full reviews. Step 7 external execution and recovery are complete after both full reviews and verified corrections; its -[closeout](../roadmap/phase-02b-events-auth.md#step-7-full-review-round-2-2026-10-17) +[closeout](../roadmap/phase-02b-delivery-log.md#step-7-full-review-round-2-2026-10-17) owns the source-specific receipts. Step 8 durable recurrence and restricted recipient submission are locally complete after both full reviews and verified corrections; its -[record](../roadmap/phase-02b-events-auth.md#p02b-4-step-8--durable-recurrence-and-restricted-fan-out-2026-10-18) +[record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-8--durable-recurrence-and-restricted-fan-out-2026-10-18) owns final qualification. Production recurrence and business registries stay empty. [Database Standards](../standards/05-database.md#background-jobs) owns canonical @@ -808,11 +808,11 @@ vendor totals are not authoritative business outcomes; fewer live rows do not promise bounded disk/backlog or recovery rate. Phase 11 owns operational retention, space and measured production capacity. -The [Step 2 closeout](../roadmap/phase-02b-events-auth.md#step-2-final-proof-and-closeout) +The [Step 2 closeout](../roadmap/phase-02b-delivery-log.md#step-2-final-proof-and-closeout) owns completed schema/bootstrap/source qualification. The -[Step 3 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-3--submission-and-app-role-admission-2026-10-16) +[Step 3 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-3--submission-and-app-role-admission-2026-10-16) owns submission and app-role admission implementation/review status; -the [Step 4 continuation](../roadmap/phase-02b-events-auth.md#source-lifetime-and-facade-continuation-2026-10-16) +the [Step 4 continuation](../roadmap/phase-02b-delivery-log.md#source-lifetime-and-facade-continuation-2026-10-16) owns completed facade/source-lifetime implementation and qualification. Step 9 implements full observation/enforcement and locally qualifies both extended canonical obligations. Its record owns full-review, local packet-closeout and diff --git a/docs/architecture/21-feature-flags.md b/docs/architecture/21-feature-flags.md index 0216ed1a..c1c0370b 100644 --- a/docs/architecture/21-feature-flags.md +++ b/docs/architecture/21-feature-flags.md @@ -345,7 +345,7 @@ Each `LimitKey` in the catalog declares a `LimitEnforcement` (`Soft` | `Hard`): `POST /api/v1/usage/report`. Example: `ClassroomMinutesPerMonth`. Packet 9 shipped the descriptor and the read. The first hard authoring gate is -the [approved content-type quota](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19): +the [approved content-type quota](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting): it returns `403 limit_exceeded` through the standard Result/Problem Details mapping. The soft-limit reporting path remains [Phase 02c](../roadmap/phase-02c-hub-foundation.md) work, the first phase in which diff --git a/docs/architecture/25-deployment-models.md b/docs/architecture/25-deployment-models.md index 3198a347..b08e990d 100644 --- a/docs/architecture/25-deployment-models.md +++ b/docs/architecture/25-deployment-models.md @@ -131,7 +131,7 @@ Internet cardinality cap. This accounting does not bound total incoming network/refusal cost. [Security Standards](../standards/11-security.md#rate-limiting) own lifecycle, replay and Retry-After obligations; the - [remediation plan](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) + [remediation plan](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) owns implementation evidence. What is required, and where it lives: **resource fairness is diff --git a/docs/architecture/30-api-gateway.md b/docs/architecture/30-api-gateway.md index 1fa0f679..3555cd6a 100644 --- a/docs/architecture/30-api-gateway.md +++ b/docs/architecture/30-api-gateway.md @@ -25,7 +25,7 @@ the LearnStack core API and the LearnStack Hub API. > [Phase 03](../roadmap/phase-03-identity-admin.md). No authoring command is routed. > Present invalid credentials return 401 even on public routes; absent AccountSite > credentials return masked 404. The “validated twice” property in § 5 remains -> the Phase 11 target. The [Step 4 delivery record](../roadmap/phase-02b-events-auth.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) +> the Phase 11 target. The [Step 4 delivery record](../roadmap/phase-02b-delivery-log.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) > owns validation and review status, rather than this topology claiming completion. **Accepted P02d-5 local topology — 2026-10-08.** @@ -62,7 +62,7 @@ owns reachable issuer/DNS/TLS drills, operational failure signals, rotation, readiness, alerts and exercised runbooks before production exposure. P02b-6 owns real realm issuance; P02b-7 owns session custody and recovery. These are separate from P02b-5's -[merged API boundary](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20). +[merged API boundary](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20). ## 1. Topology @@ -448,7 +448,7 @@ outage grace period or immediate refusal of every warm-cache request. The owns topology, cold/warm-cache and key-rotation drills, diagnostic/readiness decisions and operational runbooks before production use. P02b-6 delivers actual realm issuance and safe development convergence; its -[Step 4 record](../roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) +[Step 4 record](../roadmap/phase-02b-delivery-log.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) owns qualification. Browser-session integration remains P02b-7. ## 6. Rate limit policy diff --git a/docs/architecture/31-audit-subsystem.md b/docs/architecture/31-audit-subsystem.md index 26389184..43e2a1b4 100644 --- a/docs/architecture/31-audit-subsystem.md +++ b/docs/architecture/31-audit-subsystem.md @@ -62,7 +62,7 @@ owner is added. ADR-0065 owns the illustrative nominal 864,000 rows/24h/tenant/i steady-saturation rate (not a calendar-day hard cap) and assumed storage costs; Phase 11 owns measured capacity and distributed admission. Implementation and local proofs are delivered and merged; the -[P02b-5 merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) +[P02b-5 merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns final-source qualification. Production capacity remains unqualified. **A granted read-sensitive query rides the first row, not the second.** It used to sit @@ -1755,8 +1755,8 @@ for MUST-class would lock in exactly the defect ADR-0033 removes. |-------|-------------| | [02a Packet 9](../roadmap/phase-02a-kernel-tenancy.md) | `AuditChangeTrackerInterceptor` with the broad capture predicate, the `[PiiSensitive]` redaction gate and the size cap; `IAuditStateCapture` + impl, holding an **ordered list** of intents; `AuditLogBehavior` lit up per ADR-0033 as amended; `IAuditStore` + `PostgresAuditStore` with **four** write methods, the fourth serving `EnterPlatformAdminScope`; the classification catalogue as a **pair** — the module-owned `IAuditCatalogSource` / `IAuditCatalogBuilder` and the `IAuditCatalog` the composition root merges them into once at startup — with the six value types beside the five ports in `LearnStack.SharedKernel.Audit`; `TenantId.PlatformSentinel` and the **four** guards that enforce its invariant — `SetProvisioningTenantContextAsync`, `TenantOwnership.EnsureRealTenant`, `EventTenantContext.FromEnvelope` and, deliberately redundant at the one site every announcement passes, `SetTenantContextAsync`; `AuditEntry` aggregate and `AuditConfig` with the fail-closed MUST floor; `audit_log` as a **single plain table** with the composite primary key, org-scoped, in a fourth migration chain, with its append-only grants and its two triggers; and the named `audit` health check §§ 1, 5 and 7 read, registered through `AddHealthChecks()` at the `LearnStack.Api` composition root. | | P02b-1 Steps 1–3 | Common audit/transaction coordinators, capture-owned audit frames, producer ancestry/receipts and no-listener trace groundwork; Steps 2–3 deliver immediate outbox enqueue, successful-save collection/promotion and owner-only domain drain. Hosted dispatch is implemented in P02b-2 Step 3; P02b-3 implements consumer delivery/inbox. | -| P02b-2 Steps 1–4 | Schema/grants and confined producer transitions with MUST audit through the row-bound fifth seam; real-role atomicity/identity proofs. Steps 1–2 completed both review rounds. Step 3 implements hosted dispatch and observation, with both independent review rounds complete; Step 4 enforcement and local closeout are complete; all four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. | -| P02b-3 Steps 1–6 | Shared transport-owned inbox and retained delivery envelopes, durable acceptance, per-subscription audit frames and fenced business completion; independent scheduling/replay and Tenancy-owned subscriber terminal audit through the row-bound fifth seam. Ordinary executor refuses privileged subscriptions. Both real default subscriptions are Active with nested initializer MUST audits and semantic Seeder handoff; Step 6 extends classification to each concrete integration handler, with actual API/Seeder catalogue and missing-Off controls. P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. | +| P02b-2 Steps 1–4 | Schema/grants and confined producer transitions with MUST audit through the row-bound fifth seam; real-role atomicity/identity proofs. Steps 1–2 completed both review rounds. Step 3 implements hosted dispatch and observation, with both independent review rounds complete; Step 4 enforcement and local closeout are complete; all four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. | +| P02b-3 Steps 1–6 | Shared transport-owned inbox and retained delivery envelopes, durable acceptance, per-subscription audit frames and fenced business completion; independent scheduling/replay and Tenancy-owned subscriber terminal audit through the row-bound fifth seam. Ordinary executor refuses privileged subscriptions. Both real default subscriptions are Active with nested initializer MUST audits and semantic Seeder handoff; Step 6 extends classification to each concrete integration handler, with actual API/Seeder catalogue and missing-Off controls. P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. | | [03](../roadmap/phase-03-identity-admin.md) | Admin API endpoints over the audit stream; `UserGdprDeletedIntegrationEventHandler` + per-module `IUserReferenceLocator`. | | [06](../roadmap/phase-06-renderer-admin-studio.md) | Admin Studio audit UI: timeline view, filters, diff viewer, CSV / JSON export. | | [09](../roadmap/phase-09-billing-integrations-analytics.md) | Hub-side `hub_audit_log` + cross-stream correlation query. | diff --git a/docs/architecture/32-tenant-customization-model.md b/docs/architecture/32-tenant-customization-model.md index 657d6d39..3593e0d5 100644 --- a/docs/architecture/32-tenant-customization-model.md +++ b/docs/architecture/32-tenant-customization-model.md @@ -17,7 +17,7 @@ P02b-3 Step 5 activates the two create-only provisioning defaults and verifies built-in seed rows by semantic identity. The [Customization module spec](../modules/customization/README.md#integration-event-catalogue) owns the shipped initializer/registration serialization and preservation contract; -the [packet record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +the [packet record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current verification and review status. Earlier seed receipts remain as-of history; authored definitions and content pins retain exact identity checks. @@ -234,7 +234,7 @@ output_format: { type: "string", enum: ["a1","a2","b1","b2","c1","c2"] } ### Example B — Yoga studio platform > **Broader target example, not the P02d-2 seed.** The -> [accepted inventory](../roadmap/phase-02d-walking-skeleton.md#seed-inventory-and-ownership) +> [accepted inventory](../roadmap/phase-02d-delivery-log.md#seed-inventory-and-ownership) > selects `asana-pose` with plain-string `pose`/`instruction`, `default-card` and > `yoga-difficulty`. The integer, enum and video example below requires later renderer > coverage; it does not expand ADR-0051's text-card subset. @@ -611,10 +611,10 @@ failures are not cache misses. TTLs reclaim stranded keys; fresh generation prob provide invalidation across independent L1 instances without events or L2. The module spec owns result/missing-member semantics and measured read budgets. -[P02d-3's decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) +[P02d-3's decision package](../roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) records proof obligations. Family-wide volume includes retained revisions; measure rows/bytes and query plans as recorded in the -[delivery measurements](../roadmap/phase-02d-walking-skeleton.md#step-3-generation-cache-and-read-safety), +[delivery measurements](../roadmap/phase-02d-delivery-log.md#step-3-generation-cache-and-read-safety), and reassess before Phase 04's larger workload. The `TenantPageBlock` family remains [Phase 04](../roadmap/phase-04-cms-media-pages.md) work. @@ -663,7 +663,7 @@ Structural limits are checked at write time and return Problem Details naming th limit that was exceeded. They are deliberately generous — they exist to stop pathological documents, not to constrain reasonable authoring. Content-type registration also enforces the plan's count under the -[accepted quota accounting](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19) +[accepted quota accounting](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting) with a tenant-wide transaction lock around usage and insertion. Entitlement resolution remains authoritative: the default NullEntitlementProvider grants unlimited usage under diff --git a/docs/architecture/33-cross-cutting-concerns.md b/docs/architecture/33-cross-cutting-concerns.md index f6cd69f5..b4787bbd 100644 --- a/docs/architecture/33-cross-cutting-concerns.md +++ b/docs/architecture/33-cross-cutting-concerns.md @@ -114,7 +114,7 @@ fatal-process policy is added. The exact lifecycle and HTTP contract live in the ADR; [Observability Standards](../standards/10-observability.md#tenant-authentication-diagnostics) owns the identity-free signals. Acceptance is 2026-10-20; implementation and local runtime/exported proofs are delivered. The -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. ADR-0065 also ratifies process-wide native outbound metric projection: HTTP keeps @@ -126,7 +126,7 @@ proofs. Phase 11 qualifies finite dependency attribution before its first consum P02d-4's [accepted boundary](../decisions/0052-anonymous-public-read-boundary.md) adds factory host-ceiling admission and read-only transaction intent. -[Step 1](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-1-authority-and-read-only-foundation) +[Step 1](../roadmap/phase-02d-delivery-log.md#p02d-4-step-1-authority-and-read-only-foundation) delivers these foundations and app-role write-refusal proofs. Step 2 adds the site endpoint and structural dispatch/Off/persistence controls; Education eligibility and contract proof remain Steps 3–4. The eight-stage order, normal writer diff --git a/docs/architecture/34-course-marketplace-scoping.md b/docs/architecture/34-course-marketplace-scoping.md index 714c13bb..477a8256 100644 --- a/docs/architecture/34-course-marketplace-scoping.md +++ b/docs/architecture/34-course-marketplace-scoping.md @@ -98,7 +98,7 @@ the same policy. Failure of a protected-access evaluator denies access. The maintainer approved [ADR-0050](../decisions/0050-publication-and-course-content-access.md) and the P02d-2 package on 2026-10-02. Its -[dated G3 supersession](../roadmap/phase-02d-walking-skeleton.md#g3-supersession-2026-10-02) +[dated G3 supersession](../roadmap/phase-02d-delivery-log.md#g3-supersession-2026-10-02) replaces ADR-0048's public-only implication while preserving the original answer and delivery history. Explicit persisted policy, restricted legacy backfill and fail-closed anonymous reads are decided. P02d-2 delivers the policy, migration and writers; diff --git a/docs/decisions/0003-tenant-isolation-defense-in-depth.md b/docs/decisions/0003-tenant-isolation-defense-in-depth.md index 6d4f66f5..a1356c53 100644 --- a/docs/decisions/0003-tenant-isolation-defense-in-depth.md +++ b/docs/decisions/0003-tenant-isolation-defense-in-depth.md @@ -358,7 +358,7 @@ corrected guards from the template. ## Amendment 6 — INSERT scope and parent mirrors (2026-09-14) **Accepted — 2026-09-14.** Approved by the maintainer in -[P02d-1's decision pass](../roadmap/phase-02d-walking-skeleton.md#p02d-1-decision-pass-2026-09-14), +[P02d-1's decision pass](../roadmap/phase-02d-delivery-log.md#p02d-1-decision-pass-2026-09-14), before implementation. The original Decision and Status history remain unchanged. ### What the pass verified @@ -487,7 +487,7 @@ scheduling grants, without envelope/payload SELECT or business-table access. This is an additive navigation disclosure, not an ADR-0041 correction or a claim that this ADR contained an outbox-only grant clause. Original acceptance metadata, body and prior amendments remain intact. Acceptance authorizes implementation; -[P02b-2's delivery record](../roadmap/phase-02b-events-auth.md#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) +[P02b-2's delivery record](../roadmap/phase-02b-delivery-log.md#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) owns evidence. The platform-admin gate and pre-entry audit remain unchanged. ## Amendment 8 — Background-job grant and table-class extension (2026-10-15) diff --git a/docs/decisions/0023-strongly-typed-id-source-generator.md b/docs/decisions/0023-strongly-typed-id-source-generator.md index 53c3cd31..21de97ef 100644 --- a/docs/decisions/0023-strongly-typed-id-source-generator.md +++ b/docs/decisions/0023-strongly-typed-id-source-generator.md @@ -569,7 +569,7 @@ the body, Decision, acceptance metadata and earlier amendments remain intact. [ADR-0046](0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) adds tenant and stable subscription to that natural identity; it still mints no surrogate. P02b-3 implements the shared table under its -[accepted package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). +[accepted package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). Carriers changed for this correction are this erratum/amendment, the ADR index, Database Standards' Inbox/Identifiers text and the phase package. Database Standards already excludes inbox from DB-side minting; its canonical DDL lands diff --git a/docs/decisions/0027-frontend-i18n.md b/docs/decisions/0027-frontend-i18n.md index 96ce1e45..618595dc 100644 --- a/docs/decisions/0027-frontend-i18n.md +++ b/docs/decisions/0027-frontend-i18n.md @@ -11,7 +11,7 @@ The maintainer accepted this reserved frontend-i18n decision and P02d-6 G39 befo implementation. At acceptance, no implementation is delivered; later delivery is recorded in dated amendments. P02d-6 owns the first consumer, and Phase 04 consumes that foundation. The -[P02d-6 decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +[P02d-6 decision package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) owns the page plan and approval boundary. ## Decision Drivers @@ -282,7 +282,7 @@ Step 1 also supplies document language/direction, atomic four-color style-elemen injection, tenant chrome, bounded interactive error labels, loading/state views and the live-admitted fixed status page, which performs no Education read. Catalog/course pages remain Step 2; lesson presentation remains Step 3. The -[Step 1 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[Step 1 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns current validation, review and product/accessibility proof status. The Decision, Status, Date and Deciders remain unchanged. @@ -297,7 +297,7 @@ Resolved API label language remains distinct from UI fallback language. Step 4 adds separate real API/production Next product modes for concurrent host/locale isolation, authored RTL content, atomic theme fallback, publication freshness and content-failure recovery. The -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) owns execution and review evidence. Actual manual keyboard, focus, reflow, contrast and screen-reader evidence remains pending; P6 completion and Accessibility promotion are not claimed. This delivery note changes no decision @@ -308,7 +308,7 @@ owns the browser demo and Lighthouse activation. ### Amendment 3 — P02d-6 manual accessibility closeout (2026-10-10) P02d-6 completes its four implementation steps and two independent review rounds -per step. The [packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +per step. The [packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records keyboard, focus, 320 CSS px desktop reflow and calculated contrast observations, followed by the maintainer's passing real VoiceOver checks on the English and Turkish catalog → course → lesson flows and missing/invalid-link @@ -334,7 +334,7 @@ unchanged. The original acceptance metadata, body and prior amendments remain historical; this is bounded supersession navigation, not a correction. Acceptance delivers no runtime implementation or passing production proof. The -[three-step plan](../roadmap/phase-02d-walking-skeleton.md#adr-0055-acceptance-and-implementation-plan-2026-10-10) +[three-step plan](../roadmap/phase-02d-delivery-log.md#adr-0055-acceptance-and-implementation-plan-2026-10-10) owns implementation, two independent review rounds per step and delivery status. ### Amendment 5 — Single-bootstrap loader delivery (2026-10-10) @@ -342,7 +342,7 @@ owns implementation, two independent review rounds per step and delivery status. ADR-0055's replacement admission loader is implemented. Middleware publishes one validated immutable snapshot; provenance-checked request, resource and UI consumers share it only during that native request. Content locale and UI fallback remain -separate. The [Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +separate. The [Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns actual production proof, validation and independent review status. The original acceptance metadata, body and earlier amendments remain historical. This delivery note changes no decision or manual accessibility claim. diff --git a/docs/decisions/0036-tenant-resolution-trusted-inputs.md b/docs/decisions/0036-tenant-resolution-trusted-inputs.md index dab350fa..19ac6c0c 100644 --- a/docs/decisions/0036-tenant-resolution-trusted-inputs.md +++ b/docs/decisions/0036-tenant-resolution-trusted-inputs.md @@ -1054,14 +1054,14 @@ immutable `HostScope`, matching public admission and host-scope intersection wit normal tenant/organization filters and RLS. Both independent review rounds and focused fix verification passed. [ADR-0052 Amendment 1](0052-anonymous-public-read-boundary.md#amendment-1--p02d-4-foundation-delivery-2026-10-03) -and the [Step 1 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-1-authority-and-read-only-foundation) +and the [Step 1 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-1-authority-and-read-only-foundation) own the implementation and evidence. Amendment 8 remains historical; the reconciliation matrix and trusted-input contract are unchanged. ### 2026-10-08 — Amendment 10: trusted public renderer decision navigation [ADR-0053](0053-trusted-public-server-rendering.md) is Accepted with the -[P02d-5 package](../roadmap/phase-02d-walking-skeleton.md#p02d-5-decision-package-2026-10-08). +[P02d-5 package](../roadmap/phase-02d-delivery-log.md#p02d-5-decision-package-2026-10-08). It owns three bounded replacements: authenticated visitor-IP limiting with a peer ceiling; a server-only configured header setter outside the injected SDK; and the mode-independent no-hop startup policy/minimum of 32 characters. All other host @@ -1121,7 +1121,7 @@ held by ADR-0047, not an ADR-0041 erratum. Implementation/proofs remain P02b-4. **Status: Accepted.** The maintainer accepts [ADR-0064](0064-tenant-api-authentication-boundary.md) and the -[P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19). +[P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19). Its [exact relationship to Accepted decisions](0064-tenant-api-authentication-boundary.md#exact-relationship-to-accepted-decisions) separates the following bounded supersession, additive contracts and fact correction. This is acceptance disclosure; P02b-5 runtime and its proofs are not delivered here. @@ -1233,7 +1233,7 @@ ADR-0065 also ratifies `c6108bf9`'s process-wide native HTTP/DNS metric projecti and discloses ordinary dependency attribution loss. This is bounded normative supersession, not an ADR-0041 fact correction. Original Accepted metadata/body, prior amendments and dated implementation receipts are preserved verbatim. The -[2026-10-20 remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[2026-10-20 remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns subsequent implementation and proof status; acceptance does not deliver it. ## References diff --git a/docs/decisions/0038-cross-cutting-port-and-event-contracts.md b/docs/decisions/0038-cross-cutting-port-and-event-contracts.md index 8a84b606..6299d71f 100644 --- a/docs/decisions/0038-cross-cutting-port-and-event-contracts.md +++ b/docs/decisions/0038-cross-cutting-port-and-event-contracts.md @@ -259,7 +259,7 @@ subscriber scheduling owns retry, terminalization and targeted internal replay. Transport diagnostics use closed reasons without logging raw handler exceptions or copied envelope data. The two real default subscriptions are Active. -The [Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +The [Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns runtime proofs, bounded production censuses and current review/PR status. Original acceptance metadata, body and previous amendments are unchanged. diff --git a/docs/decisions/0040-ambient-unit-of-work.md b/docs/decisions/0040-ambient-unit-of-work.md index b2472e91..a95b901b 100644 --- a/docs/decisions/0040-ambient-unit-of-work.md +++ b/docs/decisions/0040-ambient-unit-of-work.md @@ -679,7 +679,7 @@ physical read-only frames, same/mixed-mode joins, partial-setup cleanup, poisoni and reset behavior. Both independent review rounds and focused fix verification passed. [ADR-0052 Amendment 1](0052-anonymous-public-read-boundary.md#amendment-1--p02d-4-foundation-delivery-2026-10-03) records foundation delivery; the -[Step 1 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-1-authority-and-read-only-foundation) +[Step 1 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-1-authority-and-read-only-foundation) owns real app-role EF/SQL write refusal, writable controls and lifecycle evidence. The original Amendment 8 status remains historical. @@ -742,7 +742,7 @@ implements/proves these additive seams; public host eligibility is unchanged. **Status: Accepted.** The maintainer accepts [ADR-0064](0064-tenant-api-authentication-boundary.md) and the -[P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19). +[P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19). Its [exact relationship to Accepted decisions](0064-tenant-api-authentication-boundary.md#exact-relationship-to-accepted-decisions) extends Amendment 8's public-only mode-ordering scope to exactly the authenticated, non-`[PublicSurface]` `GetAccountSiteQuery`. This is a bounded normative extension diff --git a/docs/decisions/0044-audit-write-path.md b/docs/decisions/0044-audit-write-path.md index 44248f9d..5822227b 100644 --- a/docs/decisions/0044-audit-write-path.md +++ b/docs/decisions/0044-audit-write-path.md @@ -1156,7 +1156,7 @@ prior amendments remain intact. Acceptance authorizes implementation, not delive ## Amendment 11 — Shared delivery capture exclusions (2026-10-13) **Status: Accepted.** [ADR-0046](0046-durable-event-delivery-and-recovery.md#bounded-supersession-and-additive-seams) -and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13) +and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13) add `InboxMessage` and `EventDelivery` to § 7's named capture exclusions. The inbox is transport-owned completion identity; the delivery ledger retains envelopes and retry/terminal machinery. Neither is a second business aggregate. Explicit @@ -1184,7 +1184,7 @@ stored tenant/org/subscription/event identity and the live transaction; terminal state and audit commit together. The scheduler receives no payload or causal SELECT grant. Real-role identity substitutions, audit refusal and lost-COMMIT controls are recorded with the -[Step 4 implementation](../roadmap/phase-02b-events-auth.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13). +[Step 4 implementation](../roadmap/phase-02b-delivery-log.md#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13). The catalogue names the [row-bound terminal proof](../standards/21-architecture-tests-catalogue.md#delivery_terminal_audit_identity_is_row_bound). diff --git a/docs/decisions/0046-durable-event-delivery-and-recovery.md b/docs/decisions/0046-durable-event-delivery-and-recovery.md index 0adb7b7f..04d4f535 100644 --- a/docs/decisions/0046-durable-event-delivery-and-recovery.md +++ b/docs/decisions/0046-durable-event-delivery-and-recovery.md @@ -12,10 +12,10 @@ and [Amendment 2](#amendment-2--producer-enforcement-and-local-closeout-2026-10- The Status above records acceptance-time state; Amendment 2 records local producer closeout with PR-head CI and merge pending. Current CI/review/merge navigation (2026-10-12): the -[PR handoff](../roadmap/phase-02b-events-auth.md#p02b-2-pr-handoff-2026-10-12) +[PR handoff](../roadmap/phase-02b-delivery-log.md#p02b-2-pr-handoff-2026-10-12) links the live PR; the delivery notes retain their as-of status. -The [P02b-2 decision package](../roadmap/phase-02b-events-auth.md#p02b-2-decision-package-2026-10-12) +The [P02b-2 decision package](../roadmap/phase-02b-delivery-log.md#p02b-2-decision-package-2026-10-12) owns implementation sequencing and numerical runtime bounds. This reserved record decides producer dispatch and the coupled P02b-3 subscriber state machine before either is implemented. Acceptance does not claim delivery. @@ -447,10 +447,10 @@ confined composition, fenced claims/recovery/transitions with row-bound atomic terminal MUST audit, and the mandatory API-host processor with bounded publication ownership, observation and unmapped health. All three steps completed both independent review rounds. The -[Step 3 delivery record](../roadmap/phase-02b-events-auth.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) +[Step 3 delivery record](../roadmap/phase-02b-delivery-log.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) owns validation, reviewed corrections and the runtime proof scope. -[Step 4 enforcement and closeout](../roadmap/phase-02b-events-auth.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12) +[Step 4 enforcement and closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12) implements the full production censuses and planted controls; the focused 21-case census/publication run passes with zero skips and the remaining role/health catalogue rules are Implemented. Final regression, independent reviews and @@ -468,7 +468,7 @@ runtime proof without claiming durable consumer delivery. P02b-2 producer runtime and enforcement are locally complete. All four implementation steps completed both independent review rounds. The -[Step 4 delivery record](../roadmap/phase-02b-events-auth.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12) +[Step 4 delivery record](../roadmap/phase-02b-delivery-log.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12) records nonempty production credential/publication and observation censuses, planted controls, review findings and verified corrections. Test-only round-2 fixes at `606362b` pin exact source-reader method signatures, the actual @@ -504,7 +504,7 @@ audit classification and the one-root constructor-port rule. Planted missing, dirty and clean controls exercise these bounded checks; real PostgreSQL tests own ordering, isolation and atomicity. They do not claim arbitrary reflection or SQL transaction dataflow analysis. The -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns validation, independent reviews and PR/CI status. Earlier delivery notes retain their dated state. No exactly-once publication, cross-process ordering, operator replay route, purge, broker adapter or mapped readiness is delivered. diff --git a/docs/decisions/0047-transactional-background-job-runtime.md b/docs/decisions/0047-transactional-background-job-runtime.md index c5439964..b17b28de 100644 --- a/docs/decisions/0047-transactional-background-job-runtime.md +++ b/docs/decisions/0047-transactional-background-job-runtime.md @@ -9,7 +9,7 @@ Accepted — 2026-10-15. **Maintainer acceptance — 2026-10-15.** The maintainer approves H1 (stock Hangfire plus an authoritative LearnStack job record), this detailed contract, its bounded supersessions/additive seams and the expanded nine-step -[P02b-4 decision package](../roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15). +[P02b-4 decision package](../roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15). Acceptance and the dated disclosures are committed before runtime code, package changes, migrations or grants. Implementation and production job proofs remain pending; acceptance claims neither delivery nor enforcement. @@ -722,7 +722,7 @@ closeout. ## Implementation Notes -The [decision package](../roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15) +The [decision package](../roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15) owns nine implementation steps, option bounds, validation and carrier ownership. Acceptance/dated Amendments are committed before runtime. Canonical SQL/grants, metrics and catalogue rows land with implementation, not fictional passing status. @@ -869,7 +869,7 @@ This new normative qualification has explicit maintainer acceptance on 2026-10-16; it is not an ADR-0041 fact correction or an implicit reading of the earlier promise. This record's original Status, Date, Deciders, Decision and earlier amendment remain intact. ADR-0058 receives only an additive ownership -amendment. The [Step 4 acceptance record](../roadmap/phase-02b-events-auth.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) +amendment. The [Step 4 acceptance record](../roadmap/phase-02b-delivery-log.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) owns carrier inventory and implementation timing. Acceptance authorizes the adapted Step 4; actual worker/PostgreSQL, surface-parity, startup/resource, multi-pool and exit qualification remain mandatory before activation. No runtime @@ -930,7 +930,7 @@ through the prepared domain finalizer and atomic business/terminal MUST audit; Transient names this taxonomy, not resumability. Generic runtime validation does not certify the adapter's external causal truth. -The [P02b-4 acceptance record](../roadmap/phase-02b-events-auth.md#adr-0061-acceptance-and-step-7-contract-2026-10-17) +The [P02b-4 acceptance record](../roadmap/phase-02b-delivery-log.md#adr-0061-acceptance-and-step-7-contract-2026-10-17) owns acceptance and carrier synchronization. Step 7 implements and qualifies the report/storage/control/finalizer contract before external activation; Step 9 owns full enforcement and regression. The seven affected existing catalogue rules diff --git a/docs/decisions/0049-institution-sites-and-course-marketplace.md b/docs/decisions/0049-institution-sites-and-course-marketplace.md index 214dd5b7..91619685 100644 --- a/docs/decisions/0049-institution-sites-and-course-marketplace.md +++ b/docs/decisions/0049-institution-sites-and-course-marketplace.md @@ -27,7 +27,7 @@ not approval of unseen access or commerce contracts. This ADR remains Proposed. create a launch dependency. - LearnStack serves institutions that teach live. Buying content access, a cohort place, a session reservation or a consumable pack creates different obligations. -- [P02d-1](../roadmap/phase-02d-walking-skeleton.md#merge-and-closeout-2026-09-14) +- [P02d-1](../roadmap/phase-02d-delivery-log.md#merge-and-closeout-2026-09-14) shipped tenant-owned courses and lessons with isolation. Their first application writers and seed are delivered in P02d-2; [ADR-0050](0050-publication-and-course-content-access.md) @@ -105,12 +105,12 @@ keeps those choices separate. ### Publication, discovery and access -[G3's publication answer](../roadmap/phase-02d-walking-skeleton.md#p02d-1-accepted-answers) +[G3's publication answer](../roadmap/phase-02d-delivery-log.md#p02d-1-accepted-answers) closed on 2026-09-14 through ADR-0048. Hybrid direction endorsement alone did not reopen that public-only implication. The maintainer subsequently approved [ADR-0050](0050-publication-and-course-content-access.md) and the exact P02d-2 package on 2026-10-02; the -[dated G3 supersession](../roadmap/phase-02d-walking-skeleton.md#g3-supersession-2026-10-02) +[dated G3 supersession](../roadmap/phase-02d-delivery-log.md#g3-supersession-2026-10-02) preserves the original question, accepted answer and delivery history. ADR-0050 owns independent publication, persisted policy, restricted backfill and denial before anonymous lesson exposure. This marketplace proposal itself supersedes no ADR. diff --git a/docs/decisions/0050-publication-and-course-content-access.md b/docs/decisions/0050-publication-and-course-content-access.md index 5ebaf01e..b9d447f5 100644 --- a/docs/decisions/0050-publication-and-course-content-access.md +++ b/docs/decisions/0050-publication-and-course-content-access.md @@ -22,7 +22,7 @@ and P02d-2 decision package. Implementation has not started. **Date:** 2026-10-02 **Deciders:** Cemil (repository maintainer) **Relationship:** Supersedes ADR-0048. The dated -[G3 supersession](../roadmap/phase-02d-walking-skeleton.md#g3-supersession-2026-10-02) +[G3 supersession](../roadmap/phase-02d-delivery-log.md#g3-supersession-2026-10-02) preserves the original answer and delivery history. ## Decision Drivers @@ -164,7 +164,7 @@ implication changes when protected authoring is selected. This is a new decision not a correction of a false historical statement. The maintainer approved this contract on 2026-10-02. The -[dated G3 supersession](../roadmap/phase-02d-walking-skeleton.md#g3-supersession-2026-10-02) +[dated G3 supersession](../roadmap/phase-02d-delivery-log.md#g3-supersession-2026-10-02) records the current policy and packet obligations; ADR-0048 retains its original decision as history. Acceptance establishes the contract, not a shipped migration, writer or reader. @@ -209,7 +209,7 @@ one-root publication, concurrency and audit guards remain required. ## References - [Education module](../modules/education/README.md) -- [P02d-2 decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) +- [P02d-2 decision package](../roadmap/phase-02d-delivery-log.md#p02d-2-decision-package-2026-10-02) - [Course access terminology](../glossary.md#enrollment--access) - [Phase 05](../roadmap/phase-05-education-learning-content.md) - [Phase 07](../roadmap/phase-07-enrollment-learner-portal.md) @@ -238,7 +238,7 @@ Updated carriers: this status disclosure, [the ADR index](README.md), [Proposed ADR-0049](0049-institution-sites-and-course-marketplace.md), [Phase 04](../roadmap/phase-04-cms-media-pages.md) and [Phase 07](../roadmap/phase-07-enrollment-learner-portal.md). The -[P02d-2 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-2-implementation-delivery-2026-10-02) +[P02d-2 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-2-implementation-delivery-2026-10-02) is the current delivery authority. #### Amendment 2 — Status navigation (2026-10-02) @@ -254,7 +254,7 @@ and the 2026-10-02 status disclosure left pending. Eligible restricted courses expose marketing metadata without lesson inventory; lesson reads require an eligible public-policy parent. Hidden outcomes share the same refusal, and all GET/HEAD outcomes are no-store. Real app-role store/HTTP tests and the -[Step 3 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-3-public-education-reads) +[Step 3 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads) record the proof. Phase 07 still owns authenticated grants; P02d-5/6 own the server/page consumers. No merge or browser delivery is claimed. diff --git a/docs/decisions/0051-ordered-text-card-presentation.md b/docs/decisions/0051-ordered-text-card-presentation.md index 05fee628..8a612fa3 100644 --- a/docs/decisions/0051-ordered-text-card-presentation.md +++ b/docs/decisions/0051-ordered-text-card-presentation.md @@ -174,7 +174,7 @@ when their tests exist and run. ## References -- [P02d-2 decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) +- [P02d-2 decision package](../roadmap/phase-02d-delivery-log.md#p02d-2-decision-package-2026-10-02) - [Customization module](../modules/customization/README.md) - [Tenant customization model](../architecture/32-tenant-customization-model.md) - [Localization](../standards/08-localization.md) @@ -203,7 +203,7 @@ Updated carriers: this status disclosure, [the ADR index](README.md), [Proposed ADR-0049](0049-institution-sites-and-course-marketplace.md), [Phase 04](../roadmap/phase-04-cms-media-pages.md) and [Phase 07](../roadmap/phase-07-enrollment-learner-portal.md). The -[P02d-2 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-2-implementation-delivery-2026-10-02) +[P02d-2 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-2-implementation-delivery-2026-10-02) is the current delivery authority. #### Amendment 2 — Status navigation (2026-10-02) @@ -219,7 +219,7 @@ disclosure left pending. Exact eligible definitions supply ordered labels and plain string fields; unsupported/missing definitions or unsuitable selected content produce the bounded unavailable DTO. Reads do not repeat schema evaluation or rebind to a current revision. Display unit tests, app-role HTTP -tests and the [Step 3 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-3-public-education-reads) +tests and the [Step 3 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads) record the proof. P02d-6 still owns browser rendering, fallbacks and active-sink proofs; no browser delivery is claimed. @@ -234,7 +234,7 @@ P02d-6 completes ordered plain-string lesson rendering with authored field order resolved label language/direction, omitted absent optional fields and bounded unavailable states. HTML/script/URL-like values remain inert text. Unit and production HTML/RSC cases cover the actual product routes; the -[packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +[packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records automated evidence, two review rounds per step and passing manual browser/maintainer VoiceOver smoke. PR review and merge remain separate. diff --git a/docs/decisions/0052-anonymous-public-read-boundary.md b/docs/decisions/0052-anonymous-public-read-boundary.md index b005ee0f..7c35d742 100644 --- a/docs/decisions/0052-anonymous-public-read-boundary.md +++ b/docs/decisions/0052-anonymous-public-read-boundary.md @@ -18,7 +18,7 @@ Accepted — maintainer approval recorded 2026-10-03. Implementation is pending. **Date:** 2026-10-03 **Deciders:** @cemil -The [P02d-4 approval package](../roadmap/phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) +The [P02d-4 approval package](../roadmap/phase-02d-delivery-log.md#p02d-4-decision-package-2026-10-03) records the accepted public contracts, implementation steps and dated clarifications appended to ADR-0036 and ADR-0040. Implementation has not started. @@ -238,7 +238,7 @@ refusals have independent writable controls. Institution public endpoints, lifecycle/eligibility readers, HTTP controls and OpenAPI/SDK/CI proofs remain with Steps 2–4. The original Status and Architecture Tests sections record the acceptance baseline; the catalogue and -[P02d-4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-1-authority-and-read-only-foundation) +[P02d-4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-1-authority-and-read-only-foundation) own current implementation and review evidence. ## Amendment 2 — P02d-4 site bootstrap delivery (2026-10-03) @@ -252,7 +252,7 @@ have planted positive and negative cases. PostgreSQL-backed HTTP cases exercise lifecycle withdrawal, locale emptiness/invalidity, whole-theme/null and effective attribution. Education reads and full OpenAPI/SDK/CI proof remain Steps 3–4. -The [packet delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-2-public-site-bootstrap) +The [packet delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-2-public-site-bootstrap) owns validation and both review rounds; it does not mark the whole packet complete. ## Amendment 3 — P02d-4 Education read delivery (2026-10-04) @@ -268,7 +268,7 @@ locale and bounded scoped seek cursors precede data selection. The no-schema-evaluation guard has a non-empty production handler census and planted transitive controls. Real PostgreSQL/HTTP cases and actual consumer EXPLAIN plans are recorded in the -[Step 3 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-3-public-education-reads). +[Step 3 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads). Both independent review rounds are pending at this implementation boundary. Full served/snapshot OpenAPI, SDK and required CI proof remain Step 4. @@ -277,7 +277,7 @@ Full served/snapshot OpenAPI, SDK and required CI proof remain Step 4. This delivery note changes no decision. Both independent Step 3 review rounds are complete. The verified Unicode cursor defect is fixed with bounded refusal and real HTTP controls; no verified finding remains after fresh Round 2 review. -The [Step 3 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-3-public-education-reads) +The [Step 3 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads) owns review and verification evidence. Contract/SDK/CI delivery remains Step 4. ## Amendment 5 — contract, SDK and CI implementation (2026-10-04) @@ -290,7 +290,7 @@ drift. Always-running OpenAPI CI uses the pinned compatibility policy, mutation fixtures and explicit companions for open-enum tool gaps; current response enums remain closed. Verified operation-free base composition is the only bootstrap. -The [Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +The [Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns actual verification, the two independent review rounds and the approved live sixth-check rollout. Reviews and settings activation remain pending at this implementation boundary. P02d-5/6 remain the server consumer/browser owners. @@ -304,7 +304,7 @@ references; additional CLI controls prove the previously missed changes fail. Problem Details parameter schema and SDK parsing match the existing string-valued localized-message carrier. Invalid local path encoding returns a bounded result, and caller cancellation retains precedence. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns reproduction and regression evidence. Fresh Round 2 and the approved live sixth-check registration remain pending at this fix boundary. @@ -316,7 +316,7 @@ content-form parameter/header schemas. Per-occurrence materialization, immutable analysis and tool-supported policy projections close those gaps while preserving nonbreaking controls. Exact dot segments remain inside the SDK refusal boundary; extra-operation contract mutants supply the promised regression proof. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns the verified findings and fix evidence. Fresh focused review and live sixth required-check activation remain pending at this fix boundary. @@ -327,7 +327,7 @@ fixes and identifies an incompatible refusal of a recursive open-enum addition. Private effective recursive schema copies now keep cycle edges inside the normalized policy graph, preserving closed consumers and stable identity across documentation changes. Six added CLI controls complement the earlier matrix. -The [Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +The [Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns proof and final review evidence. Live sixth-check activation is still pending. ## Amendment 9 — inline recursive comparison fix (2026-10-04) @@ -336,7 +336,7 @@ This delivery note changes no decision. Final focused review identifies recursiv normalization using an unstable traversal identity outside Schema components. Stable declaration origins now cover inline schemas and schemas inside Response components, with unchanged/open-addition CLI controls for both placements. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns reproduction and fresh verification. Live sixth-check activation is pending. ## Amendment 10 — implementation and review closeout (2026-10-04) @@ -344,7 +344,7 @@ owns reproduction and fresh verification. Live sixth-check activation is pending This delivery note changes no decision. All four P02d-4 implementation steps and their two independent review rounds are complete. Fresh focused verification of the final compatibility fixes approves, with no verified finding remaining. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns the complete regression and final control counts. Actual PR CI and live sixth required-check registration remain the final rollout proof; this note does not claim merge or browser delivery. P02d-5/6 remain the server/page owners. @@ -355,7 +355,7 @@ This delivery note changes no decision. All six real PR CI jobs pass. After the successful `openapi diff` job, its approved sixth required GitHub Actions context is activated; full API read-back proves strict checking and every other live protection setting preserved. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns the exact head, run, artifacts and activation proof. P02d-4 implementation, review loops and rollout are complete in [PR #25](https://github.com/HodeTech/LearnStack/pull/25), awaiting maintainer @@ -372,7 +372,7 @@ contract/SDK/CI delivery, reviews and required-check activation. [ADR-0036 Amendment 9](0036-tenant-resolution-trusted-inputs.md#2026-10-05--amendment-9-public-host-provenance-delivery) and ADR-0050/0051 Amendment 3 record their delivered P02d-4 parts without rewriting acceptance history. The -[Step 4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[Step 4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) owns current verification. PR #25 awaits maintainer review/merge; server/page consumers remain P02d-5/6. @@ -384,7 +384,7 @@ the Education module spec and the P02d-4 delivery record. This delivery note changes no decision. The maintainer merged [PR #25](https://github.com/HodeTech/LearnStack/pull/25) on 2026-10-08. All four P02d-4 steps, their two-round reviews and the approved required-check rollout -are complete. The [merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-4-merge-and-closeout-2026-10-08) +are complete. The [merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-4-merge-and-closeout-2026-10-08) owns the final head, merge/tree proof and verification evidence. The original Status, Date, Deciders and previous delivery notes remain unchanged as history. P02d-5/6 retain server/page delivery; Phase 02d remains in progress. @@ -409,7 +409,7 @@ P02b-4 implements/proves this bounded extension; no new public runtime is claime **Status: Accepted.** The maintainer accepts [ADR-0064](0064-tenant-api-authentication-boundary.md) and the -[P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19). +[P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19). Its [exact relationship to Accepted decisions](0064-tenant-api-authentication-boundary.md#exact-relationship-to-accepted-decisions) extends this ADR's Decision/Context authorization of mode-before-announcement ordering to exactly the authenticated, non-`[PublicSurface]` diff --git a/docs/decisions/0053-trusted-public-server-rendering.md b/docs/decisions/0053-trusted-public-server-rendering.md index 8191bc2b..fdf7841c 100644 --- a/docs/decisions/0053-trusted-public-server-rendering.md +++ b/docs/decisions/0053-trusted-public-server-rendering.md @@ -7,7 +7,7 @@ Accepted — 2026-10-08. The maintainer approved this ADR and the P02d-5 package **Date:** 2026-10-08 **Deciders:** @cemil -The [P02d-5 decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-5-decision-package-2026-10-08) +The [P02d-5 decision package](../roadmap/phase-02d-delivery-log.md#p02d-5-decision-package-2026-10-08) contains the exact defaults, entry matrix, delivery steps and proof obligations. At acceptance, implementation has not started. The bounded replacements below apply; all other Accepted contracts remain authoritative. @@ -210,7 +210,7 @@ not an automatic side effect of repository commands. ## Implementation Notes -The [packet plan](../roadmap/phase-02d-walking-skeleton.md#p02d-5-implementation-plan) +The [packet plan](../roadmap/phase-02d-delivery-log.md#p02d-5-implementation-plan) owns defaults, carrier updates, review rounds and scope by step. Acceptance updates ongoing standards and appends ADR-0036 navigation before code. Delivery notes record implementation separately; acceptance is not runtime evidence. @@ -239,7 +239,7 @@ The root private environment source, optional matching web projection and paired loopback API launcher are delivered. The native launcher provides readiness; stock Next with forged provenance is refused by the middleware foundation. -The [Step 1 record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-step-1--native-ingress-and-local-topology) +The [Step 1 record](../roadmap/phase-02d-delivery-log.md#p02d-5-step-1--native-ingress-and-local-topology) owns validation and review evidence. Step 2 still owns visitor budgets; Step 3 owns configured API transport/bootstrap/entry; Step 4 owns mechanical fences and complete production integration. TLS socket/production-launch controls are not a @@ -255,7 +255,7 @@ sanitation also removes Next's routing, resumption and revalidation controls. Next's documented `httpServer` option points at a non-listening upgrade sink: only admitted native TLS upgrades reach it, including development HMR. -The [Step 1 record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-step-1--native-ingress-and-local-topology) +The [Step 1 record](../roadmap/phase-02d-delivery-log.md#p02d-5-step-1--native-ingress-and-local-topology) owns production/socket, mutation and cleanup evidence. Steps 2–4 retain their scopes; this note changes no Accepted decision or browser-readiness claim. @@ -267,7 +267,7 @@ traffic, and chained 600/physical-peer plus 60/visitor-IP fixed-window budgets. The peer ceiling runs first; invalid trusted metadata spends fallback quota and receives masked `404` before host classification. Untrusted metadata is ignored. -The [Step 2 record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-step-2--api-visitor-admission-and-budgets) +The [Step 2 record](../roadmap/phase-02d-delivery-log.md#p02d-5-step-2--api-visitor-admission-and-budgets) owns validation and review evidence. Empty-hop startup, API tenant authority, rotation-list support and existing public response contracts remain unchanged. Configured frontend transport and full renderer proofs still belong to Steps 3–4. @@ -281,7 +281,7 @@ before live bootstrap, applies membership-first locale entry, preserves inert ra query bytes and rebuilds downstream request headers. The public layout is dynamic and no-store. Neither bootstrap nor SDK responses enter a shared renderer cache. -The [Step 3 record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-step-3--configured-caller-and-public-entry) +The [Step 3 record](../roadmap/phase-02d-delivery-log.md#p02d-5-step-3--configured-caller-and-public-entry) owns validation and reviews. Step 4 still owns complete production-build integration and mechanical frontend fences; P6 owns public page composition. This delivery note changes no Accepted decision or browser-readiness claim. @@ -300,7 +300,7 @@ Component import fails the build, stock-Next forgeries cannot bootstrap, and pri values stay out of responses, client assets and logs. Bootstrap/rendering share a request-local trace even when incoming trace context is absent or invalid. -The [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-step-4--frontend-fences-and-production-integration) +The [Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-5-step-4--frontend-fences-and-production-integration) owns validation and independent reviews. Test-owned routes are not P6 product pages or P7 browser/Lighthouse delivery. The original Accepted body is unchanged. @@ -311,7 +311,7 @@ fixes. The final source controls follow bounded static declaration and ESM value origins, preserving explicit export precedence and request-local React caching. Owned fixture cleanup proves process-group absence even when a leader exits first. -The [packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-packet-closeout-2026-10-09) +The [packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-packet-closeout-2026-10-09) owns test counts, scope and handoff. P02d-5 is implementation-complete and unmerged; maintainer PR review remains. P02d-6 owns product page composition and its decision pass; P02d-7 owns the browser demo and Lighthouse. No Accepted decision, original @@ -338,7 +338,7 @@ redirect-query encoding promise: The original Accepted body, metadata and Amendments 1–6 remain historical. All other contracts remain authoritative; no API tenant authority, public wire contract -or local topology changes. The [remediation record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) +or local topology changes. The [remediation record](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) owns current status. Acceptance delivers no runtime correction or new test/CI result; each implementation step still owes validation and two independent reviews. @@ -346,7 +346,7 @@ result; each implementation step still owes validation and two independent revie P02d-5 and its ADR-0054 remediation are complete and merged through [PR #26](https://github.com/HodeTech/LearnStack/pull/26). The -[merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) +[merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) owns the final head, merge verification and CI evidence. Original acceptance metadata and prior amendments remain historical. This delivery note changes no decision; P02d-6 product pages and P02d-7 browser/demo/Lighthouse remain separate. @@ -367,7 +367,7 @@ numeric quotas and content-error/missing-detail status policies are unchanged. This is bounded supersession navigation. The original body, metadata and earlier delivery notes remain historical. Acceptance delivers no implementation or passing production proof; the -[three-step plan](../roadmap/phase-02d-walking-skeleton.md#adr-0055-acceptance-and-implementation-plan-2026-10-10) +[three-step plan](../roadmap/phase-02d-delivery-log.md#adr-0055-acceptance-and-implementation-plan-2026-10-10) owns execution and review evidence. ### Amendment 10 — Single-bootstrap production delivery (2026-10-10) @@ -377,7 +377,7 @@ are implemented. Actual production Next/API/PostgreSQL proofs preserve ingress, isolation, content states and the two/one/three-call contract; the additional fixture covers exact bootstrap refusals, concurrent snapshots, native lifetime, stock browser fallback and fresh development admission. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns execution and independent review status. This delivery note leaves the original acceptance metadata, body and earlier amendments unchanged; it adds no P7 browser-demo, full accessibility or production deployment claim. diff --git a/docs/decisions/0054-bounded-public-renderer-admission.md b/docs/decisions/0054-bounded-public-renderer-admission.md index a1fed57c..ca43c380 100644 --- a/docs/decisions/0054-bounded-public-renderer-admission.md +++ b/docs/decisions/0054-bounded-public-renderer-admission.md @@ -213,7 +213,7 @@ reuse and P6 prefetch/page choices are not delivered by accepting this ADR. ## Implementation Notes -P02d-5's [remediation plan](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) +P02d-5's [remediation plan](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) owns implementation and review steps. Acceptance appends dated bounded supersession/navigation to ADR-0053 for accounting, web method/upgrade admission and redirect-query wording, preserving its original body and delivery history. @@ -224,7 +224,7 @@ Host normalization, trusted-input resolution and assertion-only tenant authority remain unchanged. Update ongoing Standards 04/07/11, Architecture 14/25, phase/route guidance and catalogue entries with their concrete enforcing tests. Existing -[G34/G36 acceptance](../roadmap/phase-02d-walking-skeleton.md#p02d-5-accepted-answers) +[G34/G36 acceptance](../roadmap/phase-02d-delivery-log.md#p02d-5-accepted-answers) is historical; record this replacement explicitly rather than reopening it silently. In [TrustedVisitorHttpTests](../../backend/tests/LearnStack.Tests.Integration/Database/TrustedVisitorHttpTests.cs), @@ -275,7 +275,7 @@ owned visitor limiters, request-result snapshots, bounded idle sweeping and join DI teardown. Native method/upgrade and URL controls remain pending Step 2. The original acceptance status records the state when accepted; implementation does not rewrite it. Concrete execution and review evidence lives in the -[Step 1 delivery record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-1--coordinated-anonymous-admission) +[Step 1 delivery record](../roadmap/phase-02d-delivery-log.md#remediation-step-1--coordinated-anonymous-admission) and ongoing [catalogue entry](../standards/21-architecture-tests-catalogue.md#anonymous_requests_are_rate_limited_per_peer). ### Amendment 2 — Native and URL implementation (2026-10-09) @@ -283,7 +283,7 @@ and ongoing [catalogue entry](../standards/21-architecture-tests-catalogue.md#an **Delivery note; independent reviews pending.** Remediation Step 2 implements the native method/upgrade and URL portions of this decision. Current enforcement and concrete execution/review evidence live in [Frontend Standards](../standards/07-frontend-architecture.md#native-admission-and-url-identity) -and the [Step 2 record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-2--native-ingress-and-url-boundary). +and the [Step 2 record](../roadmap/phase-02d-delivery-log.md#remediation-step-2--native-ingress-and-url-boundary). Step 1's accounting implementation has completed both independent review rounds. The accepted decision and prior delivery notes remain unchanged; fixture/tooling remediation and final PR closeout remain Steps 3–5. @@ -294,7 +294,7 @@ remediation and final PR closeout remain Steps 3–5. owned fixture lifecycle and falsifiable containment controls. The decision and prior delivery notes remain unchanged. Ongoing rules live in [Testing Standards](../standards/06-testing.md#public-renderer-fixture-ownership), concrete enforcing tests in the [catalogue](../standards/21-architecture-tests-catalogue.md#p02d-5-public-server-rendering-controls), -and execution/review evidence in the [Step 3 record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-3--fixture-reliability-and-containment). +and execution/review evidence in the [Step 3 record](../roadmap/phase-02d-delivery-log.md#remediation-step-3--fixture-reliability-and-containment). Source/tooling remediation and final PR closeout remain Steps 4–5. ### Amendment 4 — Source and tooling proof implementation (2026-10-09) @@ -304,7 +304,7 @@ bounded source-analysis, runner, lint and CI evidence corrections without changi this decision. Current rules live in [Frontend Coding Standards](../standards/03-frontend-coding.md#current-toolchain-and-lint-subjects) and [Frontend Architecture Standards](../standards/07-frontend-architecture.md#public-source-fence-scope). The [catalogue](../standards/21-architecture-tests-catalogue.md#p02d-5-public-server-rendering-controls) -names enforcing controls; the [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-4--source-runner-and-tooling-proof) +names enforcing controls; the [Step 4 record](../roadmap/phase-02d-delivery-log.md#remediation-step-4--source-runner-and-tooling-proof) owns execution/review evidence. Final corpus/CI/PR closeout remains Step 5. ### Amendment 5 — Remediation delivery navigation (2026-10-09) @@ -312,15 +312,15 @@ owns execution/review evidence. Final corpus/CI/PR closeout remains Step 5. **Delivery note.** All four runtime/proof remediation steps are delivered after both independent review rounds and verified corrections. The original acceptance and earlier delivery notes remain historical. Current implementation, validation, -reviews and unmerged PR readiness live in the [five-step remediation record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09), -including its [corpus/PR closeout](../roadmap/phase-02d-walking-skeleton.md#remediation-step-5--corpus-and-pr-closeout). +reviews and unmerged PR readiness live in the [five-step remediation record](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09), +including its [corpus/PR closeout](../roadmap/phase-02d-delivery-log.md#remediation-step-5--corpus-and-pr-closeout). This adds delivery navigation, not a new decision or a claim that PR #26 is merged. ### Amendment 6 — Merge closeout (2026-10-09) All five remediation steps are complete and merged through [PR #26](https://github.com/HodeTech/LearnStack/pull/26). The -[merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) +[merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) owns the final head, merge verification and CI evidence. The accepted decision, metadata and earlier delivery notes remain unchanged. This note records delivery only; P02d-6/7 and Phase 11 retain their named work. @@ -331,7 +331,7 @@ only; P02d-6/7 and Phase 11 retain their named work. The current verified runtime pin is Next 15.5.27 with matching eslint-config-next. The signed raw target, full-URL RSC projection and equivalent redirect-query contract are unchanged. The unused image optimizer is disabled. P02d-6's -[remediation record](../roadmap/phase-02d-walking-skeleton.md#remediation-group-3--approved-security-maintenance) +[remediation record](../roadmap/phase-02d-delivery-log.md#remediation-group-3--approved-security-maintenance) owns the replacement native/production proofs and dependency triage; historical 15.5.18 observations remain unchanged. @@ -342,7 +342,7 @@ The maintainer accepted bootstrap reuse left undelivered in this record's Context. Middleware performs one live site read and owns bootstrap refusal responses; RSC consumes the immutable same-request snapshot. Implementation and production proofs remain pending under -the [three-step plan](../roadmap/phase-02d-walking-skeleton.md#adr-0055-acceptance-and-implementation-plan-2026-10-10). +the [three-step plan](../roadmap/phase-02d-delivery-log.md#adr-0055-acceptance-and-implementation-plan-2026-10-10). ADR-0055 qualifies only the renderer forwarding boundary of [Anonymous accounting](#anonymous-accounting)'s instruction to use the selected @@ -360,7 +360,7 @@ ADR-0055's single-bootstrap reuse and bounded renderer Retry-After qualification are implemented. Real wire proofs cover supported 404/429/503, eligible zero/sixty boundaries, omitted invalid values and bodyless HEAD. API accounting, original API metadata and numeric budgets remain unchanged. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns execution and independent review status. This delivery note preserves the original acceptance metadata, body and all earlier amendments. diff --git a/docs/decisions/0055-public-renderer-bootstrap-failures.md b/docs/decisions/0055-public-renderer-bootstrap-failures.md index fe6acd11..3dfa17e1 100644 --- a/docs/decisions/0055-public-renderer-bootstrap-failures.md +++ b/docs/decisions/0055-public-renderer-bootstrap-failures.md @@ -323,7 +323,7 @@ shutdown, keep-alive, stock browser Flight fallback and development source/API refresh. Public success and Problem Details media types are enforced before SDK parsing under the existing API contract. -The [Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +The [Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns executed checks, verified corrections and independent review status. Five catalogue rules are Implemented with named executable owners. The original acceptance metadata, decision and prior feasibility observations remain historical; @@ -336,7 +336,7 @@ this delivery note changes no decision or P7/Phase 06 scope. - [ADR-0052 — Anonymous Public Read Boundary](0052-anonymous-public-read-boundary.md) - [ADR-0053 — Trusted Public Server Rendering](0053-trusted-public-server-rendering.md) - [ADR-0054 — Bounded Public Renderer Admission](0054-bounded-public-renderer-admission.md) -- [P02d-6 review decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-systematic-review-decision-package-2026-10-10) +- [P02d-6 review decision package](../roadmap/phase-02d-delivery-log.md#p02d-6-systematic-review-decision-package-2026-10-10) - [Native launcher](../../frontend/apps/web/scripts/public-server.mjs) - [Middleware](../../frontend/apps/web/src/middleware.ts) - [RSC admission loader](../../frontend/apps/web/src/server/public-request.ts) diff --git a/docs/decisions/0056-public-demo-browser-and-lighthouse-enforcement.md b/docs/decisions/0056-public-demo-browser-and-lighthouse-enforcement.md index 79098314..f6934600 100644 --- a/docs/decisions/0056-public-demo-browser-and-lighthouse-enforcement.md +++ b/docs/decisions/0056-public-demo-browser-and-lighthouse-enforcement.md @@ -55,7 +55,7 @@ runs these checks without changing the production anonymous admission budgets. The maintainer accepted this enforcement decision on 2026-10-11. It implements P02d-7's remaining G33/G38/G44 evidence; the -[phase package](../roadmap/phase-02d-walking-skeleton.md#p02d-7-decision-package-2026-10-10) +[phase package](../roadmap/phase-02d-delivery-log.md#p02d-7-decision-package-2026-10-10) owns G20, G45, implementation steps and phase exit. The maintainer approved that package's lifecycle and bounded seventh-check activation on 2026-10-11; this revised ADR is accepted on the same date. G45 names the approved `make demo` @@ -318,7 +318,7 @@ owned cleanup. Per-URL timing medians remain advisory. The first real [PR run](https://github.com/HodeTech/LearnStack/actions/runs/38106505383) passes all seven jobs. Its complete sanitized artifacts and the subsequent authorized seventh-context activation/full protection read-back are verified in -the [CI and exit closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11). +the [CI and exit closeout](../roadmap/phase-02d-delivery-log.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11). PR #28 remains subject to maintainer review and merge. This is delivery navigation; the acceptance metadata, decision and feasibility obligations remain unchanged. Existing P6 human/VoiceOver evidence and Phase 06/11 scope retain their limits. @@ -327,14 +327,14 @@ Existing P6 human/VoiceOver evidence and Phase 06/11 scope retain their limits. The original no-implementation sentence describes acceptance-time state. Amendment 1 describes later delivery and the first real run used for activation. -The [reviewed-head verification](../roadmap/phase-02d-walking-skeleton.md#reviewed-implementation-head-verification-2026-10-11) +The [reviewed-head verification](../roadmap/phase-02d-delivery-log.md#reviewed-implementation-head-verification-2026-10-11) separately records source `d47ef17` and its downloaded successful CI artifacts. Subsequent heads remain subject to all seven required checks. This clarification changes no decision, tool version, budget or original acceptance metadata. ## References -- [P02d-7 package](../roadmap/phase-02d-walking-skeleton.md#p02d-7-decision-package-2026-10-10). +- [P02d-7 package](../roadmap/phase-02d-delivery-log.md#p02d-7-decision-package-2026-10-10). - [Performance Standards](../standards/15-performance.md). - [Testing Standards](../standards/06-testing.md#end-to-end-tests). - [Accessibility Standards](../standards/16-accessibility.md#tooling). diff --git a/docs/decisions/0057-transactional-event-production-and-completion.md b/docs/decisions/0057-transactional-event-production-and-completion.md index dfbffa2d..11948ada 100644 --- a/docs/decisions/0057-transactional-event-production-and-completion.md +++ b/docs/decisions/0057-transactional-event-production-and-completion.md @@ -11,7 +11,7 @@ **Accepted — 2026-10-12.** The maintainer approves the bounded supersessions below and the -[P02b-1 decision package](../roadmap/phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12). +[P02b-1 decision package](../roadmap/phase-02b-delivery-log.md#p02b-1-decision-package-2026-10-12). **Bounded supersession:** ADR-0032 Sub-decision 2's step-7 completion role and Sub-decision 12 / Architecture Tests' separate `event_id` @@ -37,7 +37,7 @@ factual correction. outer caller absorbs the refusal. Joined frames are not savepoints under [ADR-0040 § Nesting](0040-ambient-unit-of-work.md#nesting). - Establish a useful production subject using the declared tenant defaults; - [P02b-0's audit](../roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) + [P02b-0's audit](../roadmap/phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) finds no useful invalidation effect for already fresh or uncached readers. ## Considered Options @@ -252,7 +252,7 @@ source MUST audit already commits with the producer. ## Context -[P02b-0](../roadmap/phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) +[P02b-0](../roadmap/phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) re-verified an existing outbox table and transport seam, but no enqueue port, collector, domain publisher or useful production consumer. ADR-0032's step-7 target predates an implemented producer. It cannot own completion for direct @@ -388,7 +388,7 @@ producer rules in the The acceptance-time Registered statements above remain historical commitments; the catalogue now records their implementing tests. -The [Step 4 delivery record](../roadmap/phase-02b-events-auth.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) +The [Step 4 delivery record](../roadmap/phase-02b-delivery-log.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns final validation, independent reviews and packet status. This delivery note changes no decision or original acceptance metadata. Dispatcher/lease work remains P02b-2; production inbox/subscriptions and the Seeder identity handoff @@ -410,7 +410,7 @@ section so that the entire original section, Date and Deciders remain intact. The accepted body wording is retained. The mutable carriers corrected are [Phase 02b](../roadmap/phase-02b-events-auth.md#the-decision-register)'s G5 register row and -[accepted G5 answer](../roadmap/phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12), +[accepted G5 answer](../roadmap/phase-02b-delivery-log.md#p02b-1-decision-package-2026-10-12), plus this amendment's entry in the [ADR index](README.md). These are all carriers changed for this locator correction. The Decision and the exact bounded supersession are unchanged: the two historical separate-column @@ -431,7 +431,7 @@ exact Active shape. Warm/generated IDs survive; authored identities and exact pins remain strict. App-role tests cover backlog and fresh provisioning, independent inbox effects, audit rollback, duplicate acceptance and both winning orders of Seeder/subscriber races. The -[Step 5 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +[Step 5 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns validation and review status; Step 6 retains production-census enforcement and full packet closeout. Earlier dated delivery notes retain their as-of state. diff --git a/docs/decisions/0058-bounded-stock-hangfire-maintenance.md b/docs/decisions/0058-bounded-stock-hangfire-maintenance.md index 25322933..8cf68830 100644 --- a/docs/decisions/0058-bounded-stock-hangfire-maintenance.md +++ b/docs/decisions/0058-bounded-stock-hangfire-maintenance.md @@ -181,7 +181,7 @@ An independent update succeeds before the client reads the timeout response. Idle-in-transaction timeout then terminates the remaining backend. Two 350 ms statements succeed with a 500 ms statement budget; that budget is per statement. The commands, measurements and their limitations belong to the -[Step 2 decision receipt](../roadmap/phase-02b-events-auth.md#step-2-maintenance-reassessment). +[Step 2 decision receipt](../roadmap/phase-02b-delivery-log.md#step-2-maintenance-reassessment). **What changes this decision:** a required vendor dashboard/history contract or qualified finite-timeout upstream aggregator triggers renewed comparison. Loss @@ -264,7 +264,7 @@ P02b-4 Step 2 implements the shared five-second idle-session setting and proves cold/warm reset, real idle/aborted-idle cleanup and healthy source reuse alongside existing outbox/delivery transactions. Both fresh step reviews and verified-fix checks are complete; the -[Step 2 closeout](../roadmap/phase-02b-events-auth.md#step-2-final-proof-and-closeout) +[Step 2 closeout](../roadmap/phase-02b-delivery-log.md#step-2-final-proof-and-closeout) owns exact commit, regression and distribution evidence. The earlier pending wording records acceptance-time state. Step 4 component/filter selection, expiration ownership and supported-pool progress, and Step 9 full enforcement @@ -303,7 +303,7 @@ pending. Acceptance claims no implemented maintenance or heartbeat owner. ## References - [ADR-0047](0047-transactional-background-job-runtime.md). -- [P02b-4 decision package](../roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15). +- [P02b-4 decision package](../roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15). - [Database Standards](../standards/05-database.md). - [Infrastructure Standards](../standards/20-infrastructure-stack.md). - [Architecture-test catalogue](../standards/21-architecture-tests-catalogue.md). diff --git a/docs/decisions/0059-owned-hangfire-server-generations.md b/docs/decisions/0059-owned-hangfire-server-generations.md index 1c85bf97..51816519 100644 --- a/docs/decisions/0059-owned-hangfire-server-generations.md +++ b/docs/decisions/0059-owned-hangfire-server-generations.md @@ -455,7 +455,7 @@ signals on Core tokens, the positive child exits while an actual stock process and a private cancellation callback remain held. A test-only observer confirms Core reached its forced shutdown signal. This proves neither actual cleanup nor production callback confinement; final teardown aborts unresolved background work. -The [Step 4 decision receipt](../roadmap/phase-02b-events-auth.md#p02b-4-step-4--server-generation-decision-2026-10-16) +The [Step 4 decision receipt](../roadmap/phase-02b-delivery-log.md#p02b-4-step-4--server-generation-decision-2026-10-16) owns reproducible commands, results and limits; experiments are not shipped enforcement or acceptance. diff --git a/docs/decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md b/docs/decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md index dda7aa7f..6a3c825c 100644 --- a/docs/decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md +++ b/docs/decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md @@ -353,7 +353,7 @@ refuses qualification; no skip or synthetic-to-production inference closes the g - [ADR-0047](0047-transactional-background-job-runtime.md), [ADR-0058](0058-bounded-stock-hangfire-maintenance.md), [ADR-0059](0059-owned-hangfire-server-generations.md). -- [P02b-4 Step 4 acceptance](../roadmap/phase-02b-events-auth.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16). +- [P02b-4 Step 4 acceptance](../roadmap/phase-02b-delivery-log.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16). - [Phase 11 Reliability](../roadmap/phase-11-production-hardening.md#reliability). - [Phase 04](../roadmap/phase-04-cms-media-pages.md), [Phase 03](../roadmap/phase-03-identity-admin.md). diff --git a/docs/decisions/0061-known-external-job-failure-policy.md b/docs/decisions/0061-known-external-job-failure-policy.md index 42d40129..120c0b29 100644 --- a/docs/decisions/0061-known-external-job-failure-policy.md +++ b/docs/decisions/0061-known-external-job-failure-policy.md @@ -368,7 +368,7 @@ path without claiming that uncommitted facts survive process death. - [Decision index](README.md) and [Background Jobs glossary](../glossary.md#background-jobs). - [ADR-0040](0040-ambient-unit-of-work.md), [ADR-0044](0044-audit-write-path.md) and [Documentation Standards](../standards/13-documentation.md). -- [P02b-4 proposal and acceptance gate](../roadmap/phase-02b-events-auth.md#p02b-4-external-completed-failure-proposal-2026-10-16). +- [P02b-4 proposal and acceptance gate](../roadmap/phase-02b-delivery-log.md#p02b-4-external-completed-failure-proposal-2026-10-16). - [ADR-0047](0047-transactional-background-job-runtime.md), [ADR-0058](0058-bounded-stock-hangfire-maintenance.md), [ADR-0059](0059-owned-hangfire-server-generations.md), [ADR-0060](0060-fatal-hangfire-startup-and-unsafe-unwind.md). - [Database Standards](../standards/05-database.md#background-jobs), [Error Handling](../standards/09-error-handling.md#background-jobs), [Infrastructure Stack](../standards/20-infrastructure-stack.md#background-jobs-and-hangfire). - [Architecture Tests Catalogue](../standards/21-architecture-tests-catalogue.md#p02b-4-background-job-obligations), [Audit Coverage](../standards/18-audit-coverage.md), [Events and Outbox](../architecture/15-event-and-outbox.md). diff --git a/docs/decisions/0062-native-crash-proof-ci-provisioning.md b/docs/decisions/0062-native-crash-proof-ci-provisioning.md index d6922dcd..caf28680 100644 --- a/docs/decisions/0062-native-crash-proof-ci-provisioning.md +++ b/docs/decisions/0062-native-crash-proof-ci-provisioning.md @@ -190,7 +190,7 @@ Integration setup took 2:13, leaving only 15:17 under the old proposed deadline. Three older green Docker test steps took 12:20, 12:52 and 16:52 before this native workload. They warn against the old reserve; they do not measure current source. -The owning [CI follow-up](../roadmap/phase-02b-events-auth.md#hosted-ci-qualification-follow-up-2026-10-18) +The owning [CI follow-up](../roadmap/phase-02b-delivery-log.md#hosted-ci-qualification-follow-up-2026-10-18) records the fresh read-only baseline and local corrections separately. Neither establishes fit for an unimplemented split or a qualified native workload. @@ -320,7 +320,7 @@ contexts and strict mode remain unchanged. This is bounded supersession plus additive CI authority, not an ADR-0041 factual correction or record retirement. Acceptance precedes dependent implementation. The three-step -[delivery record](../roadmap/phase-02b-events-auth.md#adr-0063-acceptance-and-implementation-2026-10-18) +[delivery record](../roadmap/phase-02b-delivery-log.md#adr-0063-acceptance-and-implementation-2026-10-18) owns progress and actual final-source qualification; the ordinary membership-I/O fault remains independent corrective work under this record. This amendment rewrites none of the Accepted body, date or acceptance metadata above. @@ -328,7 +328,7 @@ rewrites none of the Accepted body, date or acceptance metadata above. ## References - [ADR-0060](0060-fatal-hangfire-startup-and-unsafe-unwind.md#diagnostics-dumps-and-durable-consequences). -- [P02b-4 CI follow-up](../roadmap/phase-02b-events-auth.md#hosted-ci-qualification-follow-up-2026-10-18). +- [P02b-4 CI follow-up](../roadmap/phase-02b-delivery-log.md#hosted-ci-qualification-follow-up-2026-10-18). - [Documentation governance](../standards/13-documentation.md#correcting-and-amending-adrs). - [Infrastructure](../standards/20-infrastructure-stack.md#background-jobs-and-hangfire), [Testing](../standards/06-testing.md), diff --git a/docs/decisions/0063-complete-bounded-ci-test-shards.md b/docs/decisions/0063-complete-bounded-ci-test-shards.md index f77524ba..b9e79973 100644 --- a/docs/decisions/0063-complete-bounded-ci-test-shards.md +++ b/docs/decisions/0063-complete-bounded-ci-test-shards.md @@ -52,7 +52,7 @@ independent review rounds before advancing. remains serial. Architecture explicitly caps parallel threads at two. More collection concurrency does not isolate process-global hooks or repair order dependence. The shared-hook/filter-restoration constraint is recorded in the [hosted - follow-up](../roadmap/phase-02b-events-auth.md#hosted-ci-qualification-follow-up-2026-10-18). + follow-up](../roadmap/phase-02b-delivery-log.md#hosted-ci-qualification-follow-up-2026-10-18). 4. **Several isolated test processes per VM** (credible alternative, not selected for this rollout). Reuse checkout/build and isolate static state in distinct testhosts. This needs one owner for all children and Docker lifecycle, private result paths, @@ -462,7 +462,7 @@ final-source meta passes with the new controls. - [Infrastructure Standards](../standards/20-infrastructure-stack.md). - [Architecture Tests Catalogue](../standards/21-architecture-tests-catalogue.md). - [Documentation Standards](../standards/13-documentation.md). -- [P02b-4 hosted follow-up](../roadmap/phase-02b-events-auth.md#hosted-ci-qualification-follow-up-2026-10-18). +- [P02b-4 hosted follow-up](../roadmap/phase-02b-delivery-log.md#hosted-ci-qualification-follow-up-2026-10-18). - [Native probe instructions](../../backend/tests/LearnStack.Tests.JobLifecycleProbe/README.md). - [VSTest 17.12 filter contract](https://github.com/microsoft/vstest/blob/v17.12.0/docs/filter.md). - [xUnit adapter identity producer](https://github.com/xunit/visualstudio.xunit/blob/2.8.2/src/xunit.runner.visualstudio/Sinks/VsDiscoverySink.cs#L71-L85). diff --git a/docs/decisions/0064-tenant-api-authentication-boundary.md b/docs/decisions/0064-tenant-api-authentication-boundary.md index c8b08045..6e7e26f8 100644 --- a/docs/decisions/0064-tenant-api-authentication-boundary.md +++ b/docs/decisions/0064-tenant-api-authentication-boundary.md @@ -447,7 +447,7 @@ boundary before its first consumer; do not infer authorization from this phase. ## Implementation Notes -The [P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19) +The [P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) owns steps, per-step reviews and current implementation status. Acceptance records dated disclosures in ADR-0036, ADR-0040 and ADR-0052, plus row-10 errata, and reconciles Standards 11's PublicSurface-only wording. It registers catalogue @@ -558,9 +558,9 @@ all exported channels; ordinary HTTP traces/logs stay observable. Phase 11 owns qualified finite dependency aliases before their first consumer and measured production audit capacity. Original Accepted body/metadata remain verbatim; this is not an ADR-0041 false-when-written correction. The prior -[Step 5 closeout](../roadmap/phase-02b-events-auth.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) +[Step 5 closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) remains historical; the -[2026-10-20 remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[2026-10-20 remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns subsequent implementation, proofs and current PR-head qualification. ### Amendment 2 — explicit subject registry bound and attribution (2026-10-20) @@ -582,7 +582,7 @@ erratum/amendment, the [decision index](README.md), Standards [33](../architecture/33-cross-cutting-concerns.md), the [glossary](../glossary.md), [CLAUDE.md](../../CLAUDE.md), the [roadmap index](../roadmap/README.md), [Phase 11](../roadmap/phase-11-production-hardening.md) -and the [acceptance/delivery record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20). +and the [acceptance/delivery record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20). Catalogue Asserts and runtime/test owners gain their new obligations together with actual implementation; acceptance alone is not proof of delivery. @@ -596,5 +596,5 @@ amendment. No new read-mode authorization follows from the summary label. This clarification preserves the original Status, Decision, date, deciders and rationale. The [decision index](README.md) links this clarification; the -[systematic correction record](../roadmap/phase-02b-events-auth.md#p02b-5-systematic-proof-and-document-corrections-2026-10-20) +[systematic correction record](../roadmap/phase-02b-delivery-log.md#p02b-5-systematic-proof-and-document-corrections-2026-10-20) owns the associated mutable-carrier reconciliation. No decision changes. diff --git a/docs/decisions/0065-bounded-tenant-assertion-diagnostics.md b/docs/decisions/0065-bounded-tenant-assertion-diagnostics.md index d8023e83..c61effb1 100644 --- a/docs/decisions/0065-bounded-tenant-assertion-diagnostics.md +++ b/docs/decisions/0065-bounded-tenant-assertion-diagnostics.md @@ -255,9 +255,9 @@ complete acceptance-carrier register is: [Phase 02b record](../roadmap/phase-02b-events-auth.md). The prior -[Step 5 closeout](../roadmap/phase-02b-events-auth.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) +[Step 5 closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) remains historical. The -[2026-10-20 remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[2026-10-20 remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns this correction's implementation, review and current PR-head CI receipts. Acceptance alone does not mark any new proof Implemented. @@ -301,7 +301,7 @@ used as evidence for the independent target-tenant audit limit. [Audit Coverage](../standards/18-audit-coverage.md), [Architecture test catalogue](../standards/21-architecture-tests-catalogue.md), [Tenancy audit matrix](../modules/tenancy/audit.md), - [P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19). + [P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19). ## Amendments @@ -324,7 +324,7 @@ unprojected positives and production negatives under both `always_on` and insufficient evidence. [Observability Standards](../standards/10-observability.md) and the [catalogue](../standards/21-architecture-tests-catalogue.md) carry the same proof boundary. Source-bound review and hosted qualification belong to the -[second remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-second-external-review-follow-up-2026-10-20). +[second remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-second-external-review-follow-up-2026-10-20). The original Accepted body, decision, date and deciders remain intact. ### Amendment 2 — subject registry source attribution (2026-10-20) @@ -346,7 +346,7 @@ erratum/amendment, the [decision index](README.md), Standards [33](../architecture/33-cross-cutting-concerns.md), the [glossary](../glossary.md), [CLAUDE.md](../../CLAUDE.md), the [roadmap index](../roadmap/README.md), [Phase 11](../roadmap/phase-11-production-hardening.md) -and the [acceptance/delivery record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20). +and the [acceptance/delivery record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20). The catalogue and actual runtime/test owners are updated with the implementation; this acceptance is not a claim that those controls already run. @@ -355,7 +355,7 @@ this acceptance is not a claim that those controls already run. The Status and acceptance-time notes describe the state before dependent implementation. The singleton allowance, scoped recorder, closed suppression signal and outbound projection are implemented; the -[remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) and subsequent correction records own executed results and source-bound CI. Acceptance is not itself a test receipt. Original Accepted text, decision, metadata and evidence-loss trade-offs remain intact. diff --git a/docs/decisions/0066-bounded-tenant-subject-admission.md b/docs/decisions/0066-bounded-tenant-subject-admission.md index 5a1494ec..5c72d842 100644 --- a/docs/decisions/0066-bounded-tenant-subject-admission.md +++ b/docs/decisions/0066-bounded-tenant-subject-admission.md @@ -335,7 +335,7 @@ owners in the same change; served/snapshot OpenAPI and the generated SDK disclos the capacity hint and sticky cleanup-fault cause. No policy in this ADR changes. Its Accepted body, date and deciders remain intact. -The [implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +The [implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns exact local results, two fresh implementation review rounds and final-source hosted qualification. Local controls do not establish production sizing, latency, mapped readiness or an exercised Phase 11 runbook. @@ -344,10 +344,10 @@ mapped readiness or an exercised Phase 11 runbook. The “pending implementation obligations” introduction in Tests and proofs is an acceptance-time snapshot. Amendment 1 and the -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) record the delivered owners and actual results; the checklist is retained as the original proof requirement, not current pending status. The -[systematic correction record](../roadmap/phase-02b-events-auth.md#p02b-5-systematic-proof-and-document-corrections-2026-10-20) +[systematic correction record](../roadmap/phase-02b-delivery-log.md#p02b-5-systematic-proof-and-document-corrections-2026-10-20) owns subsequent verification. No historical receipt qualifies later source. The 4224 ceiling is 4096 retained plus the single retirement owner, which has diff --git a/docs/decisions/0067-development-tenant-access-token-issuance.md b/docs/decisions/0067-development-tenant-access-token-issuance.md index e3439c70..2eb04d7e 100644 --- a/docs/decisions/0067-development-tenant-access-token-issuance.md +++ b/docs/decisions/0067-development-tenant-access-token-issuance.md @@ -5,7 +5,7 @@ Accepted — 2026-10-21. The maintainer explicitly approved the revised dedicated record after its review corrections and two fresh independent review rounds. The earlier P02b-6 approval of 900s development issuance remains recorded in its -[decision package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20); +[decision package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20); this separate acceptance does not backdate ADR authority. **Date:** 2026-10-21 @@ -213,7 +213,7 @@ runtime or current-head hosted test result. - [ADR-0004 — Authentication Strategy](0004-authentication-strategy.md). - [ADR-0064 — Tenant API Authentication Boundary](0064-tenant-api-authentication-boundary.md). -- [P02b-6 decision package and approval](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20). +- [P02b-6 decision package and approval](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20). - [Security 11 — Authentication](../standards/11-security.md#authentication). - [Documentation 13 — ADRs](../standards/13-documentation.md#adrs). - [Identity and authentication architecture](../architecture/13-identity-and-auth.md). diff --git a/docs/decisions/0068-development-warm-realm-qualification.md b/docs/decisions/0068-development-warm-realm-qualification.md index 13de76cb..706f0fc0 100644 --- a/docs/decisions/0068-development-warm-realm-qualification.md +++ b/docs/decisions/0068-development-warm-realm-qualification.md @@ -91,14 +91,14 @@ A subsequent explicit invocation reads the durable current state anew. ### Two bounded replacements of Accepted phase clauses The Accepted package's -[Reconciler ownership, failure and security boundaries](../roadmap/phase-02b-events-auth.md#reconciler-ownership-failure-and-security-boundaries) +[Reconciler ownership, failure and security boundaries](../roadmap/phase-02b-delivery-log.md#reconciler-ownership-failure-and-security-boundaries) requires: “Read and validate the complete bounded change plan before the first write.” Decision 1 replaces that ordering only for its single metadata write: qualify bounded preparation, write and verify it, then build the full fresh plan before all other mutations. The remaining ownership and preservation rules survive. The Accepted -[Account-console self-service capability](../roadmap/phase-02b-events-auth.md#account-console-self-service-capability--proposal-2026-10-21) +[Account-console self-service capability](../roadmap/phase-02b-delivery-log.md#account-console-self-service-capability--proposal-2026-10-21) requires: > Refuse a wider/customized role allowance or @@ -115,10 +115,10 @@ Removing compatible stock edges too would lose the reason to continue once the last incompatible edge disappeared. The three-edge decision needs no durable marker: its final deletion naturally hands later passes to compatible preservation. -The [dated acceptance record](../roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22) +The [dated acceptance record](../roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22) names both replacements beside their phase clauses and retains the original package and review chronology. The -[Step 2 review](../roadmap/phase-02b-events-auth.md#step-2-review-round-1--identity-visibility-and-plan-feasibility) +[Step 2 review](../roadmap/phase-02b-delivery-log.md#step-2-review-round-1--identity-visibility-and-plan-feasibility) demonstrated an actual hidden-actor overwrite before the visibility guard. That guard is protective, and the old warm fixture enabled unmanaged attributes. The current bootstrap-parity fixture derives from today's desired export; it @@ -394,7 +394,7 @@ prior phase receipts and invent no new canonical rule. ## References -- [Accepted P02b-6 package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20). +- [Accepted P02b-6 package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20). - [Security 11 — Authentication](../standards/11-security.md#authentication). - [Architecture 13](../architecture/13-identity-and-auth.md) and [Keycloak guide](../../infra/keycloak/README.md). - [ADR-0004](0004-authentication-strategy.md), [ADR-0064](0064-tenant-api-authentication-boundary.md) diff --git a/docs/decisions/0069-phase-documents-and-delivery-logs.md b/docs/decisions/0069-phase-documents-and-delivery-logs.md new file mode 100644 index 00000000..a987820e --- /dev/null +++ b/docs/decisions/0069-phase-documents-and-delivery-logs.md @@ -0,0 +1,294 @@ +# ADR-0069: Phase Documents and Delivery Logs + +## Status + +Accepted — 2026-10-22. + +**Date:** 2026-10-22 +**Deciders:** @cemil + +The maintainer accepted this record after one review round whose findings the +accepted text resolves. Acceptance authorizes the migration and guards in +§ Implementation Notes; it claims neither as delivered. + +## Decision Drivers + +- **A phase document stopped being a plan.** Measured at `dada277b` on 2026-10-22, + [Phase 02b](../roadmap/phase-02b-events-auth.md) is 18,884 lines (1.33 MB, about + 171,000 words). 17,420 of those lines (92%) are packet records: decision + packages, step records, review rounds, corrections, CI receipts and merge + closeouts. The plan sections, its 108-line Status block included, are about 1,460 + lines, and the real `## Scope` content starts 9,800 lines below its heading. The + document had 1,383 lines on 2026-10-11; 408 commits touched it in the eleven days + since. +- **The pattern is structural, not local.** [Phase 02d](../roadmap/phase-02d-walking-skeleton.md) + is 8,319 lines. Its records sit inside `## Scope`, dated and undated alike — + `### Delivery record: P02d-3`, `### P02d-6 Step 1: …` — and after + `## Phase Exit Decision`. [Roadmap § Phase Structure](../roadmap/README.md#phase-structure) + names six sections and says nothing about where a packet's records go, while + [Documentation Standards § Doc Types](../standards/13-documentation.md#doc-types) + makes a shipped packet's record immutable. An append-only record kept inside the + document that must also stay a readable plan grows without bound. +- **The document cannot be read whole by the agents told to read it.** `CLAUDE.md` + directs every task to the live phase. At roughly 300,000 tokens, Phase 02b fits + in no single read, so the plan is consulted in fragments or not at all. +- **Status is restated, not linked.** One packet state is narrated in the phase + Status block, the packet table, the Completion Criteria preamble, the roadmap + index and `CLAUDE.md` — in its § What state this is in, its § Where to start and + even one § Things to never do bullet. "Complete and merged" appears 19 times in + Phase 02b alone, and `CLAUDE.md`, loaded into every session, is 856 lines, 471 of + them status narrative. Every step edits all of them, which is how they keep + growing. +- **Nothing checks a fragment.** CI's Markdown link audit strips `#fragment` before + its file-existence test, skips pure in-file `#fragment` links, and reads only + changed files. 63 tracked files carry 336 links to 81 distinct anchors in Phase + 02b, and 65 carry 301 links to 72 anchors in Phase 02d — 637 fragment links in + 102 files, the two phase documents' links to each other included. Phase 02b + holds 94 in-file anchor links and Phase 02d 133. Moving a section breaks every + anchor into it silently. +- **Written conventions did not hold.** Both documents grew under the existing + rules; a rule with no failing check is the failure mode this corpus already + learned to distrust. + +## Considered Options + +1. **A plan document plus one append-only delivery log per phase, with guards** + (chosen). +2. **One record file per packet** (rejected). Related records then live in + different files: a decision package and the correction that amends it a packet + later, or a post-merge CI fix and the step it repairs, become cross-file links, + and every new file is another link prefix to keep coherent. One log per phase + keeps one file and one link prefix, and needs only three declared non-packet + sections — a phase entry, cross-packet records and the status archive — for + what no single packet owns. +3. **Keep records in the phase document, after `## Phase Exit Decision`**, as + Phase 02a does (rejected). The plan becomes readable, but the file still grows + without bound and every reader of the plan still loads every record. Phase 02a + reached 3,606 lines with this shape. +4. **Keep records only in pull requests and CI artifacts** (rejected). ADRs, + standards and catalogue entries cite dated records by anchor; pull request text + is not versioned with the repository, and Actions artifacts expire. +5. **Written convention without automated checks** (rejected, see the last driver). + +## Decision + +LearnStack keeps each phase's roadmap material in sibling documents under +`docs/roadmap/`, holds status in one place, and enforces both with CI guards. + +**File classes.** A file is classified by its name, suffix first: + +| Class | Name | Holds | +|---|---|---| +| Delivery log | `phase--delivery-log.md` | The phase's packet records | +| Exit evidence index | `phase--exit-evidence.md` | Optional, written at phase exit: each exit criterion mapped to its proof, as [Phase 02d's](../roadmap/phase-02d-exit-evidence.md) does | +| Phase document | every other `phase--.md` | The plan | + +**The phase document is the plan.** It carries the six sections +[Roadmap § Phase Structure](../roadmap/README.md#phase-structure) names, with that +section's declared exceptions; further plan sections may sit between `## Goal` and +`## Phase Exit Decision`, and nothing follows `## Phase Exit Decision`. A phase +with packets carries a Status block of at most 40 lines above `## Goal`, in +progress and after completion: the phase's state and one packet table whose rows +link each packet's records in the log. The phase document holds **no records**: no +heading carries a date, a packet identifier (`P-`), or the words +*delivery record*, *review round*, *closeout*, *decision package* or *decision +pass*. Its whole file stays within 2,000 physical lines. + +**The delivery log is the record.** Each `##` section is either a packet — +`P- — `, in packet order — or one of three non-packet sections: +`Phase entry` for records before the first decision pass, `Cross-packet records` +for what no single packet owns, and `Status archive` for retired Status prose. +Each entry is a `###` heading in its section with its date in the heading. The log +is append-only: a shipped packet's entries are not rewritten, and a false citation +gets the dated inline correction Documentation Standards already prescribes. + +**Decision packages are normative.** A decision package in the log is the vehicle +a gate marked *phase-doc* closes in. Once Accepted, its answers bind exactly as the +phase document's own text would, the decision register's status cell links the +exact answer, and implementers read it before writing the code it governs. + +**Status lives once.** Packet state lives in the phase document's Status block, +gate state in its decision register. The [roadmap index](../roadmap/README.md) +gives each phase at most six lines in § Phases and links no delivery log there. +`CLAUDE.md` gives § What state this is in and § Where to start at most 40 lines +each and links no delivery log anywhere; it points to the phase document. + +**Two guards run in CI's `meta` job and in a new `make lint-docs` target.** + +- `scripts/markdown-fragment-audit.py` resolves every relative link that carries a + `#fragment` — `[text](path#fragment)`, pure in-file `[text](#fragment)`, and + `href="path#fragment"` — in every tracked Markdown file and in the doc comments of + tracked C#, TypeScript and JavaScript sources. A path resolves against the source + file's directory, then against the repository root, as the existing link audit + does. The fragment must match a GitHub heading slug of the target, with GitHub's + `-1`, `-2` duplicate numbering, or an explicit `id` / `name` anchor. It reads the + whole tree, because a heading edited in one file breaks links in files the change + never touched. +- `scripts/roadmap-structure.py` holds the three file classes, the roadmap index + and `CLAUDE.md` to the rules above. + +Each ships with planted-violation controls that prove it can fail. + +**Legacy shapes are declared, not silently exempted.** Phase 02a, complete on +2026-09-12, is exempt from every phase-document check as one frozen file: its +`## Delivery Record` sections after its exit decision, the dated headings inside +them and its 3,606 lines stay as they are. Phase 01 keeps the status annotation +block Roadmap § Phase Structure already declares. Ten Phase 02d entries whose +headings predate the dating rule are listed by anchor in the guard; any other +undated entry fails it. + +## Context + +**What the migration moves and what it touches.** The migration this decision +authorizes moves Phase 02b's and Phase 02d's records to their logs in their +original order within each packet, under one new `##` section per packet. Record +text does not change. Two things around it do: heading levels shift where a record +moves under its packet section, and a link whose target now sits in the other file +is retargeted — 138 of the 227 in-file links cross the split. The move is +therefore *verbatim in text*, not byte-identical. + +**Anchors survive only if order does.** GitHub derives an anchor from heading text +and numbers repeated slugs by their order in the file: Phase 02b repeats 13 heading +texts, `step-1-review-round-1` four times, and `runtime-bounds-and-observation` +twice (P02b-2 and P02b-4), with +[Observability Standards](../standards/10-observability.md) linking the first. +Changing the order of two same-named headings swaps their anchors without breaking +a single link. The migration therefore keeps every packet's records in source order, +places the packets in source order, and verifies each heading individually: the +anchor it has in its new file must equal the anchor it had before. A deliberately +reordered run fails that check. + +**Retargeting is not a correction.** Links into a moved record keep their text and +change their target. That is explicitly not a correction under +[ADR-0041](0041-correcting-false-statements-in-accepted-adrs.md), so the Accepted +ADRs whose links move owe no amendment, and CI's Accepted ADR disclosure step +already ignores link-target-only diffs. Phase 04's only dated plan heading, +`Content-type quota accounting — accepted (2026-10-19)`, keeps its date in its +existing acceptance line and drops it from the heading; its six inbound links are +retargeted with the rest. + +**Why a line budget and not only a shape check.** The heading rule catches the +forms the growth took: dated and packet-named record headings inside `## Scope`, +and sections appended after `## Phase Exit Decision`. A record pasted under a plan +heading would pass it. The 2,000-line budget is the backstop: the migrated plans, +new Status blocks included, are about 1,385 lines for Phase 02b and 1,680 for +Phase 02d, and no phase document without records exceeds 820. + +**Why `CLAUDE.md` is in scope.** It is the one document every session loads, and +the same growth costs most there. Bounding its two status-bearing sections and +forbidding delivery-log links anywhere in it removes the incentive to narrate, +because the narration has nowhere to point. + +**What would change this decision.** A phase whose plan legitimately outgrows 2,000 +lines is split, as 02a/02b/02c/02d already are; the budget is not raised. If GitHub +changes its slug rules, the fragment audit's slug function follows them. + +## Consequences + +### Positive + +- The phase document is readable in one pass again. +- A packet step updates one log entry and one Status row, not five narratives. +- A broken anchor anywhere in the corpus fails CI instead of failing a reader. + +### Negative + +- Two files per phase with packets instead of one, and a reader following a record + link lands in a second file. +- The migration retargets about 600 links in about 100 files once. +- Implementers read the Accepted decision packages in the log, not only the plan; + the decision register is their index. +- Contributors writing a record must know which file it belongs in; the guard tells + them when they are wrong, not before. + +### Neutral + +- The log keeps growing, and its decision packages stay binding. A reader who needs + an answer follows one register link; only a reader who wants the delivery history + reads the rest. +- Phase 02a keeps its shape until someone has a reason to touch it. + +## Implementation Notes + +Acceptance authorizes this work, in this order: + +1. **Migration.** Split Phase 02b and Phase 02d into plan and + `phase-02b-delivery-log.md` / `phase-02d-delivery-log.md` with the per-heading + anchor verification above; move each superseded Status block verbatim into its + log's `Status archive`; write each phase document's bounded Status block; + retarget every inbound link; drop the date from Phase 04's plan heading and + retarget its six links. +2. **Status in one place.** Strip packet narrative from the phase documents' packet + tables and Completion Criteria preambles, reduce the roadmap index's § Phases + entries and `CLAUDE.md` § What state this is in and § Where to start to the + budgets above, and remove the status sentence from `CLAUDE.md` § Things to never + do. +3. **Carriers.** [Roadmap § Phase Structure](../roadmap/README.md#phase-structure) + and § Decision Timing — whose *Acceptance is explicit* bullet names where closed + parts are listed and where a *phase-doc* answer lives; + [Documentation Standards](../standards/13-documentation.md) § Layout, § Doc Types + and § When to Update Documentation; the [glossary](../glossary.md)'s *Packet* + entry and new *Delivery Log*, *Delivery Record* and *Decision Package* entries; + `CLAUDE.md` § Documentation layout and § Things to never do; the `implement-task` + and `standards-check` skills; and this record's row in the + [decisions index](README.md). +4. **Guards.** `scripts/markdown-fragment-audit.py` and + `scripts/roadmap-structure.py` with their controls + (`scripts/test-markdown-fragment-audit.py`, `scripts/test-roadmap-structure.py`), + two `meta` job steps, and the new `make lint-docs` target. They are CI guards + over the documentation corpus, like the Markdown link audit and the Accepted ADR + disclosure step, not entries in the architecture-test catalogue. + +## References + +- [ADR-0007](0007-documentation-language-and-conventions.md) — documentation + language and conventions, the authority of Documentation Standards. +- [ADR-0041](0041-correcting-false-statements-in-accepted-adrs.md) — link + retargeting is not a correction. +- [Roadmap § Phase Structure](../roadmap/README.md#phase-structure) and + [§ Decision Timing](../roadmap/README.md#decision-timing). +- [Documentation Standards](../standards/13-documentation.md). +- [Glossary § Phase, Packet](../glossary.md). + +## Amendments + +### 2026-10-22 — The README carries status, and budgets count non-blank lines + +Applying § Implementation Notes step 2 found a carrier the Decision Drivers did not +name. The repository [README](../../README.md)'s § Where it is today narrated packet +state in 105 lines with 23 delivery-log links, and its Quickstart carried two more +links and a completed packet's review-round narrative. It is held +exactly as `CLAUDE.md` is: § Where it is today within 40 lines, and no +delivery-log link anywhere in the file. The structure guard enforces both. + +The Decision states its section budgets in lines without saying how they are +counted. Every budget except the whole-file one counts **non-blank** lines: the +Status block is everything between the title and `## Goal`, a section runs from its +heading to the next heading of the same or a higher level, and a roadmap index +entry is one top-level list item with its continuation lines. The phase document's +2,000-line budget stays a count of physical lines. + +The Decision is unchanged — status lives once, and each bound applies the same +rule to one more place or states how an existing bound is measured. + +### 2026-10-23 — Each delivery log opens with a generated index + +The migrated logs are too large to read whole: Phase 02b's is 17,569 lines, about +305,000 tokens, and an agent that needs one entry has no map of the rest. Each +delivery log therefore opens with an index, between the generated-block markers, +above its first `##` section. A row is a packet section, an entry, or a dated +heading deeper than an entry — the dated depth matters because Phase 02b's +post-merge corrections sit under one 3,843-line entry — with its anchor and its +length in lines. That index is about 165 rows and 5,000 tokens for Phase 02b. + +Three properties are deliberate. Lengths, not line numbers: the index sits above +every heading, so each new row would renumber every row below it. No inferred kind: +a pattern that tags rows *decision* or *closeout* misread real headings in the +prototype, and the heading text already names the record. Generated, never hand +kept: `scripts/delivery-log-index.py` writes the block (`make docs-index`) and, in +CI's `meta` job and `make lint-docs`, refuses a stale or misplaced one; the +fragment audit checks every row's anchor. + +The index is navigation, not a record. Regenerating it rewrites no entry, so it +does not touch the log's append-only rule. The Decision is unchanged. + diff --git a/docs/decisions/README.md b/docs/decisions/README.md index c6b519a4..26c30448 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -39,7 +39,7 @@ and supersedes only two ADR-0047 same-pool progress readings during generation draining. [ADR-0047 Amendment 2](0047-transactional-background-job-runtime.md#amendment-2--owned-server-lifecycle-and-bounded-availability-supersession-2026-10-16) discloses that bounded change; [ADR-0058 Amendment 2](0058-bounded-stock-hangfire-maintenance.md#amendment-2--independent-shared-component-ownership-2026-10-16) adds shared-component ownership navigation only. Local implementation/reviews are -complete; the [P02b-4 closeout](../roadmap/phase-02b-events-auth.md#p02b-4-local-closeout-2026-10-18) +complete; the [P02b-4 closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-local-closeout-2026-10-18) owns outstanding hosted CI/PR qualification. Phase 11 owns production qualification. ## Active ADRs @@ -89,27 +89,28 @@ owns outstanding hosted CI/PR qualification. Phase 11 owns production qualificat | 0043 | [What LearnStack Does With a Tenant-Authored Payload](0043-customization-payload-validation.md) | JSON Schema draft 2020-12, evaluated by `JsonSchema.Net` **pinned at 8.0.5** (the last MIT-expression release) behind an `IJsonSchemaValidator` port. A tenant document passes **four ordered gates** — JSON, the LearnStack profile, the 2020-12 meta-schema, then the build — because the library's own defaults keep none of the rules the corpus states: its default dialect is not 2020-12, a tenant's `$schema` line overrides the pinned one, a tenant's `$id` becomes process-global state (first-writer-wins, a cross-tenant denial of service), and `true` / `false` / `{}` are all valid schemas that switch validation off. `pattern` is refused — the built `Regex` carries an infinite `MatchTimeout` and `maxLength` does not short-circuit it (measured, 30.2 s on one property). **No compiled-validator cache**: compiling is measured *cheaper* than evaluating (0.5× at the 100-property ceiling), so § 8.2's cache is deleted rather than re-keyed. Rule bodies are opaque `text` with a `dialect` discriminator naming the language of their `condition` expressions. Amendments 1–2 (2026-09-04/05) refuse **every** `$ref` cycle and bound the reference graph; Amendment 3 (2026-09-06) seals the port's exception surface and makes `ValidateInstance` enforce § 8.4's entry cap; **Amendment 4 (2026-09-07) refuses what the `jsonb` column refuses** — `U+0000`, an unpaired surrogate, a number outside `numeric`; **Amendment 5 (2026-10-02) adds ADR-0051’s optional ordered text-card profile** | | 0044 | [The Audit Write Path](0044-audit-write-path.md) | **Amendments 1–5 (2026-09-08), 6–7 (2026-09-11).** The eleven questions ADR-0033 left open, decided before the first audit file: the reserved **non-nil** platform sentinel tenant id (the nil uuid is refused by three shipped guards that read all-zero as *no tenant*), and a `tenants` CHECK that keeps it unprovisionable; the row's `tenant_id` is the tenant the **transaction announced**, so a provisioning command audits under the tenant it creates and `make seed` still commits; **N intents per request**, one per audited resource, because two shipped commands already write two — and only the **owning** unit-of-work frame writes them or reports the commit boundary, which is what stops a nested `Send` from claiming durability nothing committed; `outcome` closes at four values (`indeterminate` included) and the writer always supplies `timestamp`, so ADR-0033's deliberate duplicate-id pair is legal under `(id, timestamp)` rather than a `23505`; the catalogue is **code** keyed by request type and the matrix is prose, with a test asserting they agree, and every request must be classified — there is no `RequestKind.Other`; the interceptor captures **every** tracked entity minus a named exclusion list, because the `AuditableEntity<>` predicate was blind to `platform_host_to_tenant`; `[PiiSensitive]` and an elision record that preserves the column's JSON type; `audit_log` is org-scoped, carries **no** FK to `tenants`, and both standalone writers announce **two** GUCs — measured: an org-scoped `denied` row is refused without the second. Amendment 1 makes `audit_config` tenant-**wide**; Amendment 2 corrects the redaction sentinel to the shipped constant and the reason `FORCE` needs a trigger (the policy binds the owner by tenant, not by immutability — measured); Amendment 3 gives the matrix↔catalogue join two directions with two domains, because 23 of 30 shipped matrix slugs have no request type and the rule as written was red on arrival, and moves the audit value types into `SharedKernel.Audit` to break the same project cycle `AuditEntryId` had; Amendment 4 makes `[PiiSensitive]` property-granular, `jsonb` included, ships `audit_config` unwritten and binds the matrix rule to modules with code; Amendment 5 guards the sentinel where it is announced and fills `entity_type` / `entity_id` from the declared aggregate; Amendment 6 — from an external review that reproduced four defects against real PostgreSQL — has a handler designate the subject when it writes two instances of its aggregate, carries the actor and correlation id on the intent, keeps each intent's own request's result, captures a contained entity with its aggregate, and instance-qualifies `changes` pointers; Amendment 7 corrects § 7's count of plain entities — seven today, five of them MUST — and names the Tenancy matrix alone as the one that singles out the host mapping. [Amendment 8 (2026-10-12)](0044-audit-write-path.md#amendment-8--common-audit-ownership-outside-mediatr-2026-10-12) clarifies common audit ownership outside MediatR under ADR-0057 without adding an audit writer. [Amendment 11 (2026-10-13)](0044-audit-write-path.md#amendment-11--shared-delivery-capture-exclusions-2026-10-13) accepts the inbox/delivery machinery capture exclusions under ADR-0046; P02b-3 implements them through the shared business owner. [Amendment 13 (2026-10-15)](0044-audit-write-path.md#amendment-13--job-terminal-sixth-write-and-capture-exclusions-2026-10-15) adds the job-terminal sixth write and exact job/control capture exclusions. | | 0045 | [The Entitlement and Feature-Flag Socket](0045-entitlement-and-feature-flag-socket.md) | **Amendment 1 (2026-09-08)** reads it against the Hub's merged code: the limit vocabulary is the Hub's, `expires_at`/`valid_until` are nullable, the generation guard admits the equal case, and `platform_killswitches` ships **unwritten** because `DenyAllPlatformAdminGate` makes a writer unreachable until Phase 03. **Amendment 2 (2026-09-11):** a registry's membership is the vocabulary the contract names — fourteen Hub features, nine `limits.*`, two tenant flags, three killswitches — and enforcement, not membership, waits for a consumer. **Amendment 3 (2026-09-11):** a key's fail-open/fail-closed class decides only when no projection exists; one past its grace window is read-only, as ADR-0021 decides. **Amendment 4 (2026-09-11):** of the projection's names, `PlanCode` differs from the wire (`tier`) and `ExpiresAt` from the column (`valid_until`) — § 1 had called both wire differences. Declares the port twenty documents name and none define. `IEntitlementProvider.GetAsync(TenantId)` + `RefreshAsync(projection)`, the projection carrying every field `entitlement-v1.schema.json` requires — **`compliance` and `generation` included**, both already `NOT NULL` columns — and the refresh **generation-guarded inside the write statement**, so a stale push cannot resurrect a revoked plan. `IFeatureFlags` is the only module-facing read and **composes over the provider** rather than querying `platform_entitlement_cache`, which is the only reading under which the Phase 02a criterion — swapping the provider changes the answer — can be true. Limits: **`-1` unlimited, `0` denied**, `long` not `long?`; the inverse reading would have made the degraded read-only mode grant unlimited. `NullEntitlementProvider` is registered in **every** deployment mode, per ADR-0035's default-implementation gate rather than ADR-0020's Development-only switch. Killswitches leave `tenant_feature_flags` for a platform-scoped `platform_killswitches`: a foreign key to `tenants` is a constraint no role or `BYPASSRLS` moves, so the sentinel could never have satisfied it. Push-primary, **not** push-only — ADR-0034's `license/verify` fallback stands; the no-Hub absolute belongs to host resolution | -| 0046 | [Durable Event Delivery and Recovery](0046-durable-event-delivery-and-recovery.md) | Accepted 2026-10-12: fenced producer leases/retries, Pending readiness holds and atomic row-bound terminal audit; P02b-2 is complete and merged through PR #30; its [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) owns final verification. [Amendment 2](0046-durable-event-delivery-and-recovery.md#amendment-2--producer-enforcement-and-local-closeout-2026-10-12) records verified local closeout. [Amendment 1](0046-durable-event-delivery-and-recovery.md#amendment-1--producer-runtime-delivery-2026-10-12) records producer runtime delivery and its review evidence. [Amendment 3](0046-durable-event-delivery-and-recovery.md#amendment-3--consumer-runtime-and-enforcement-delivery-2026-10-13) records P02b-3 consumer runtime, both Active defaults and production enforcement; P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. Named bounded supersessions preserve earlier Accepted records. | -| 0047 | [Transactional Background Job Runtime](0047-transactional-background-job-runtime.md) | Accepted 2026-10-15: H1 stock Hangfire opaque wakeups plus authoritative transactional job/attempt records, external stages, tenant capacity and trusted recurrence/fan-out; bounded supersessions and additive seams disclosed in prior records. [Amendment 1](0047-transactional-background-job-runtime.md#amendment-1--maintenance-replacement-and-additive-ownership-seams-2026-10-16) records ADR-0058's accepted maintenance configuration replacement and additive ownership seams. The [P02b-4 package](../roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15) authorizes nine implementation steps on development; all nine steps and both reviews per step are complete and merged through PR #32 on 2026-10-19; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records final-source qualification | +| 0046 | [Durable Event Delivery and Recovery](0046-durable-event-delivery-and-recovery.md) | Accepted 2026-10-12: fenced producer leases/retries, Pending readiness holds and atomic row-bound terminal audit; P02b-2 is complete and merged through PR #30; its [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns final verification. [Amendment 2](0046-durable-event-delivery-and-recovery.md#amendment-2--producer-enforcement-and-local-closeout-2026-10-12) records verified local closeout. [Amendment 1](0046-durable-event-delivery-and-recovery.md#amendment-1--producer-runtime-delivery-2026-10-12) records producer runtime delivery and its review evidence. [Amendment 3](0046-durable-event-delivery-and-recovery.md#amendment-3--consumer-runtime-and-enforcement-delivery-2026-10-13) records P02b-3 consumer runtime, both Active defaults and production enforcement; P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. Named bounded supersessions preserve earlier Accepted records. | +| 0047 | [Transactional Background Job Runtime](0047-transactional-background-job-runtime.md) | Accepted 2026-10-15: H1 stock Hangfire opaque wakeups plus authoritative transactional job/attempt records, external stages, tenant capacity and trusted recurrence/fan-out; bounded supersessions and additive seams disclosed in prior records. [Amendment 1](0047-transactional-background-job-runtime.md#amendment-1--maintenance-replacement-and-additive-ownership-seams-2026-10-16) records ADR-0058's accepted maintenance configuration replacement and additive ownership seams. The [P02b-4 package](../roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15) authorizes nine implementation steps on development; all nine steps and both reviews per step are complete and merged through PR #32 on 2026-10-19; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final-source qualification | | 0050 | [Publication and Course Content Access](0050-publication-and-course-content-access.md) | Accepted 2026-10-02: publication/access separation, restricted backfill and anonymous denial; supersedes ADR-0048; P02d-2 policy, migration, writers and seed delivered ([Amendment 1](0050-publication-and-course-content-access.md#amendment-1--p02d-2-implementation-delivery-2026-10-02)); P02d-4 public-read enforcement delivered, grants Phase 07 | | 0051 | [Ordered Text Card Presentation](0051-ordered-text-card-presentation.md) | Accepted 2026-10-02: optional root `x-fields`, localized ordered text cards; compatible extension linked by ADR-0043 Amendment 5; P02d-2 profile parsing, resolution and seed verification delivered ([Amendment 1](0051-ordered-text-card-presentation.md#amendment-1--p02d-2-implementation-delivery-2026-10-02)); P02d-4 public projection delivered; P02d-6 completes ordered plain-text rendering, automated product proofs and manual accessibility smoke | | 0052 | [Anonymous Public Read Boundary](0052-anonymous-public-read-boundary.md) | Accepted 2026-10-03: host-resolved bootstrap, immutable host ceiling, mandatory marked dispatch and read-only ambient frames; ADR-0036/0040 Amendment 8; P02d-4 Steps 1–3 deliver host provenance, physical read-only frames and all institution GET/HEAD reads; both Step 3 review rounds pass; Step 4 delivers OpenAPI/SDK/CI controls; both review rounds and focused fix verification pass; six real required CI jobs and live sixth-check activation verified; P02d-4 complete and merged through PR #25 on 2026-10-08 ([Amendment 13](0052-anonymous-public-read-boundary.md#amendment-13--merge-closeout-2026-10-08)). [Amendment 15](0052-anonymous-public-read-boundary.md#amendment-15--exact-authenticated-read-mode-scope-2026-10-19) discloses ADR-0064's exact authenticated read-mode extension without weakening the public-read contract. | -| 0053 | [Trusted Public Server Rendering](0053-trusted-public-server-rendering.md) | Accepted 2026-10-08: P02d-5 delivers native ingress, configured transport, dynamic entry and source/runtime proofs. [ADR-0054](0054-bounded-public-renderer-admission.md) replaces bounded accounting/native/query contracts. P02d-5 is complete and merged through PR #26 on 2026-10-09; the [merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) owns final verification ([Amendment 8](0053-trusted-public-server-rendering.md#amendment-8--merge-closeout-2026-10-09)); P6/P7 remain separate | -| 0054 | [Bounded Public Renderer Admission](0054-bounded-public-renderer-admission.md) | Accepted 2026-10-09: coordinated anonymous accounting, native GET/HEAD/production-upgrade admission and equivalent redirect-query encoding are delivered. All five remediation steps are complete and merged through PR #26; the [merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) owns final verification ([Amendment 6](0054-bounded-public-renderer-admission.md#amendment-6--merge-closeout-2026-10-09)) | -| 0055 | [Handle Public Renderer Bootstrap Failures in Middleware](0055-public-renderer-bootstrap-failures.md) | Accepted 2026-10-10: one live middleware bootstrap and an immutable native same-request snapshot; exact bootstrap 404/429/503, bounded renderer Retry-After and two/one/three-call accounting implemented. Production replacement proofs pass; all three steps completed both review rounds and focused fix verification. [Step 3](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) owns delivery evidence, completed reviews and verified fixes; five new catalogue rules are Implemented | -| 0056 | [Public Demo Browser and Lighthouse Enforcement](0056-public-demo-browser-and-lighthouse-enforcement.md) | Accepted 2026-10-11: pinned Lighthouse/Playwright Chromium, seed-derived nine-page browser proof, 27 serial audits, actual-page admission, normalized gzip/CLS/accessibility hard checks and advisory timings delivered; four proof rules Implemented, real PR CI/artifacts pass and seventh required context activated ([Amendment 1](0056-public-demo-browser-and-lighthouse-enforcement.md#amendment-1--p02d-7-enforcement-delivery-2026-10-11)); complete and merged through PR #28 on 2026-10-11 ([merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11)) | -| 0057 | [Transactional Event Production and Completion](0057-transactional-event-production-and-completion.md) | Accepted 2026-10-12: immediate ambient enqueue, owner-only domain completion, sticky produced-work refusal protection, identifier-only bounded payloads and completed-provisioning publisher; eight producer rules Implemented; Steps 1–3 implement shared execution, immediate enqueue, successful-save collection and the publisher; Step 4 adds production censuses and catalogue enforcement. P02b-1 is complete and merged through PR #29 on 2026-10-12; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-1-merge-and-closeout-2026-10-12) owns final verification. Amendment 1 links delivery verification and review status. [Amendment 2 (2026-10-12)](0057-transactional-event-production-and-completion.md#amendment-2--correct-adr-0032-clause-locators-2026-10-12) corrects the ADR-0032 clause locators through inline errata; the Decision and bounded supersession are unchanged. [Amendment 3](0057-transactional-event-production-and-completion.md#amendment-3--useful-default-consumers-and-semantic-seed-handoff-2026-10-13) records the two Active default subscriptions and semantic Seeder handoff delivered in P02b-3. | -| 0058 | [Bounded Stock Hangfire Maintenance](0058-bounded-stock-hangfire-maintenance.md) | Accepted 2026-10-16: selective stock aggregation/history suppression, shared owned expiration, finite enabled I/O and reset-safe idle-session cleanup; [ADR-0047 Amendment 1](0047-transactional-background-job-runtime.md#amendment-1--maintenance-replacement-and-additive-ownership-seams-2026-10-16) records the configuration replacement and additive seams. [Amendment 1](0058-bounded-stock-hangfire-maintenance.md#amendment-1--sourcereset-qualification-delivered-2026-10-16) records completed Step 2 source/reset qualification and both reviews; Step 4 ownership and Step 9 enforcement are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records hosted qualification | -| 0059 | [Owned Hangfire Server Generations](0059-owned-hangfire-server-generations.md) | Accepted 2026-10-16: additive public stock lifecycle composition, one actual generation per pool and replacement after actual cleanup; bounded supersession of exactly two ADR-0047 same-pool progress clauses during generation draining, with additive ADR-0058 component ownership. The [Step 4 adaptation](../roadmap/phase-02b-events-auth.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) is authorized; implementation/reviews are complete and merged through PR #32; [P02b-4 merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records CI/merge verification, while Phase 11 owns production qualification | -| 0060 | [Fatal Hangfire Startup and Unsafe Unwind](0060-fatal-hangfire-startup-and-unsafe-unwind.md) | Accepted 2026-10-16: conservative process-wide fatal boundary for opaque construction and before/after-capture unqualified Core unwind; viable quarantine alternative and whole-API availability cost disclosed through ADR-0047 Amendment 3 / ADR-0059 Amendment 1. Dependent Step 4 implementation/reviews are complete and merged through PR #32; [P02b-4 merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records final-source CI/merge verification; [Amendment 1](0060-fatal-hangfire-startup-and-unsafe-unwind.md#amendment-1--native-ci-provisioning-boundary-2026-10-18) discloses ADR-0062's bounded native CI authority | -| 0061 | [Known External Job Failure Policy](0061-known-external-job-failure-policy.md) | Accepted 2026-10-17: one immutable three-state policy, Permanent only for Failed, deterministic retry/finalization/reason guards and actual-row-bound audit; [ADR-0047 Amendment 4](0047-transactional-background-job-runtime.md#amendment-4--known-completed-external-failure-policy-2026-10-17) discloses the bounded input replacement and additive contract. Step 7 implementation/reviews and Step 9 enforcement are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records final-source hosted qualification | -| 0062 | [Native Crash Proof CI Provisioning](0062-native-crash-proof-ci-provisioning.md) | Accepted 2026-10-18: dedicated disposable native VM, verified fixed collector setup without restoration, complete complementary Docker execution and fail-closed existing required result; [ADR-0060 Amendment 1](0060-fatal-hangfire-startup-and-unsafe-unwind.md#amendment-1--native-ci-provisioning-boundary-2026-10-18) preserves earlier authority. Implementation/reviews and final-source hosted qualification are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records verified evidence and its availability limits | -| 0063 | [Complete Bounded CI Test Shards](0063-complete-bounded-ci-test-shards.md) | Accepted 2026-10-18: bounded manual Architecture/ordinary counts, initial base + 6 + 12 + native, complete selector/case-ID aggregates, two-assignment qualification and confined non-Docker ownership; [ADR-0062 Amendment 1](0062-native-crash-proof-ci-provisioning.md#amendment-1--bounded-ci-shards-and-additive-non-docker-owner-2026-10-18) records replacement/additive seams. All three dependent steps/reviews and both full hosted assignments are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) records exact source and actual bounded fit | -| 0064 | [Tenant API Authentication Boundary](0064-tenant-api-authentication-boundary.md) | Accepted 2026-10-19: strict tenant bearer profile, stable actor/subject quota, closed authenticated read and bounded membership-denial audit replacement; [five-step P02b-5 package](../roadmap/phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19) approved before implementation. Own dated disclosures in ADR-0036/0040/0052 preserve their Accepted bodies. All five implementation steps and both independent review rounds per step are locally complete; the [Step 5 closeout](../roadmap/phase-02b-events-auth.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) owns historical local/source evidence; the [2026-10-20 remediation](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) owns subsequent corrections and PR #33 owns current-head CI. [Amendment 1](0064-tenant-api-authentication-boundary.md#amendment-1--bounded-assertion-diagnostics-2026-10-20) discloses ADR-0065's audit-admission replacement. [Amendment 2](0064-tenant-api-authentication-boundary.md#amendment-2--explicit-subject-registry-bound-and-attribution-2026-10-20) records ADR-0066 acceptance and corrects the old cap attribution. [Amendment 3](0064-tenant-api-authentication-boundary.md#amendment-3--read-mode-instrument-classification-2026-10-20) clarifies read-mode instrument classification. | -| 0065 | [Bounded Tenant Assertion Diagnostics](0065-bounded-tenant-assertion-diagnostics.md) | Accepted 2026-10-20: singleton host-tenant admission of 600 authenticated audit attempts per instance/minute, closed counters and one attributed warning per occurrence; explicitly accepts lost durable actor evidence and unbounded log volume. Ratifies process-wide native outbound metric projection and dependency-attribution cost. Implementation and local proofs are delivered; the [remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) owns implementation and proof status. [Amendment 1](0065-bounded-tenant-assertion-diagnostics.md#amendment-1--exemplar-export-enforcement-2026-10-20) clarifies exemplar privacy enforcement and its actual export controls. [Amendment 2](0065-bounded-tenant-assertion-diagnostics.md#amendment-2--subject-registry-source-attribution-2026-10-20) corrects subject-registry attribution without changing audit allowance. [Amendment 3](0065-bounded-tenant-assertion-diagnostics.md#amendment-3--delivered-implementation-and-receipt-chronology-2026-10-20) clarifies delivered implementation chronology. | -| 0066 | [Bounded Tenant Subject Admission](0066-bounded-tenant-subject-admission.md) | Accepted 2026-10-20: explicit 4096 retained-subject process bound, one-disposal acquisition reclamation, sole joined cleanup owner and distinct quota/capacity/fault results and metrics. Sticky cleanup fault refuses new keys with 503; quota/capacity stay 429. ADR-0064/0065 each carry inline attribution errata and their own Amendment 2. [Amendment 1](0066-bounded-tenant-subject-admission.md#amendment-1--implementation-and-local-proof-ownership-2026-10-20) records implementation and actual proof owners; the [delivery record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) owns status. [Amendment 2](0066-bounded-tenant-subject-admission.md#amendment-2--acceptance-time-proof-list-and-cleanup-evidence-2026-10-20) clarifies acceptance-time proof list and cleanup evidence. | -| 0067 | [Development Tenant Access-Token Issuance](0067-development-tenant-access-token-issuance.md) | Accepted 2026-10-21 after separate maintainer approval: dedicated authority for the already approved 900s development issuance choice, inherited ID-token expiration and bounded provider timestamp/session semantics. Security 11 owns the ongoing rule; API acceptance and BFF session policy remain separate. The [acceptance record](../roadmap/phase-02b-events-auth.md#adr-0067-acceptance-and-carrier-reconciliation-2026-10-21) preserves original phase approval and source-bound proof/review status. | -| 0068 | [Development Warm-Realm Qualification](0068-development-warm-realm-qualification.md) | Accepted 2026-10-22 under conditional maintainer authority after verified review corrections: identity-independent prechecks, one bounded profile preparation and three qualified stock-console assignment detachments. Implementation and automatic-path qualification remain pending; the [acceptance record](../roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22) owns the three-step plan and proof status. | +| 0053 | [Trusted Public Server Rendering](0053-trusted-public-server-rendering.md) | Accepted 2026-10-08: P02d-5 delivers native ingress, configured transport, dynamic entry and source/runtime proofs. [ADR-0054](0054-bounded-public-renderer-admission.md) replaces bounded accounting/native/query contracts. P02d-5 is complete and merged through PR #26 on 2026-10-09; the [merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) owns final verification ([Amendment 8](0053-trusted-public-server-rendering.md#amendment-8--merge-closeout-2026-10-09)); P6/P7 remain separate | +| 0054 | [Bounded Public Renderer Admission](0054-bounded-public-renderer-admission.md) | Accepted 2026-10-09: coordinated anonymous accounting, native GET/HEAD/production-upgrade admission and equivalent redirect-query encoding are delivered. All five remediation steps are complete and merged through PR #26; the [merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) owns final verification ([Amendment 6](0054-bounded-public-renderer-admission.md#amendment-6--merge-closeout-2026-10-09)) | +| 0055 | [Handle Public Renderer Bootstrap Failures in Middleware](0055-public-renderer-bootstrap-failures.md) | Accepted 2026-10-10: one live middleware bootstrap and an immutable native same-request snapshot; exact bootstrap 404/429/503, bounded renderer Retry-After and two/one/three-call accounting implemented. Production replacement proofs pass; all three steps completed both review rounds and focused fix verification. [Step 3](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns delivery evidence, completed reviews and verified fixes; five new catalogue rules are Implemented | +| 0056 | [Public Demo Browser and Lighthouse Enforcement](0056-public-demo-browser-and-lighthouse-enforcement.md) | Accepted 2026-10-11: pinned Lighthouse/Playwright Chromium, seed-derived nine-page browser proof, 27 serial audits, actual-page admission, normalized gzip/CLS/accessibility hard checks and advisory timings delivered; four proof rules Implemented, real PR CI/artifacts pass and seventh required context activated ([Amendment 1](0056-public-demo-browser-and-lighthouse-enforcement.md#amendment-1--p02d-7-enforcement-delivery-2026-10-11)); complete and merged through PR #28 on 2026-10-11 ([merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11)) | +| 0057 | [Transactional Event Production and Completion](0057-transactional-event-production-and-completion.md) | Accepted 2026-10-12: immediate ambient enqueue, owner-only domain completion, sticky produced-work refusal protection, identifier-only bounded payloads and completed-provisioning publisher; eight producer rules Implemented; Steps 1–3 implement shared execution, immediate enqueue, successful-save collection and the publisher; Step 4 adds production censuses and catalogue enforcement. P02b-1 is complete and merged through PR #29 on 2026-10-12; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-1-merge-and-closeout-2026-10-12) owns final verification. Amendment 1 links delivery verification and review status. [Amendment 2 (2026-10-12)](0057-transactional-event-production-and-completion.md#amendment-2--correct-adr-0032-clause-locators-2026-10-12) corrects the ADR-0032 clause locators through inline errata; the Decision and bounded supersession are unchanged. [Amendment 3](0057-transactional-event-production-and-completion.md#amendment-3--useful-default-consumers-and-semantic-seed-handoff-2026-10-13) records the two Active default subscriptions and semantic Seeder handoff delivered in P02b-3. | +| 0058 | [Bounded Stock Hangfire Maintenance](0058-bounded-stock-hangfire-maintenance.md) | Accepted 2026-10-16: selective stock aggregation/history suppression, shared owned expiration, finite enabled I/O and reset-safe idle-session cleanup; [ADR-0047 Amendment 1](0047-transactional-background-job-runtime.md#amendment-1--maintenance-replacement-and-additive-ownership-seams-2026-10-16) records the configuration replacement and additive seams. [Amendment 1](0058-bounded-stock-hangfire-maintenance.md#amendment-1--sourcereset-qualification-delivered-2026-10-16) records completed Step 2 source/reset qualification and both reviews; Step 4 ownership and Step 9 enforcement are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records hosted qualification | +| 0059 | [Owned Hangfire Server Generations](0059-owned-hangfire-server-generations.md) | Accepted 2026-10-16: additive public stock lifecycle composition, one actual generation per pool and replacement after actual cleanup; bounded supersession of exactly two ADR-0047 same-pool progress clauses during generation draining, with additive ADR-0058 component ownership. The [Step 4 adaptation](../roadmap/phase-02b-delivery-log.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) is authorized; implementation/reviews are complete and merged through PR #32; [P02b-4 merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records CI/merge verification, while Phase 11 owns production qualification | +| 0060 | [Fatal Hangfire Startup and Unsafe Unwind](0060-fatal-hangfire-startup-and-unsafe-unwind.md) | Accepted 2026-10-16: conservative process-wide fatal boundary for opaque construction and before/after-capture unqualified Core unwind; viable quarantine alternative and whole-API availability cost disclosed through ADR-0047 Amendment 3 / ADR-0059 Amendment 1. Dependent Step 4 implementation/reviews are complete and merged through PR #32; [P02b-4 merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final-source CI/merge verification; [Amendment 1](0060-fatal-hangfire-startup-and-unsafe-unwind.md#amendment-1--native-ci-provisioning-boundary-2026-10-18) discloses ADR-0062's bounded native CI authority | +| 0061 | [Known External Job Failure Policy](0061-known-external-job-failure-policy.md) | Accepted 2026-10-17: one immutable three-state policy, Permanent only for Failed, deterministic retry/finalization/reason guards and actual-row-bound audit; [ADR-0047 Amendment 4](0047-transactional-background-job-runtime.md#amendment-4--known-completed-external-failure-policy-2026-10-17) discloses the bounded input replacement and additive contract. Step 7 implementation/reviews and Step 9 enforcement are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final-source hosted qualification | +| 0062 | [Native Crash Proof CI Provisioning](0062-native-crash-proof-ci-provisioning.md) | Accepted 2026-10-18: dedicated disposable native VM, verified fixed collector setup without restoration, complete complementary Docker execution and fail-closed existing required result; [ADR-0060 Amendment 1](0060-fatal-hangfire-startup-and-unsafe-unwind.md#amendment-1--native-ci-provisioning-boundary-2026-10-18) preserves earlier authority. Implementation/reviews and final-source hosted qualification are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records verified evidence and its availability limits | +| 0063 | [Complete Bounded CI Test Shards](0063-complete-bounded-ci-test-shards.md) | Accepted 2026-10-18: bounded manual Architecture/ordinary counts, initial base + 6 + 12 + native, complete selector/case-ID aggregates, two-assignment qualification and confined non-Docker ownership; [ADR-0062 Amendment 1](0062-native-crash-proof-ci-provisioning.md#amendment-1--bounded-ci-shards-and-additive-non-docker-owner-2026-10-18) records replacement/additive seams. All three dependent steps/reviews and both full hosted assignments are complete and merged through PR #32; the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records exact source and actual bounded fit | +| 0064 | [Tenant API Authentication Boundary](0064-tenant-api-authentication-boundary.md) | Accepted 2026-10-19: strict tenant bearer profile, stable actor/subject quota, closed authenticated read and bounded membership-denial audit replacement; [five-step P02b-5 package](../roadmap/phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) approved before implementation. Own dated disclosures in ADR-0036/0040/0052 preserve their Accepted bodies. All five implementation steps and both independent review rounds per step are locally complete; the [Step 5 closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) owns historical local/source evidence; the [2026-10-20 remediation](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns subsequent corrections and PR #33 owns current-head CI. [Amendment 1](0064-tenant-api-authentication-boundary.md#amendment-1--bounded-assertion-diagnostics-2026-10-20) discloses ADR-0065's audit-admission replacement. [Amendment 2](0064-tenant-api-authentication-boundary.md#amendment-2--explicit-subject-registry-bound-and-attribution-2026-10-20) records ADR-0066 acceptance and corrects the old cap attribution. [Amendment 3](0064-tenant-api-authentication-boundary.md#amendment-3--read-mode-instrument-classification-2026-10-20) clarifies read-mode instrument classification. | +| 0065 | [Bounded Tenant Assertion Diagnostics](0065-bounded-tenant-assertion-diagnostics.md) | Accepted 2026-10-20: singleton host-tenant admission of 600 authenticated audit attempts per instance/minute, closed counters and one attributed warning per occurrence; explicitly accepts lost durable actor evidence and unbounded log volume. Ratifies process-wide native outbound metric projection and dependency-attribution cost. Implementation and local proofs are delivered; the [remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) owns implementation and proof status. [Amendment 1](0065-bounded-tenant-assertion-diagnostics.md#amendment-1--exemplar-export-enforcement-2026-10-20) clarifies exemplar privacy enforcement and its actual export controls. [Amendment 2](0065-bounded-tenant-assertion-diagnostics.md#amendment-2--subject-registry-source-attribution-2026-10-20) corrects subject-registry attribution without changing audit allowance. [Amendment 3](0065-bounded-tenant-assertion-diagnostics.md#amendment-3--delivered-implementation-and-receipt-chronology-2026-10-20) clarifies delivered implementation chronology. | +| 0066 | [Bounded Tenant Subject Admission](0066-bounded-tenant-subject-admission.md) | Accepted 2026-10-20: explicit 4096 retained-subject process bound, one-disposal acquisition reclamation, sole joined cleanup owner and distinct quota/capacity/fault results and metrics. Sticky cleanup fault refuses new keys with 503; quota/capacity stay 429. ADR-0064/0065 each carry inline attribution errata and their own Amendment 2. [Amendment 1](0066-bounded-tenant-subject-admission.md#amendment-1--implementation-and-local-proof-ownership-2026-10-20) records implementation and actual proof owners; the [delivery record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns status. [Amendment 2](0066-bounded-tenant-subject-admission.md#amendment-2--acceptance-time-proof-list-and-cleanup-evidence-2026-10-20) clarifies acceptance-time proof list and cleanup evidence. | +| 0067 | [Development Tenant Access-Token Issuance](0067-development-tenant-access-token-issuance.md) | Accepted 2026-10-21 after separate maintainer approval: dedicated authority for the already approved 900s development issuance choice, inherited ID-token expiration and bounded provider timestamp/session semantics. Security 11 owns the ongoing rule; API acceptance and BFF session policy remain separate. The [acceptance record](../roadmap/phase-02b-delivery-log.md#adr-0067-acceptance-and-carrier-reconciliation-2026-10-21) preserves original phase approval and source-bound proof/review status. | +| 0068 | [Development Warm-Realm Qualification](0068-development-warm-realm-qualification.md) | Accepted 2026-10-22 under conditional maintainer authority after verified review corrections: identity-independent prechecks, one bounded profile preparation and three qualified stock-console assignment detachments. Implementation and automatic-path qualification remain pending; the [acceptance record](../roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22) owns the three-step plan and proof status. | +| 0069 | [Phase Documents and Delivery Logs](0069-phase-documents-and-delivery-logs.md) | Accepted 2026-10-22 after one review round: each phase keeps its plan in the phase document and its dated packet records in a sibling append-only delivery log whose Accepted decision packages stay normative; packet status lives once, in the phase document's bounded Status block; a whole-tree Markdown fragment audit and a roadmap structure guard enforce both, with Phase 02a, Phase 01 and ten Phase 02d entries declared as legacy shapes. | ## Proposed ADRs @@ -120,7 +121,7 @@ owns outstanding hosted CI/PR qualification. Phase 11 owns production qualificat The maintainer endorsed the marketplace direction and accepted ADR-0050/0051 and the P02d-2 package on 2026-10-02. Their rows are now in Active ADRs; ADR-0049 remains Proposed and its commerce contracts are not hidden P02d-2 dependencies. The -[phase record](../roadmap/phase-02d-walking-skeleton.md#approval-boundary-and-readiness) +[phase record](../roadmap/phase-02d-delivery-log.md#approval-boundary-and-readiness) records acceptance and the request to wait before implementation. On future acceptance, move a Proposed row to Active ADRs instead of duplicating it. Draft SLAs are unchanged. @@ -191,7 +192,7 @@ ADR-0047 is Accepted on 2026-10-15 and appears in Active ADRs. Its reserved number is consumed; G9 and the package's new job parts are Accepted. P02b-4 implementation and enforcement are complete and merged through PR #32 on 2026-10-19; its -[merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) +[merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) owns final qualification and merge verification. **SLA:** any draft whose target phase is currently in progress without an Accepted ADR diff --git a/docs/glossary.md b/docs/glossary.md index 728e42af..7eccdf7e 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -28,14 +28,14 @@ This glossary defines LearnStack-specific terms. When a term is ambiguous across | **Role** | A named bundle of permissions. Scope: `Platform` / `Tenant` / `Organization`. Examples: `tenant-admin`, `editor`, `instructor`, `learner`, `org-admin`. | | **Permission** | A fine-grained capability `{module}.{resource}.{action}` with a scope (Platform / Tenant / Organization). Action set is closed: `read \| write \| delete \| admin`. | | **Invitation** | A pending offer for a user to accept a membership in a tenant + organization. | -| **Development realm reconciliation** | P02b-6 tooling operation that converges the named tenant-realm configuration and demo identity attributes on a fresh or existing local Keycloak database. It preserves account identity and credentials, does not provision application memberships and is not the runtime `IIdentityProvider`. The [P02b-6 decision package](roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) owns its approved field/capability boundaries; the [Step 3 record](roadmap/phase-02b-events-auth.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21) records delivered entry-point convergence and the Step 4 record owns remaining qualification. | +| **Development realm reconciliation** | P02b-6 tooling operation that converges the named tenant-realm configuration and demo identity attributes on a fresh or existing local Keycloak database. It preserves account identity and credentials, does not provision application memberships and is not the runtime `IIdentityProvider`. The [P02b-6 decision package](roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) owns its approved field/capability boundaries; the [Step 3 record](roadmap/phase-02b-delivery-log.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21) records delivered entry-point convergence and the Step 4 record owns remaining qualification. | | **Validated tenant identity** | P02b-5 request-local immutable projection of a successfully validated tenant access token: its issuer/subject, stable actor and optional scalar tenant/organization. Actor attribution is independent of tenant authority: a claimless actor can remain HostOnly and cannot enter protected reads. It proves neither live membership nor permission. Accepted [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md) owns the contract; the P02b-5 delivery record owns implementation status. | | **Claimless principal** | A validated tenant API identity without a tenant claim. It keeps the HostOnly public ceiling; it cannot acquire tenant authority merely through its actor UUID. See [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md#access-token-profile). | | **AccountSite** | The one authenticated host-backed API read: validated actor UUID, resolved tenant/organization and the existing public site projection. It grants no membership or application permission. See [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md#closed-authenticated-read). | | **TenantAssertionSource** | The closed diagnostic origin of an assertion: `header` or validated `jwt-claim`. It selects neither tenant nor organization. See [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md#rejection-recorder-and-diagnostic-contracts). | -| **TenantAssertionAuditBudget** | Singleton API-instance allowance shared by scoped recorders: 600 authenticated audit write attempts per independently defended host tenant per first-request-anchored monotonic minute. Failed writes consume allowance; suppressed occurrences retain refusal, counter and one attributed Warning without a durable row or database I/O. It grants no actor-coverage guarantee, adds no tenant-registry cap and cannot be overridden by tenant `AuditConfig`. Admitted events remain MUST; general mutation durability is unchanged. Accepted [ADR-0065](decisions/0065-bounded-tenant-assertion-diagnostics.md) owns the evidence-loss and capacity costs; the [remediation record](roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) records delivered implementation and local proofs. | +| **TenantAssertionAuditBudget** | Singleton API-instance allowance shared by scoped recorders: 600 authenticated audit write attempts per independently defended host tenant per first-request-anchored monotonic minute. Failed writes consume allowance; suppressed occurrences retain refusal, counter and one attributed Warning without a durable row or database I/O. It grants no actor-coverage guarantee, adds no tenant-registry cap and cannot be overridden by tenant `AuditConfig`. Admitted events remain MUST; general mutation durability is unchanged. Accepted [ADR-0065](decisions/0065-bounded-tenant-assertion-diagnostics.md) owns the evidence-loss and capacity costs; the [remediation record](roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) records delivered implementation and local proofs. | | **Subject quota** | Additional API request budget keyed on validated issuer and subject, stable across access-token rotation and tenant selection. It does not replace the earlier visitor/peer quotas or promise independent end-to-end throughput. Accepted [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md) owns the decision; P02b-5 implements it. | -| **Subject admission registry** | API-instance singleton retaining at most 4096 validated issuer/subject quota partitions, shared across tenants and hosts. Accepted [ADR-0066](decisions/0066-bounded-tenant-subject-admission.md) bounds idle-only retirement ownership and distinguishes spent quota, registry capacity and sticky cleanup fault. Acquisition can synchronously dispose one limiter; a blocked disposal can indefinitely delay its request and joined shutdown. Its implementation has local runtime/exported proofs; the [implementation record](roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. | +| **Subject admission registry** | API-instance singleton retaining at most 4096 validated issuer/subject quota partitions, shared across tenants and hosts. Accepted [ADR-0066](decisions/0066-bounded-tenant-subject-admission.md) bounds idle-only retirement ownership and distinguishes spent quota, registry capacity and sticky cleanup fault. Acquisition can synchronously dispose one limiter; a blocked disposal can indefinitely delay its request and joined shutdown. Its implementation has local runtime/exported proofs; the [implementation record](roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. | | **ExplicitReadOnlyRequestCatalog** | Singleton immutable exact-type set built from composition declarations. Every MediatR transaction behavior shares this snapshot; naming or a request-supplied flag never selects physical read-only mode. See [ADR-0064](decisions/0064-tenant-api-authentication-boundary.md#closed-authenticated-read). | ## Content & Pages @@ -161,7 +161,7 @@ These entries distinguish P02d-2 contracts from P02d-3 internal read contracts: | Term | Definition | |---|---| | **`IExactCustomizationDefinitionReader`** | Contextual uncached application reader for exact content-type/taxonomy revision values, with NewBinding versus ExistingPin eligibility; [Customization spec](modules/customization/README.md#p02d-2-accepted-exact-write-contract). | -| **`ICustomizationDefinitionProjectionReader`** | Accepted P02d-3 internal batched display reader for exact tenant-owned revision pins, with immutable generation-keyed definition families. Step 3 implements coherent loading, generation caching and scope-safe bypass; both review rounds passed. Not a public API; the [decision package](roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) records acceptance on 2026-10-02. | +| **`ICustomizationDefinitionProjectionReader`** | Accepted P02d-3 internal batched display reader for exact tenant-owned revision pins, with immutable generation-keyed definition families. Step 3 implements coherent loading, generation caching and scope-safe bypass; both review rounds passed. Not a public API; the [decision package](roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) records acceptance on 2026-10-02. | | **`ResolvedLocalizedText`** | An immutable display label paired with its actual authored canonical locale, following [Localization § Fallback Rules](architecture/12-localization.md#fallback-rules). P02d-3 delivers internal metadata; P02d-4 Step 3 delivers its public `{value, locale}` projection. P02d-6 implements page language/direction attributes, independently of the UI fallback language. | | **`ITenantSettingsAccessor`** | Accepted P02d-3 typed, uncached ambient settings reader with registered scope/grammar and explicit organization precedence. Step 1 implements the reader; the [Tenancy contract](modules/tenancy/README.md#p02d-3-accepted-typed-settings-contract) owns its scope. Both review rounds passed. | | **`IPublicTenantConfigurationReader`** | P02d-4's typed internal live-scope and locale configuration reader, on the announced read-only transaction. Valid emptiness, unavailable scope and invalid stored configuration stay distinct; [Tenancy contract](modules/tenancy/README.md#p02d-4-public-configuration-contract). | @@ -335,7 +335,7 @@ These entries distinguish P02d-2 contracts from P02d-3 internal read contracts: Unless explicitly marked Proposed, these terms belong to [Accepted ADR-0047](decisions/0047-transactional-background-job-runtime.md), accepted with the expanded nine-step P02b-4 package on 2026-10-15. The contract is implemented and merged through PR #32 on 2026-10-19; the -[P02b-4 merge closeout](roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) +[P02b-4 merge closeout](roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) owns final implementation, review and CI verification. Production business and recurrence definitions remain empty. @@ -350,7 +350,7 @@ and recurrence definitions remain empty. | **ConfirmedStartReceipt** | Single-use activation evidence minted only after the existing transaction owner receives the start transaction's COMMIT acknowledgement. It distinguishes an acknowledged start from an unknown commit outcome. | | **BackgroundJobRunGate** | Sticky permission for one owned invocation and its finite sequential checkpoint boundaries. Stopping it cannot be reversed by a later durable-history observation. | | **BackgroundJobCommitGate** | One exact checkpoint's issuance and COMMIT admission. Physical acknowledgement, known rollback and locked historical confirmation remain distinct facts; none independently proves cleanup or current lease authority. | -| **Checkpoint confirmation** | Payload-free evidence from a locked, fresh read of an exact original checkpoint. Publication follows the probe's own rollback acknowledgement and actual cleanup; confirmation neither rewrites physical COMMIT history nor mints another business receipt. The [Step 7 record](roadmap/phase-02b-events-auth.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) owns current implementation and qualification. | +| **Checkpoint confirmation** | Payload-free evidence from a locked, fresh read of an exact original checkpoint. Publication follows the probe's own rollback acknowledgement and actual cleanup; confirmation neither rewrites physical COMMIT history nor mints another business receipt. The [Step 7 record](roadmap/phase-02b-delivery-log.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) owns current implementation and qualification. | | **BackgroundJobExternalRecoveryReceipt** | Fresh nonexecuting recovery authority binding the original normal ledger identity separately from the current recovery token, generation and lease. Its immutable purpose comes from the actual stored phase/reason: `Reconcile` permits reconciliation checkpoints; `TerminalNoStart` permits only plan-free NoStart cleanup for an existing terminal request. Neither prepares, executes or fabricates a counted start receipt. | | **BackgroundJobExternalRecoveryRenewal** | Passive evidence from an actual recovery lease UPDATE, published only after physical COMMIT acknowledgement and resource cleanup. The exact still-live Run may accept its newer window; elapsed or stopped authority cannot be revived, and durable-history confirmation alone cannot mint it. | | **JobExternalReadHandle** | Exact acknowledged app-read candidate retained with its original receipt or recovery binding after actual read-owner cleanup. Its canonical envelope and external data supply later attribution and validation, never independent provider permission. | @@ -368,8 +368,8 @@ and recurrence definitions remain empty. | **PlatformMaintenance** | Separate execution class for privileged tenantless maintenance. It is unavailable to ordinary tenant jobs; declaring the class does not authorize a privileged executor. | | **BackgroundJobBridge** | Confined handoff from committed LearnStack intent to an opaque stock Hangfire wakeup. Vendor IDs are repair hints; a missing/failed/succeeded hint cannot complete business work or suppress same-generation repair. P02b-4 Step 4 supplies the bridge and qualified API-host activation; vendor completion remains distinct from business completion. | | **BackgroundJobRuntime** | API-instance facade owning storage bootstrap, pool owners, shared components and the bridge through actual completion. Its shared-source lifetime also waits for both actual messaging processors. See [Events and Outbox](architecture/15-event-and-outbox.md#background-job-transport-and-maintenance); Step 4 implementation and both full reviews are complete; Step 5 extends it with independent renewal, recovery and terminal lanes. | -| **BackgroundJobDurableObservation** | Complete immutable status aggregate classified against frozen local job/recurrence metadata. Publication requires the read transaction's rollback acknowledgement and actual cleanup. Unknown or incompatible durable work remains visible independently of local declarations, due time and previously written deployment markers; the aggregate grants no execution authority. The [Step 9 record](roadmap/phase-02b-events-auth.md#durable-observation-foundation-qualification) owns implementation and qualification. | -| **BackgroundJobObservation** | Required API/Seeder telemetry singleton with a once-bound concrete API runtime. Observable collection projects immutable memory facts and the last complete durable sample without SQL, worker activation or execution/cleanup authority. [Observability Standards](standards/10-observability.md#required-metrics) owns instrument names and finite dimensions; the [Step 9 record](roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) owns implementation and qualification status. | +| **BackgroundJobDurableObservation** | Complete immutable status aggregate classified against frozen local job/recurrence metadata. Publication requires the read transaction's rollback acknowledgement and actual cleanup. Unknown or incompatible durable work remains visible independently of local declarations, due time and previously written deployment markers; the aggregate grants no execution authority. The [Step 9 record](roadmap/phase-02b-delivery-log.md#durable-observation-foundation-qualification) owns implementation and qualification. | +| **BackgroundJobObservation** | Required API/Seeder telemetry singleton with a once-bound concrete API runtime. Observable collection projects immutable memory facts and the last complete durable sample without SQL, worker activation or execution/cleanup authority. [Observability Standards](standards/10-observability.md#required-metrics) owns instrument names and finite dimensions; the [Step 9 record](roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) owns implementation and qualification status. | | **MessagingPrivilegedLifetime** | Closed source-use witness for one actual messaging processor's startup and main loop. Its `PrivilegedCompletion` task requires positive connection cleanup or irrevocable no-issuance closure; finite caller waiting and unrelated app-role callback completion supply no substitute. See [Database Standards](standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity). | | **BackgroundJobPhysicalCapacity** | Conservative simultaneous-acquisition calculation for the current Step 5 topology, enforced before bootstrap. [Database Standards](standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity) owns its formula and qualification limits; it is distinct from tenant job reservations and deployment-wide PostgreSQL sizing. | | **BackgroundJobRuntimeGate** | Process-wide job-start arbitration shared by all pools and independent job-control lanes. Host stop closes starts; final teardown and the closed fatal boundary have distinct ordered terminal states. A prior admission supplies no cleanup or external-quiescence evidence. [ADR-0060](decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md) owns its exceptional failure policy; runtime qualification precedes activation. | @@ -381,7 +381,7 @@ and recurrence definitions remain empty. | **Job execution profile** | A finite definition's transactional or external execution shape. External work separates short prepare/finalize transactions from an operation that runs without a business transaction. | | **Job reservation** | Tenant-wide durable occupancy of a declared capacity group by one job attempt. Lease expiry does not release unresolved external occupancy. | | **External quiescence** | Positive evidence that an old external attempt has ended and cannot start late. Missing heartbeats, expired leases and provider NotFound alone do not prove it. | -| **Completed external failure policy** | Bounded classification of a known external failure and whether the same stable operation may be attempted again. Accepted [ADR-0061](decisions/0061-known-external-job-failure-policy.md) owns the three-state policy and cancellation restriction; the [Step 7 closeout](roadmap/phase-02b-events-auth.md#step-7-full-review-round-2-2026-10-17) owns completed implementation, qualification and both full review rounds. | +| **Completed external failure policy** | Bounded classification of a known external failure and whether the same stable operation may be attempted again. Accepted [ADR-0061](decisions/0061-known-external-job-failure-policy.md) owns the three-state policy and cancellation restriction; the [Step 7 closeout](roadmap/phase-02b-delivery-log.md#step-7-full-review-round-2-2026-10-17) owns completed implementation, qualification and both full review rounds. | | **Job occurrence** | One durable logical UTC slot of a code-declared recurrence, independent of vendor tick IDs and duplicate wakeups. | | **Job recipient** | Immutable tenant/org routing intent for one occurrence, admitted through a restricted stored-row witness before a child job is submitted. | | **BackgroundJobRecipientClaim** | Single-use routing witness from an acknowledged, cleaned-up claim of one stored recipient. It binds the frozen manifest, occurrence, tenant/org and live acquisition; it carries no child job identity or general scheduling authority. | @@ -413,13 +413,13 @@ and recurrence definitions remain empty. | **`IFeatureFlags`** | The **only** module-facing entitlement read: `IsEnabledAsync(FeatureKey)` and `GetLimitAsync(LimitKey)` returning `long`. It resolves the tenant from `ITenantContext` and throws when there is none, so module code can never name another tenant. It **composes** rather than queries: a plan-projected key resolves through `IEntitlementProvider.GetAsync` — not by reading `platform_entitlement_cache` — a tenant-flag key reads `tenant_feature_flags`, and the killswitch overlay is applied last and wins over both. Its implementation lives in `LearnStack.Modules.Tenancy.Infrastructure`, because `tenant_feature_flags` is that module's table, and is registered at the composition root. `IFeatureFlagService` and `IUsageLimitService` are **withdrawn**, not renamed ([ADR-0021](decisions/0021-feature-based-entitlement.md)). Per [ADR-0045 § 2](decisions/0045-entitlement-and-feature-flag-socket.md). | | **`IHostToTenantResolver` / `HostResolution`** | Interface for host → `(tenant_id, organization_id?)` resolution, returning the `HostResolution(TenantId, OrganizationId?)` record or null. Reads `platform_host_to_tenant` and **nothing else** — never the Hub, because an anonymous page load must not depend on a control plane being reachable ([ADR-0034](decisions/0034-hub-contract-surface-invariant.md)). | | **APISIX** | The gateway in standalone YAML-reload mode per [ADR-0015](decisions/0015-api-gateway-apisix.md). The intended tenant-facing ingress, demand-gated to [Phase 11](roadmap/phase-11-production-hardening.md); until then ASP.NET middleware carries the same responsibilities in-process. `/api/internal/*` is never proxied by it — that listener is mTLS-only inside the pod. | -| **`OutboxProcessor`** | The API-host BackgroundService that claims one admitted outbox row immediately before invocation, with a fresh acquisition token in `locked_by`, a database-time lease and one counted attempt. Token/expiry-fenced transitions own retry and explicit audited terminal state; stable worker identity is diagnostic only. Accepted [ADR-0046](decisions/0046-durable-event-delivery-and-recovery.md) governs P02b-2 implementation: Steps 1–2 completed both review rounds, and Step 3 implements hosted execution/observation with both independent review rounds complete. Step 4 enforcement and local closeout are complete; all four steps completed both independent review rounds. P02b-2 is complete and merged; its [merge closeout](roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) owns final verification. P02b-3 delivers the independent shared inbox and subscriber runtime for at-least-once recovery; P02b-3 is complete and merged through PR #31; its [merge closeout](roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. | +| **`OutboxProcessor`** | The API-host BackgroundService that claims one admitted outbox row immediately before invocation, with a fresh acquisition token in `locked_by`, a database-time lease and one counted attempt. Token/expiry-fenced transitions own retry and explicit audited terminal state; stable worker identity is diagnostic only. Accepted [ADR-0046](decisions/0046-durable-event-delivery-and-recovery.md) governs P02b-2 implementation: Steps 1–2 completed both review rounds, and Step 3 implements hosted execution/observation with both independent review rounds complete. Step 4 enforcement and local closeout are complete; all four steps completed both independent review rounds. P02b-2 is complete and merged; its [merge closeout](roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns final verification. P02b-3 delivers the independent shared inbox and subscriber runtime for at-least-once recovery; P02b-3 is complete and merged through PR #31; its [merge closeout](roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. | | **`IUnitOfWork`** | The ambient unit of work: **one database connection per scope**, and the transaction on it ([ADR-0040](decisions/0040-ambient-unit-of-work.md)). Every module `DbContext` resolved in the scope is built on that connection and enlisted in that transaction, and `IAuditStore` and `IOutbox` reach it through the same seam. The connection count is a correctness property, not a performance one: `SET LOCAL app.tenant_id` is connection- **and** transaction-local, so a context on its own connection reads zero rows from every tenant-owned table — silently. It exposes no `SaveChangesAsync`; contexts save themselves and it owns only the transaction boundary. [ADR-0040 Amendment 8](decisions/0040-ambient-unit-of-work.md#amendment-8--read-only-public-frames-2026-10-03) accepts explicit read-only/read-write intent, defaulting to writable: same-mode joins preserve ownership, mixed-mode joins poison the unit, and successful read-only completion permits a later writer. P02d-4 Step 1 delivers these modes and lifecycle controls; poison still requires a fresh scope. | | **`IInboxGuard`** | The shared, transport-owned inbox claim seam, implemented as a transaction-bound primitive in P02b-3 Step 2 and integrated with the business owner in Step 3. Deduplication is `(tenant_id, subscription_id, event_id)`, claimed before handler construction on the announced app-role transaction. Business state, completed inbox, produced outbox, MUST audit and fenced ledger completion commit together; rollback removes a new claim. Handlers do not call the guard, and targeted replay never resets a completed inbox. See [ADR-0046](decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership). | | **Inbox** | Shared tenant-owned completion record for one stable subscription/event pair. A new claim is uncommitted business-transaction work; only successful completion persists it. The delivery ledger owns failed/terminal/replay state. P02b-3 Step 1 implements its canonical DDL in [Database Standards](standards/05-database.md#inbox). | | **Delivery ledger** | Shared `event_deliveries` storage retaining one validated envelope copy per `(tenant_id, subscription_id, event_id)`, independent of the producer row. It owns attempts, leases, completion and terminal/replay state; shared inbox identity owns deduplication. P02b-3 Steps 1–4 implement storage, acceptance, execution and scheduling. See [Database Standards](standards/05-database.md#inbox). | -| **`DeliveryProcessor`** | API-host subscriber worker implemented in P02b-3 Step 4. The confined scheduler claims one exact delivery tuple; a separate app-role executor owns business execution. Retries spend only that subscription's budget, terminal state commits with row-bound MUST audit, and internal replay resets one eligible terminal tuple without broadcast or inbox reset. Controlled tasks retain callbacks/scope cleanup within bounded capacity; the `delivery` health check is registered and unmapped. Step 5 activates both real defaults; the [Step 6 record](roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) and [external follow-ups](roadmap/phase-02b-events-auth.md#p02b-3-second-external-review-follow-up-2026-10-15) own validation/review status; P02b-3 is complete and merged through PR #31, with final verification in its [merge closeout](roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15). | -| **Built-in customization initialization** | Create-only installation of the platform's `card@1` content type and `plain@1` taxonomy, each independently owned by Customization. Any existing concept history is preserved; new IDs are owner-minted, while Seeder verifies matching built-ins semantically and retains warm IDs. P02b-3 Step 5 shares the initializer commands between the two real subscriptions and Seeder. See [Customization's flow](modules/customization/README.md#primary-integration-event-flow-provisioning-defaults) and its [delivery record](roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13). | +| **`DeliveryProcessor`** | API-host subscriber worker implemented in P02b-3 Step 4. The confined scheduler claims one exact delivery tuple; a separate app-role executor owns business execution. Retries spend only that subscription's budget, terminal state commits with row-bound MUST audit, and internal replay resets one eligible terminal tuple without broadcast or inbox reset. Controlled tasks retain callbacks/scope cleanup within bounded capacity; the `delivery` health check is registered and unmapped. Step 5 activates both real defaults; the [Step 6 record](roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) and [external follow-ups](roadmap/phase-02b-delivery-log.md#p02b-3-second-external-review-follow-up-2026-10-15) own validation/review status; P02b-3 is complete and merged through PR #31, with final verification in its [merge closeout](roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15). | +| **Built-in customization initialization** | Create-only installation of the platform's `card@1` content type and `plain@1` taxonomy, each independently owned by Customization. Any existing concept history is preserved; new IDs are owner-minted, while Seeder verifies matching built-ins semantically and retains warm IDs. P02b-3 Step 5 shares the initializer commands between the two real subscriptions and Seeder. See [Customization's flow](modules/customization/README.md#primary-integration-event-flow-provisioning-defaults) and its [delivery record](roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13). | | **Integration-event subscription** | One explicitly identified consumer reaction, independent of handler class or assembly. Its stable `{module}.{subscription}.v{N}` ID versions deduplication semantics, not event schema or built-in revision. Renaming needs a migration/replay decision; a handler refactor preserves identity. [ADR-0046](decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) owns the exact grammar. | | **Subscription readiness** | Construction-free Pending, Active or IntentionallyUnsubscribed declaration in `OutboxEventRegistry`, the closed resolver of declared concrete contracts, compatible aliases and retired identities. Any required Pending subscription holds its contract/aliases before acquisition and validation. Active requires a real registered handler; intentional absence is explicit, never inferred from zero discovered handlers. Accepted P02b-2 policy under [ADR-0046](decisions/0046-durable-event-delivery-and-recovery.md). | | **Outbox lease** | Paired `locked_by` / `locked_until` fields; the former holds a fresh canonical UUID acquisition token, the latter a database-time expiry. Every transition checks both current token and unexpired lease. Recovery replaces expired ownership before another transition. Stable worker identity confers no ownership. | @@ -455,11 +455,14 @@ and recurrence definitions remain empty. | Term | Definition | |---|---| | **Phase** | A roadmap-level milestone with its own `phase-NN-topic.md` file under `docs/roadmap/`. Phases are numbered, sometimes letter-suffixed (`02a` / `02b` / `02c`) when sub-streams ship in parallel or in sequence. Each phase doc carries its own `## Phase Exit Decision` section spelling out the gate that closes the phase. | -| **Packet** | A dependency-ordered shipping slice **within** a phase, sized to be independently reviewable in one pull request. Packet numbering restarts per phase (`P02a-0`, `P02a-1`, …); the canonical reference shape is `P<PhaseId>-<PacketIndex>` (so the kickoff packet of Phase 02a is `P02a-0`). Commit and PR titles use the prose form (`feat(phase-02a): packet 0 — kickoff`). A packet may ship documentation only (e.g. a kickoff packet that defines the breakdown), decisions only (an ADR move from Draft to Accepted), code only, or any combination — but always one phase's worth of progress, no cross-phase bundling. Per-phase packet history lives in the phase doc's Status block (see [phase-01-repository-tooling.md](roadmap/phase-01-repository-tooling.md) for the canonical shape). | +| **Packet** | A dependency-ordered shipping slice **within** a phase, sized to be independently reviewable in one pull request. Packet numbering restarts per phase (`P02a-0`, `P02a-1`, …); the canonical reference shape is `P<PhaseId>-<PacketIndex>` (so the kickoff packet of Phase 02a is `P02a-0`). Commit and PR titles use the prose form (`feat(phase-02a): packet 0 — kickoff`). A packet may ship documentation only (e.g. a kickoff packet that defines the breakdown), decisions only (an ADR move from Draft to Accepted), code only, or any combination — but always one phase's worth of progress, no cross-phase bundling. A packet's state lives in its row of the phase doc's Status block; its dated history lives in the phase's **Delivery Log** ([ADR-0069](decisions/0069-phase-documents-and-delivery-logs.md)). | | **Kickoff Packet** | The first packet of a phase when that phase is large enough to need an explicit plan up front. A kickoff packet ships only the per-packet breakdown for its phase plus any glossary / cross-reference updates the breakdown depends on; no code. Phase 01 did not need one (packets fell out cleanly from the existing scaffold targets); Phase 02a does (the foundation surface is wide). | | **Decision Gate** | An open question a phase document registers because one of its packets cannot be written without the answer; [Roadmap § Decision Timing](roadmap/README.md#decision-timing) owns when and how it closes. Not a phase's exit gate (its `## Phase Exit Decision`), and not one of the four payload-validation gates of [ADR-0043](decisions/0043-customization-payload-validation.md). | | **Decision Pass** | The step a packet of a gated phase opens with, in which the decision gates it waits on are closed; [Roadmap § Decision Timing](roadmap/README.md#decision-timing) defines it. | | **Decision Register** | The table in a phase document with one row per decision gate; [Roadmap § Decision Timing](roadmap/README.md#decision-timing) owns its mechanics, and [Phase 02b](roadmap/phase-02b-events-auth.md#the-decision-register) carries the first. | +| **Delivery Log** | The sibling of a phase document, `docs/roadmap/phase-<id>-delivery-log.md`, holding the phase's dated **Delivery Records**: one `##` section per packet plus the declared `Phase entry`, `Cross-packet records` and `Status archive` sections. Append-only; the phase document stays the plan ([ADR-0069](decisions/0069-phase-documents-and-delivery-logs.md)). It opens with an index generated from its headings — navigation, not a record — which `make docs-index` rewrites. Phase 02a predates it and keeps its records inside its phase document. | +| **Delivery Record** | One entry of a **Delivery Log** — a decision package, a step record, a review round, a correction or a closeout. A shipped packet's records are not rewritten; a false citation gets a dated inline correction ([Documentation Standards § Doc Types](standards/13-documentation.md#doc-types)). Not the log itself. | +| **Decision Package** | The **Delivery Record** a packet's decision pass produces: re-verified premises, the gate answers and the implementation steps they authorize. Once the maintainer accepts it, its answers are normative exactly as the phase document's own text would be, and the **Decision Register** links each one ([Roadmap § Decision Timing](roadmap/README.md#decision-timing)). | | **Walking Skeleton** | A **thin vertical slice through every layer** that produces a working, browser-visible artefact as early as the foundation allows — deliberately shallow in features and complete in path. LearnStack's is [Phase 02d](roadmap/phase-02d-walking-skeleton.md), which owns its scope and exit: two hosts, two tenants in unrelated domains, one backend binary, one database, one schema. Its purpose is evidence, not features: it moves the platform's single most testable claim — that the same code paths serve unrelated education domains — from an assertion five phases away to something a non-engineer can check in a browser. Each capability it touches is delivered shallowly there and completely in its owning phase, and each owning phase records what the skeleton already shipped so no work is claimed twice. | ## List Queries diff --git a/docs/modules/customization/README.md b/docs/modules/customization/README.md index f362ede5..e0768583 100644 --- a/docs/modules/customization/README.md +++ b/docs/modules/customization/README.md @@ -181,7 +181,7 @@ an Active winner from another revision is never retired or adopted by authored s Built-ins use the separate semantic initialization path described below. Ordinary content-type registration enforces the -[accepted authoring quota](../../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19). +[accepted authoring quota](../../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting). Custom-key writers acquire a tenant-wide transaction advisory lock before their concept lock, then count usage and insert inside the same ambient transaction. The standard `limit_exceeded` refusal names the limit key and allowance, maps to @@ -191,7 +191,7 @@ classification. This changes accounting, not deletion or restoration authority. ### Primary integration-event flow: provisioning defaults **Implemented by P02b-3 Step 5; complete and merged through PR #31.** The -[merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) +[merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification; step-level validation/reviews are recorded below. [ADR-0057](../../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) authorizes independent `card@1` content-type and `plain@1` taxonomy initialization @@ -232,7 +232,7 @@ scopes bypass their cache. The writer reader remains uncached. owns family keys, ambient snapshot loading, dirty-scope bypass, fault/cancellation behavior and freshness. The two families include eligible retained revisions and immutable bands; the writer's exact-purpose reader below stays uncached. -[P02d-3's accepted package](../../roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) +[P02d-3's accepted package](../../roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) owns implementation steps and proof obligations. P02d-4's accepted Education consumer uses exact pins and ordered allowlisted string fields, with whole-content unavailable outcomes. Internal field requiredness comes from schema.required; @@ -328,7 +328,7 @@ classified nested command, refusing a failed result rather than completing inbox Seeder discovers built-ins by key/version and verifies their exact Active shape, retaining warm/generated IDs. Authored curriculum identities/pins stay exact. -The [Step 5 record](../../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +The [Step 5 record](../../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns initialization, race and Seeder validation/review status. No other module reacts to a customization change through events today. Public @@ -354,7 +354,7 @@ In [audit.md](audit.md), the file | Path | Budget | Why this number | |---|---|---| | Resolve batched definitions (warm) | **< 1 ms** for in-memory resolution, excluding SQL probe | One fresh generation SELECT; no definition query. End-to-end timing measured separately in P02d-3 | -| Resolve batched definitions (cold/partial/fault) | **< 20 ms** production p95 target, not proven by the local sample | At most two SELECTs: probe plus coherent generation/rows snapshot; [seeded measurements](../../roadmap/phase-02d-walking-skeleton.md#step-3-generation-cache-and-read-safety) report rows/bytes and query plans, not production p95 | +| Resolve batched definitions (cold/partial/fault) | **< 20 ms** production p95 target, not proven by the local sample | At most two SELECTs: probe plus coherent generation/rows snapshot; [seeded measurements](../../roadmap/phase-02d-delivery-log.md#step-3-generation-cache-and-read-safety) report rows/bytes and query plans, not production p95 | | Admit a tenant-authored schema (four gates) | **< 50 ms** p95 | Interactive, on save, and rare | | Validate one instance at the § 8.4 caps | **742 ms, 1.6 GB** | Measured worst case, not a budget — see below | | Publish a successor (2 reads, 2 updates, 1 upsert) | **< 100 ms** p95 | Interactive but rare | diff --git a/docs/modules/customization/audit.md b/docs/modules/customization/audit.md index beb8eb7c..e217b765 100644 --- a/docs/modules/customization/audit.md +++ b/docs/modules/customization/audit.md @@ -158,5 +158,5 @@ A new root is Active at its single save and advances generation once. A preserve concept has no entity change or generation bump, but its initialization attempt remains classified. The transport skips construction for a durable inbox duplicate, so that duplicate adds no business audit. Completed Seeder acts skip the command -before invocation. The [Step 5 record](../../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +before invocation. The [Step 5 record](../../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns validation and review status. diff --git a/docs/modules/customization/permissions.md b/docs/modules/customization/permissions.md index 40c9849a..6b777139 100644 --- a/docs/modules/customization/permissions.md +++ b/docs/modules/customization/permissions.md @@ -69,7 +69,7 @@ The planned Studio editors below own human-facing authorization. Every command takes its tenant from context rather than request input. RLS and `Write_With_Foreign_TenantId_Is_Rejected_By_WithCheck` protect the database write; reachability is the current authorization boundary, not a new permission grant. -The [Step 5 record](../../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +The [Step 5 record](../../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) owns implementation validation/review status. **Every key in the `{module}.{resource}.{action}` form.** The resources above are diff --git a/docs/modules/education/README.md b/docs/modules/education/README.md index 07c05ef0..2ba9712d 100644 --- a/docs/modules/education/README.md +++ b/docs/modules/education/README.md @@ -2,31 +2,31 @@ **Status:** P02d-1 complete and merged — 2026-09-14. Domain, persistence, isolation proofs and both agent review rounds per step are complete. The -[merge closeout](../../roadmap/phase-02d-walking-skeleton.md#merge-and-closeout-2026-09-14) +[merge closeout](../../roadmap/phase-02d-delivery-log.md#merge-and-closeout-2026-09-14) records all five required checks on the final PR head and merge commit. -The [decision pass](../../roadmap/phase-02d-walking-skeleton.md#p02d-1-decision-pass-2026-09-14) +The [decision pass](../../roadmap/phase-02d-delivery-log.md#p02d-1-decision-pass-2026-09-14) records the accepted scope. P02d-2 implements unrouted writers and adds seed execution; P02d-4 Step 3 supplies public Education reads. -The [P02d-2 package](../../roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) +The [P02d-2 package](../../roadmap/phase-02d-delivery-log.md#p02d-2-decision-package-2026-10-02) is Accepted on 2026-10-02. Step 1 implements the course access column and contextual verification queries, explicitly classified Off. Step 3 implements six writers; both review rounds and a focused fix review passed. Step 4 completes the seed after both review rounds. P02d-2 is complete and merged — 2026-10-02; its -[merge closeout](../../roadmap/phase-02d-walking-skeleton.md#p02d-2-merge-and-closeout-2026-10-02) +[merge closeout](../../roadmap/phase-02d-delivery-log.md#p02d-2-merge-and-closeout-2026-10-02) records final verification. P02d-3 read internals are complete and merged through [PR #24](https://github.com/HodeTech/LearnStack/pull/24) on 2026-10-03; its -[merge closeout](../../roadmap/phase-02d-walking-skeleton.md#p02d-3-merge-and-closeout-2026-10-03) +[merge closeout](../../roadmap/phase-02d-delivery-log.md#p02d-3-merge-and-closeout-2026-10-03) records final verification. P02d-4's -[public-read package](../../roadmap/phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) +[public-read package](../../roadmap/phase-02d-delivery-log.md#p02d-4-decision-package-2026-10-03) and [ADR-0052](../../decisions/0052-anonymous-public-read-boundary.md) are Accepted — 2026-10-03. Step 3 implements all three Education GET/HEAD pairs with app-role HTTP/database proofs; both independent review rounds passed. Step 4 adds OpenAPI/SDK/CI controls; both review rounds and fresh fix verification pass. The -[delivery record](../../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) +[delivery record](../../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) records verified live rollout and all six successful required jobs. P02d-4 is complete and merged through [PR #25](https://github.com/HodeTech/LearnStack/pull/25) on 2026-10-08; its -[merge closeout](../../roadmap/phase-02d-walking-skeleton.md#p02d-4-merge-and-closeout-2026-10-08) +[merge closeout](../../roadmap/phase-02d-delivery-log.md#p02d-4-merge-and-closeout-2026-10-08) records final verification. The diagram includes the access column. ## Overview @@ -288,8 +288,8 @@ No Education code names a Customization or Tenancy table. **P02d-4 Step 3 implemented — 2026-10-04; both review rounds complete.** Three institution Education requests dispatch through ISender under `[PublicSurface]`, audit Off and GET/HEAD. Site bootstrap is owned by Tenancy. The -[public DTO/route contract](../../roadmap/phase-02d-walking-skeleton.md#public-routes-and-dto-contract) -and [cursor codec](../../roadmap/phase-02d-walking-skeleton.md#catalog-and-outline-continuation) +[public DTO/route contract](../../roadmap/phase-02d-delivery-log.md#public-routes-and-dto-contract) +and [cursor codec](../../roadmap/phase-02d-delivery-log.md#catalog-and-outline-continuation) fix the allowlist and protocol before v1 freezes; no internal/seed DTO is exported. - Require resolved matching factory HostScope. Tenant host: tenant-wide rows only; @@ -325,7 +325,7 @@ fix the allowlist and protocol before v1 freezes; no internal/seed DTO is export The public no-schema-evaluation guard is Implemented with direct, concrete and transitive/interface controls. App-role HTTP/database cases exercise the source queries and wire contracts; measurements and review evidence belong to the -[Step 3 delivery record](../../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-3-public-education-reads). +[Step 3 delivery record](../../roadmap/phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads). Step 4 implements the recursive OpenAPI response guard with nested leak controls. [EducationPersistenceTests](../../../backend/tests/LearnStack.Tests.Integration/Database/EducationPersistenceTests.cs) diff --git a/docs/modules/tenancy/README.md b/docs/modules/tenancy/README.md index a353e7f4..43499b42 100644 --- a/docs/modules/tenancy/README.md +++ b/docs/modules/tenancy/README.md @@ -76,7 +76,7 @@ Tenancy owns **who a request belongs to** and nothing about what they do with it ## P02d-2 accepted locale and branding contract **Step 2 complete after both review rounds — 2026-10-02.** The [phase -package](../../roadmap/phase-02d-walking-skeleton.md#p02d-2-decision-package-2026-10-02) +package](../../roadmap/phase-02d-delivery-log.md#p02d-2-decision-package-2026-10-02) records approval and seed inventory. All three commands are unrouted, require resolved tenant-wide context and write one aggregate; organization context is refused rather than silently promoted to tenant scope. Tenant ids are not caller authority. @@ -150,7 +150,7 @@ No caller tenant/org IDs or cross-module table join is introduced. ADR-0052; no-store applies to all responses. Direct internal contracts inherit the ambient mode and create no request/audit intent. -[The accepted public allowlist](../../roadmap/phase-02d-walking-skeleton.md#public-routes-and-dto-contract) +[The accepted public allowlist](../../roadmap/phase-02d-delivery-log.md#public-routes-and-dto-contract) owns serialized fields; HTTP/database positive controls are required before exit. No platform locale registry is introduced. Admission uses the existing `LocaleTag` @@ -175,7 +175,7 @@ physical READ ONLY frame. The live configuration reader independently retains its host, enlistment, tenant/organization lifecycle and locale checks. Theme/null and attribution follow the public contract above; `branding.theme` stays tenant-wide. P02b-5 Step 4 exposes only `GET /api/v1/account/site`; its -[delivery record](../../roadmap/phase-02b-events-auth.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) +[delivery record](../../roadmap/phase-02b-delivery-log.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) owns HTTP validation and review status. ### Whole-theme setting and public boundary @@ -245,7 +245,7 @@ entry. The accessor uses the existing announced ambient transaction, without opening/announcing a new one or retaining a per-scope value snapshot. A subsequent read observes supported writes under the ambient isolation. Measure the indexed read/selection budget in P02d-3. The -[accepted package](../../roadmap/phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) +[accepted package](../../roadmap/phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) records the tests and step plan. ### Job lifecycle projection @@ -255,7 +255,7 @@ projection. The framework reads only the minimal columns allowed by [Database Standards](../../standards/05-database.md#job-lifecycle-projection); tenantless orchestration constructs no Tenancy service and accepts no arbitrary tenant selector. The additive Tenancy migration owns this SELECT-only grant. -The [Step 8 record](../../roadmap/phase-02b-events-auth.md#p02b-4-step-8--durable-recurrence-and-restricted-fan-out-2026-10-18) +The [Step 8 record](../../roadmap/phase-02b-delivery-log.md#p02b-4-step-8--durable-recurrence-and-restricted-fan-out-2026-10-18) owns implementation and pending complete qualification. ## Entity-relationship diagram @@ -528,7 +528,7 @@ announcement while provisioning ambient context remains unresolved. State, event and the existing two MUST audit rows share one transaction. P02b-1 persists pending rows; P02b-2 implements hosted dispatch and production-census enforcement. All four steps completed both independent review rounds and local closeout. -The [merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +The [merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. P02b-3 Steps 1–4 implement consumer ownership and scheduling; Step 5 supplies the two actual default subscriptions and semantic Seeder handoff. @@ -537,10 +537,10 @@ P02b-3 Step 5 activates both real Customization subscriptions together over transport-owned inbox and independent delivery ledger. The stable identities are `customization.initialize-content-type-default.v1` for `card@1` content type and `customization.initialize-taxonomy-default.v1` for `plain@1` taxonomy. The -[Step 5 record](../../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) +[Step 5 record](../../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) records validation and reviews; neither subscription is a placeholder. P02b-3 is complete and merged through PR #31; its -[merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) +[merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. | Topic | Payload | Publisher | Consumers | Phase | diff --git a/docs/modules/tenancy/audit.md b/docs/modules/tenancy/audit.md index 27c9f545..47afc5c7 100644 --- a/docs/modules/tenancy/audit.md +++ b/docs/modules/tenancy/audit.md @@ -10,10 +10,10 @@ aggregate. A failed MUST write rolls back tenant, organization and outbox togeth The [integration-event catalogue](README.md#integration-event-catalogue) owns the flow; P02b-2 implements hosted producer dispatch and production-census enforcement. All four steps completed both independent review rounds and local closeout. -The [merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +The [merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. P02b-3 Steps 1–5 implement durable subscriber delivery and both real defaults; its -[Step 6 record](../../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current enforcement and review status. **ADR-0046 producer terminal writer implemented — 2026-10-12; both review rounds @@ -152,7 +152,7 @@ unmarked row is one a shipped command already raises. | `platform_entitlement_cache` | `tenancy.entitlement.refresh` `(planned)` `(off-path)` | **MUST** | Changes what the tenant may do; written only by `IEntitlementProvider.RefreshAsync`, a port method driven by the Hub over `/api/internal/*` ([ADR-0045 § 1](../../decisions/0045-entitlement-and-feature-flag-socket.md)) and never by a MediatR request, so there is no request type to key a catalogue entry on. **Both markers**, for the reason `tenancy.killswitch.toggle` carries both: Packet 9 ships `NullEntitlementProvider`, which answers from constants and touches no table, and the `HubEntitlementProvider` that performs a real refresh lands in [Phase 02c](../../roadmap/phase-02c-hub-foundation.md) ([ADR-0045 § 6](../../decisions/0045-entitlement-and-feature-flag-socket.md)) — so there is no writer here yet either | | `platform_host_to_tenant` | `tenancy.hostmapping.write` | **MUST** | The resolution index — the row that decides whose data an anonymous request sees | | `platform_host_to_tenant` | `tenancy.hostmapping.delete` `(planned)` | **MUST** | The same row removed. The table carries no `deleted_at`, so the delete is a row gone and a host that resolves to nobody | -| `TenantAssertion` | `tenancy.tenant_assertion.reject` `(off-path)` | **MUST** for admitted events (`security-event`) | A validated header/claim mismatch with an independently defended host tenant is recorded under that host tenant, never the asserted tenant or sentinel; row 14 is counted only. [ADR-0065](../../decisions/0065-bounded-tenant-assertion-diagnostics.md) admits 600 authenticated standalone write attempts per host tenant per API instance per first-request-anchored monotonic minute, shared across scoped recorders, actors, sources and dimensions. Failed writes consume permits; later occurrences make no audit-store call and retain their refusal, count and exactly one attributed Warning (4006 replaces normal 4001). An attacker can exhaust the allowance, so later actors lose durable evidence; aggregate log volume remains unbounded. Admitted events retain MUST failure/health behavior, tenant-wide organization scope, exact actor/correlation and trusted organization in metadata. No tenant `AuditConfig` override or independent tenant-registry cap exists. General mutation MUST durability is unchanged. Packet 9 owns the recorder/decorator path; P02b-5 Steps 3–4 implement JWT attribution and HTTP activation under ADR-0064. ADR-0065 acceptance precedes the dependent budget implementation; the [merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) owns its final delivery status | +| `TenantAssertion` | `tenancy.tenant_assertion.reject` `(off-path)` | **MUST** for admitted events (`security-event`) | A validated header/claim mismatch with an independently defended host tenant is recorded under that host tenant, never the asserted tenant or sentinel; row 14 is counted only. [ADR-0065](../../decisions/0065-bounded-tenant-assertion-diagnostics.md) admits 600 authenticated standalone write attempts per host tenant per API instance per first-request-anchored monotonic minute, shared across scoped recorders, actors, sources and dimensions. Failed writes consume permits; later occurrences make no audit-store call and retain their refusal, count and exactly one attributed Warning (4006 replaces normal 4001). An attacker can exhaust the allowance, so later actors lose durable evidence; aggregate log volume remains unbounded. Admitted events retain MUST failure/health behavior, tenant-wide organization scope, exact actor/correlation and trusted organization in metadata. No tenant `AuditConfig` override or independent tenant-registry cap exists. General mutation MUST durability is unchanged. Packet 9 owns the recorder/decorator path; P02b-5 Steps 3–4 implement JWT attribution and HTTP activation under ADR-0064. ADR-0065 acceptance precedes the dependent budget implementation; the [merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns its final delivery status | | `TenantAssertion` | `tenancy.tenant_assertion.anonymous_burst` `(off-path)` | **MUST** (`security-event`) | The anonymous half of the same detector, written once per `(resolved tenant, dimension, window)` when the mismatch counter crosses its threshold. An anonymous mismatch is not itself an audited operation; the burst is — the precedent the baseline's "login failure burst" already sets ([ADR-0036 Amendment 7](../../decisions/0036-tenant-resolution-trusted-inputs.md)). Same writer, and `(off-path)` for the same reason. The window is **in-process** and never `ICacheService` — a cache outage must not decide whether a MUST-class security event is recorded — so the effective threshold is per instance, which errs toward more auditing. `Tenancy:AssertionBurst` sets it; the defaults are ten occurrences in five minutes | | any | `platform.admin_scope.enter` `(off-path)` | **MUST** (`security-event`) | Cross-tenant access is the one read worth a row; [Audit Coverage](../../standards/18-audit-coverage.md) puts every platform-bypass invocation on `security-event`. [Packet 9](../../roadmap/phase-02a-kernel-tenancy.md) ships it: `PlatformAdminScope.EnterAsync` writes the row through `IAuditStore.WritePlatformScopeAsync` on the scope's own platform-role connection, in a transaction of its own that **commits before** the caller's begins — so work that later fails, throws or is abandoned cannot take the record with it — carrying `TenantId.PlatformSentinel` ([ADR-0044 § 1, § 10](../../decisions/0044-audit-write-path.md)). An entry the catalogue cannot classify, or whose row cannot be written, is **refused** — no transaction is handed out for it. The `Warning` log line stays beside the row, carrying its id, as the real-time signal the row is not. `EnterAsync` is a service method and not a MediatR request, and the catalogue is keyed by request type — so its catalogue entry is registered by slug rather than by request type. Its module segment is `platform` for the same reason: the scope belongs to no module's request path | diff --git a/docs/modules/tenancy/permissions.md b/docs/modules/tenancy/permissions.md index 85f889cd..70d62e3b 100644 --- a/docs/modules/tenancy/permissions.md +++ b/docs/modules/tenancy/permissions.md @@ -18,7 +18,7 @@ Existing command reachability is unchanged. The [integration-event catalogue](README.md#integration-event-catalogue) owns the flow. **ADR-0046 P02b-2 complete and merged — 2026-10-13.** All four steps -completed both independent review rounds. The [merge closeout](../../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +completed both independent review rounds. The [merge closeout](../../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. The API-owned dispatcher and terminal audit add no permission key or HTTP endpoint. P02b-3's diff --git a/docs/roadmap/README.md b/docs/roadmap/README.md index f3b7384b..6847d264 100644 --- a/docs/roadmap/README.md +++ b/docs/roadmap/README.md @@ -45,151 +45,13 @@ not deferred to the showcase phase. - [Phase 01: Repository, Tooling, and Local Infrastructure](phase-01-repository-tooling.md) — **complete** - [Phase 02a: Platform Kernel, Multi-Tenancy, Organization, and Foundation Sockets](phase-02a-kernel-tenancy.md) — **complete** (packets 0–3, 3b and 4–10 shipped) - [Phase 02d: Two-Tenant Walking Skeleton](phase-02d-walking-skeleton.md) — - **complete and merged — 2026-10-11**. - P02d-1 and P02d-2 complete and merged; the - [P02d-2 closeout](phase-02d-walking-skeleton.md#p02d-2-merge-and-closeout-2026-10-02) - records final verification. P02d-3 read internals are implemented; the - [decision package](phase-02d-walking-skeleton.md#p02d-3-decision-package-2026-10-02) - is Accepted — 2026-10-02; Step 1 is implemented; both review rounds passed. - Step 2 implements batched definition reads; both review rounds passed. - Step 3 adds generation caching and scope-safe bypass; both review rounds passed. - P02d-3 is complete and merged through - [PR #24](https://github.com/HodeTech/LearnStack/pull/24) on 2026-10-03; its - [merge closeout](phase-02d-walking-skeleton.md#p02d-3-merge-and-closeout-2026-10-03) - records final verification. P02d-4's - [public-read decision package](phase-02d-walking-skeleton.md#p02d-4-decision-package-2026-10-03) - is Accepted — 2026-10-03; all four implementation steps and their review loops - are complete. All six real required CI jobs pass and live sixth-check activation - is verified. P02d-4 is complete and merged through - [PR #25](https://github.com/HodeTech/LearnStack/pull/25) on 2026-10-08; its - [merge closeout](phase-02d-walking-skeleton.md#p02d-4-merge-and-closeout-2026-10-08) - records final verification. P02d-5's decision package and ADR-0053 are Accepted - — 2026-10-08. All four steps and both fresh review rounds per step are complete. - The [remediation and closeout record](phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) - owns delivery and review evidence. P02d-5 is complete and merged through - [PR #26](https://github.com/HodeTech/LearnStack/pull/26) on 2026-10-09; its - [merge closeout](phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) - records final verification. - P02d-6's ADR-0027 and decision package are Accepted — 2026-10-09. Its localized - catalog/course/lesson pages and product proofs are implemented; the - [closeout record](phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) - records completed reviews and scoped browser/VoiceOver observations. - The original implementation is complete. ADR-0055 remediation delivers - single-bootstrap admission and passing production replacement proofs. All three - steps completed both independent review rounds; - the [Step 3 record](phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) - owns completed Step 3 reviews, verified fixes and delivery evidence. P02d-6 is - complete and merged through [PR #27](https://github.com/HodeTech/LearnStack/pull/27) - on 2026-10-10; its - [merge closeout](phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) - records final verification. P02d-7's demo, Lighthouse and phase-exit - [decision package](phase-02d-walking-skeleton.md#p02d-7-decision-package-2026-10-10) - and ADR-0056 were approved on 2026-10-11. All four steps completed both independent - review rounds. The shared demo, genericity fences and seeded browser/Lighthouse - proof pass real CI; the seventh required context is active. The - [Step 4 record](phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) - owns CI enforcement, reviews and the positive phase-exit verdict. - [PR #28](https://github.com/HodeTech/LearnStack/pull/28) is merged; its - [merge closeout](phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) - owns final verification and the completed phase exit. - The [individual exit evidence](phase-02d-exit-evidence.md) maps each exit - criterion to its actual proof and completed disposition. + **complete and merged — 2026-10-11** through PR #28. Its Status block links each + packet's merge closeout; the [individual exit evidence](phase-02d-exit-evidence.md) + maps each exit criterion to its proof. - [Phase 02b: Events, Background Jobs, Identity, and Session](phase-02b-events-auth.md) - — **P02b-0 through P02b-5 complete; P02b-1–5 merged through PRs #29–33**. - P02b-6 implementation is complete locally; the correction records below own - validation and independent reviews. - [PR #34](https://github.com/HodeTech/LearnStack/pull/34) records current-head - hosted qualification and maintainer review. Merge remains separate; - P02b-7–8 are pending. Its - [entry audit](phase-02b-events-auth.md#p02b-0-entry-verification-2026-10-12) - verifies the inherited baseline; Accepted ADR-0057 and the - [producer package](phase-02b-events-auth.md#p02b-1-decision-package-2026-10-12) - authorize the implemented lifecycle, enqueue and provisioning publisher. The - [P02b-1 merge closeout](phase-02b-events-auth.md#p02b-1-merge-and-closeout-2026-10-12) - records final CI verification and the completed delivery/review history. - P02b-2 delivers hosted dispatch, fenced recovery, atomic terminal audit, - confined credentials and observation/enforcement under Accepted ADR-0046. - All four steps and correction bundles completed both independent review rounds; - its [merge closeout](phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) - owns final verification. P02b-3 Steps 1–5 implement durable acceptance, shared - inbox/ledger, independent subscriber retries, both real default subscriptions - and semantic Seeder handoff. Its - [Step 6 record](phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) - records completed enforcement/regression and both review rounds for all six - steps. The - [external follow-up](phase-02b-events-auth.md#p02b-3-external-review-follow-up-2026-10-15) - adds verified corrections and two further independent review rounds; the - [second follow-up](phase-02b-events-auth.md#p02b-3-second-external-review-follow-up-2026-10-15) - records subsequent runtime/proof corrections and their completed reviews. - P02b-3 is complete and merged through PR #31 on 2026-10-15; its - [merge closeout](phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) - owns final verification. - P02b-4 is complete and merged through PR #32 on 2026-10-19. Its - [merge closeout](phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) - records all nine runtime steps, three CI steps, completed independent reviews - and both complete final-source hosted assignments. Production business and - recurrence definitions remain empty. P02b-5's - [decision package](phase-02b-events-auth.md#p02b-5-decision-package-2026-10-19) - and ADR-0064/0065/0066 are Accepted; five implementation steps, each with two - fresh independent review rounds, are authorized. Step 1 completes the isolated - token foundation after both independent reviews; its - [record](phase-02b-events-auth.md#p02b-5-step-1--token-foundation-2026-10-19) - owns the verified metric-privacy correction. Step 2 completes the real read-only - subject after both independent review rounds; its - [record](phase-02b-events-auth.md#p02b-5-step-2--real-read-only-application-subject-2026-10-19) - owns validation. Step 3 completes attributed reconciliation and subject - admission after both independent reviews; its - [record](phase-02b-events-auth.md#p02b-5-step-3--attributed-reconciliation-and-subject-admission-2026-10-19) - owns verified corrections. Step 4 installs the complete HTTP boundary and typed - contract; its [record](phase-02b-events-auth.md#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) - owns validation and both completed reviews. Step 5 completes the authority - census, carrier reconciliation and both review rounds; its - [local closeout](phase-02b-events-auth.md#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) - retains its source-bound pre-merge scope. **P02b-5 is complete and merged** - through [PR #33](https://github.com/HodeTech/LearnStack/pull/33) on 2026-10-20. - Its [merge closeout](phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) - owns final-source CI, unchanged-plan A/B qualification and identical merge - trees. P02b-6's realm/TTL - [decision pass](phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) - is Accepted — 2026-10-21, including its four implementation steps. G12's - realm/reconciliation/callback choices and G13's issuance-TTL part are Accepted; - the dedicated issuance follow-up - [ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) is - Accepted — 2026-10-21 after separate maintainer approval, with no runtime or - G13 session-policy change. - The [additional correction record](phase-02b-events-auth.md#p02b-6-additional-verification-and-correction-pass-2026-10-22) - owns current findings; [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) - is Accepted — 2026-10-22 after verified review corrections under conditional - maintainer authority. Its [first correction step](phase-02b-events-auth.md#adr-0068-step-1--qualified-stock-assignment-implementation-2026-10-22) - completes both review rounds locally. Its - [second correction step](phase-02b-events-auth.md#adr-0068-step-2--owned-visibility-preparation-2026-10-22) - completes owned preparation and fresh planning after both independent review - rounds. Its [third correction step](phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) - completes local historical entry, credential/MFA, signed API and self-service - proof after both review rounds, and owns source-bound hosted qualification. - Step 1 is complete locally after both review rounds; its - [record](phase-02b-events-auth.md#p02b-6-step-1--executable-realm-and-identity-declaration-2026-10-21) - owns fresh-provider qualification and implementation reviews. Step 2 is - complete locally after both review rounds and fresh fix reviews; its [record](phase-02b-events-auth.md#p02b-6-step-2--owned-warm-realm-reconciliation-2026-10-21) - owns the Accepted server-information response allowance and actual correction - qualification. Step 3 is complete locally after both review rounds and fresh - corrections; its - [record](phase-02b-events-auth.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21) - owns actual seed/demo and cancellation evidence. Step 4's - [record](phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) - owns completed local provider/API proofs, both independent review rounds and - source-bound correction/CI receipts. The correction record above owns exact - hosted assignments and evidence limits; merge remains separate. All four steps - are complete locally; - G13's session part stays Open. - The [second external-review follow-up](phase-02b-events-auth.md#p02b-5-second-external-review-follow-up-2026-10-20) - retains its source-bound corrections. [ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) - is Accepted — 2026-10-20; its subject-cap, cleanup and refusal refinements are - implemented with local runtime/exported proofs. Its - [implementation record](phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) - retains source-bound validation and independent reviews; the merge closeout - above owns final-source qualification. - BFF sessions and phase-exit enforcement remain P02b-7–8. + — **in progress**: P02b-0–5 complete and merged through PRs #29–#33; P02b-6's + implementation merged through PR #34; P02b-7–8 pending. Its Status block owns + packet state. - [Phase 03: Identity Domain, Authorization, and Admin Foundation](phase-03-identity-admin.md) - [Phase 04: Headless CMS, Page Builder, and Media Library](phase-04-cms-media-pages.md) - [Phase 05: Education Catalog and Learning Content](phase-05-education-learning-content.md) @@ -293,7 +155,7 @@ retrofit**, and **thin where it is not**: including `Core_Modules_HaveNo_DomainSpecific_Names`, which keeps every name the platform ships free of the forbidden domain terms. That rule reads names and strips literals. P02d-7's - [G20 controls](phase-02d-walking-skeleton.md#p02d-7-genericity-enforcement) + [G20 controls](phase-02d-delivery-log.md#p02d-7-genericity-enforcement) add typed exact identity matching across nonempty backend/frontend/JSON subjects, compiled/restore-resolved Seeder-reference bans and planted dirty/clean controls. The production schema-replacement proof complements that source fence; @@ -336,9 +198,37 @@ Three exceptions, all deliberate: convention and carries `## Technical Notes` instead. Its annotation block records this; it is not a gap to fill. -Phases in progress additionally carry a dated `> **Status**` block at the top, listing -packets and their state. A **packet** is an independently reviewable, independently -mergeable slice with its own pull request; see [Glossary](../glossary.md). +A phase with packets additionally carries a dated `> **Status**` block above `## Goal`, +in progress and after completion: the phase's state and one packet table whose rows +link each packet's records. A **packet** is an independently reviewable, +independently mergeable slice with its own pull request; see [Glossary](../glossary.md). + +**Plan and record live in separate files** +([ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md)): + +- The **phase document** is the plan. Further plan sections may sit between + `## Goal` and `## Phase Exit Decision`; nothing follows `## Phase Exit Decision`. It + holds no records: no heading carries a date, a packet identifier (`P02b-4`) or the + words *delivery record*, *review round*, *closeout*, *decision package* or *decision + pass*. Its Status block stays within 40 non-blank lines and the whole file within + 2,000 lines. +- The **delivery log**, `phase-<id>-delivery-log.md`, is the phase's dated record: + one `##` section per packet (`P02b-4 — Background jobs`), plus `Phase entry`, + `Cross-packet records` and `Status archive` where needed, each entry a dated `###` + heading. It is append-only; a shipped packet's entries are not rewritten. It opens + with an index generated from its headings — `make docs-index` writes it, CI refuses + a stale one — so a reader opens the index and then only the entry it needs. +- An optional **exit evidence index**, `phase-<id>-exit-evidence.md`, maps each exit + criterion to its proof at phase exit, as + [Phase 02d's](phase-02d-exit-evidence.md) does. +- **Status lives once.** Packet state lives in the Status block and gate state in the + decision register. § Phases above gives each phase at most six lines and links no + delivery log; `CLAUDE.md` and the repository README link none at all. + +[Phase 02a](phase-02a-kernel-tenancy.md) keeps its frozen single-file shape, with its +delivery records after its exit decision. `scripts/roadmap-structure.py` and +`scripts/markdown-fragment-audit.py` hold every other phase to these rules in CI and in +`make lint-docs`. The roadmap deliberately carries **no effort estimates, owners, or timeboxes**. It is a dependency and scope plan; sequencing decisions belong here, capacity decisions do not. @@ -376,9 +266,12 @@ Each open question is a **gate**, answered at its last responsible moment: - **Acceptance is explicit.** Preserve each original gate question and record `Accepted — YYYY-MM-DD` with a link to its answer and accepted vehicle, including phase-doc, standard and catalogue answers. For a split gate, name exactly the part - closed and the parts still open. Each packet's status and delivery record list its - closed parts. A Proposed record closes nothing. This notation applies roadmap-wide, - accepted in [P02d-1's decision pass](phase-02d-walking-skeleton.md#p02d-1-accepted-answers) + closed and the parts still open. Each packet's Status row and its decision package + in the [delivery log](#phase-structure) list its closed parts. A gate whose vehicle is + the phase document is answered in that dated decision package: once Accepted, it is + normative exactly as the phase document's own text would be, and the register links + it. A Proposed record closes nothing. This notation applies roadmap-wide, + accepted in [P02d-1's decision pass](phase-02d-delivery-log.md#p02d-1-accepted-answers) on 2026-09-14. - **A register pre-assigns nothing that moves.** An amendment takes the next free number on the day it is written. A phase that waits behind another re-verifies its register diff --git a/docs/roadmap/phase-02b-delivery-log.md b/docs/roadmap/phase-02b-delivery-log.md new file mode 100644 index 00000000..a558a571 --- /dev/null +++ b/docs/roadmap/phase-02b-delivery-log.md @@ -0,0 +1,17791 @@ +# Phase 02b — delivery log + +The dated record of +[Phase 02b: Events, Background Jobs, Identity, and Session](phase-02b-events-auth.md). +The phase document holds the plan and the current Status; this log holds what +each packet decided and delivered, as +[ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md) decides. + +- **Append-only.** A new entry is a `###` heading under its packet's `##` + section, with its date in the heading. A shipped packet's entries are not + rewritten; a false citation gets the dated inline correction + [Documentation Standards § Doc Types](../standards/13-documentation.md#doc-types) + prescribes. +- **Decision packages are normative.** An Accepted package's answers bind exactly + as the phase document would; the phase document's decision register links each + one. +- **Moved, not rewritten.** Every entry dated up to 2026-10-22 moved here from the + phase document with its heading text and anchor unchanged. Heading levels shifted + to sit under the packet sections, and links whose targets now live in the other + file were retargeted. Position words inside a moved entry — *above*, *below*, + *the register* — still mean the single document it was written in; the plan + sections they point at now live in the phase document. The + [Status archive](#status-archive) keeps the retired Status block. +- **Read the index, not the log.** The index below lists every packet section, + every entry and every dated sub-entry with its length in lines. Pick the entry + there, search for its heading to find its line, and read only that many lines. + After adding an entry, run `make docs-index`: the index is generated navigation, + not a record, and CI refuses a stale one. + +<!-- BEGIN GENERATED INDEX: scripts/delivery-log-index.py — run `make docs-index`; do not edit by hand --> + +**Index** + +- [P02b-0 — Phase entry](#p02b-0--phase-entry) — 127 lines + - [P02b-0 entry verification (2026-10-12)](#p02b-0-entry-verification-2026-10-12) — 125 lines +- [P02b-1 — Producer](#p02b-1--producer) — 731 lines + - [P02b-1 decision package (2026-10-12)](#p02b-1-decision-package-2026-10-12) — 171 lines + - [Maintainer acceptance — 2026-10-12](#maintainer-acceptance--2026-10-12) — 9 lines + - [P02b-1 Step 1 — Shared execution lifecycle (2026-10-12)](#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) — 90 lines + - [P02b-1 Step 2 — Immediate outbox production (2026-10-12)](#p02b-1-step-2--immediate-outbox-production-2026-10-12) — 70 lines + - [P02b-1 Step 3 — Domain completion and provisioning publisher (2026-10-12)](#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) — 60 lines + - [P02b-1 Step 4 — Producer enforcement and closeout (2026-10-12)](#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) — 79 lines + - [P02b-1 packet closeout (2026-10-12)](#p02b-1-packet-closeout-2026-10-12) — 209 lines + - [PR #29 external-review proof follow-up (2026-10-12)](#pr-29-external-review-proof-follow-up-2026-10-12) — 35 lines + - [PR #29 systematic-review remediation (2026-10-12)](#pr-29-systematic-review-remediation-2026-10-12) — 61 lines + - [PR #29 outbox INSERT and ownership follow-up (2026-10-12)](#pr-29-outbox-insert-and-ownership-follow-up-2026-10-12) — 34 lines + - [P02b-1 merge and closeout (2026-10-12)](#p02b-1-merge-and-closeout-2026-10-12) — 50 lines +- [P02b-2 — Dispatcher](#p02b-2--dispatcher) — 967 lines + - [P02b-2 decision package (2026-10-12)](#p02b-2-decision-package-2026-10-12) — 257 lines + - [Proposal review and validation (2026-10-12)](#proposal-review-and-validation-2026-10-12) — 22 lines + - [External proposal review reconciliation (2026-10-12)](#external-proposal-review-reconciliation-2026-10-12) — 37 lines + - [P02b-2 acceptance (2026-10-12)](#p02b-2-acceptance-2026-10-12) — 18 lines + - [P02b-2 Step 1 — Decision, schema and confined composition (2026-10-12)](#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) — 74 lines + - [P02b-2 Step 2 — Durable transitions and terminal audit (2026-10-12)](#p02b-2-step-2--durable-transitions-and-terminal-audit-2026-10-12) — 98 lines + - [P02b-2 Step 3 — Hosted lifecycle and observability (2026-10-12)](#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) — 89 lines + - [P02b-2 Step 4 — Enforcement and closeout (2026-10-12)](#p02b-2-step-4--enforcement-and-closeout-2026-10-12) — 111 lines + - [P02b-2 PR handoff (2026-10-12)](#p02b-2-pr-handoff-2026-10-12) — 20 lines + - [P02b-2 PR review follow-up (2026-10-13)](#p02b-2-pr-review-follow-up-2026-10-13) — 31 lines + - [P02b-2 external review remediation (2026-10-13)](#p02b-2-external-review-remediation-2026-10-13) — 95 lines + - [P02b-2 review of 3531a2eb (2026-10-13)](#p02b-2-review-of-3531a2eb-2026-10-13) — 111 lines + - [Snapshot interval correction (2026-10-13)](#snapshot-interval-correction-2026-10-13) — 16 lines + - [P02b-2 merge and closeout (2026-10-13)](#p02b-2-merge-and-closeout-2026-10-13) — 61 lines +- [P02b-3 — Consumer](#p02b-3--consumer) — 1,359 lines + - [P02b-3 decision package (2026-10-13)](#p02b-3-decision-package-2026-10-13) — 383 lines + - [Maintainer acceptance (2026-10-13)](#maintainer-acceptance-2026-10-13) — 11 lines + - [P02b-3 Step 1 — shared storage and privileges (2026-10-13)](#p02b-3-step-1--shared-storage-and-privileges-2026-10-13) — 75 lines + - [P02b-3 Step 2 — durable acceptance and inbox primitives (2026-10-13)](#p02b-3-step-2--durable-acceptance-and-inbox-primitives-2026-10-13) — 79 lines + - [P02b-3 Step 3 — business owner and completion gate (2026-10-13)](#p02b-3-step-3--business-owner-and-completion-gate-2026-10-13) — 99 lines + - [P02b-3 Step 4 — subscriber scheduling, terminalization and replay (2026-10-13)](#p02b-3-step-4--subscriber-scheduling-terminalization-and-replay-2026-10-13) — 111 lines + - [P02b-3 Step 5 — useful defaults and semantic seed handoff (2026-10-13)](#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) — 75 lines + - [P02b-3 Step 6 — production enforcement and PR closeout (2026-10-13)](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) — 143 lines + - [P02b-3 PR handoff (2026-10-13)](#p02b-3-pr-handoff-2026-10-13) — 22 lines + - [P02b-3 external review follow-up (2026-10-15)](#p02b-3-external-review-follow-up-2026-10-15) — 140 lines + - [P02b-3 second external review follow-up (2026-10-15)](#p02b-3-second-external-review-follow-up-2026-10-15) — 170 lines + - [P02b-3 merge and closeout (2026-10-15)](#p02b-3-merge-and-closeout-2026-10-15) — 60 lines +- [P02b-4 — Background jobs](#p02b-4--background-jobs) — 7,119 lines + - [P02b-4 decision package (2026-10-15)](#p02b-4-decision-package-2026-10-15) — 352 lines + - [Maintainer acceptance (2026-10-15)](#maintainer-acceptance-2026-10-15) — 15 lines + - [Hangfire comparison follow-up (2026-10-15)](#hangfire-comparison-follow-up-2026-10-15) — 24 lines + - [Workload and corpus correction pass (2026-10-15)](#workload-and-corpus-correction-pass-2026-10-15) — 50 lines + - [P02b-4 Step 1 — contracts and authority (2026-10-16)](#p02b-4-step-1--contracts-and-authority-2026-10-16) — 89 lines + - [P02b-4 Step 2 — storage and guarded vendor bootstrap (2026-10-16)](#p02b-4-step-2--storage-and-guarded-vendor-bootstrap-2026-10-16) — 350 lines + - [Step 2 maintenance acceptance (2026-10-16)](#step-2-maintenance-acceptance-2026-10-16) — 29 lines + - [P02b-4 Step 3 — submission and app-role admission (2026-10-16)](#p02b-4-step-3--submission-and-app-role-admission-2026-10-16) — 129 lines + - [P02b-4 Step 4 — server-generation decision (2026-10-16)](#p02b-4-step-4--server-generation-decision-2026-10-16) — 1,038 lines + - [External proposal review and verified revision (2026-10-16)](#external-proposal-review-and-verified-revision-2026-10-16) — 54 lines + - [Maintainer acceptance and Step 4 adaptation (2026-10-16)](#maintainer-acceptance-and-step-4-adaptation-2026-10-16) — 73 lines + - [Step 4 required-startup qualification (2026-10-16)](#step-4-required-startup-qualification-2026-10-16) — 711 lines + - [Independent Step 4 foundation slice (2026-10-16)](#independent-step-4-foundation-slice-2026-10-16) — 58 lines + - [Independent foundation review corrections (2026-10-16)](#independent-foundation-review-corrections-2026-10-16) — 29 lines + - [ADR-0060 external-review revision (2026-10-16)](#adr-0060-external-review-revision-2026-10-16) — 72 lines + - [ADR-0060 acceptance and Step 4 continuation (2026-10-16)](#adr-0060-acceptance-and-step-4-continuation-2026-10-16) — 31 lines + - [Owned generation and maintenance foundation (2026-10-16)](#owned-generation-and-maintenance-foundation-2026-10-16) — 60 lines + - [Foundation review round 1 and verified corrections (2026-10-16)](#foundation-review-round-1-and-verified-corrections-2026-10-16) — 31 lines + - [Foundation review round 2 (2026-10-16)](#foundation-review-round-2-2026-10-16) — 14 lines + - [Pool replacement and framework cleanup ownership (2026-10-16)](#pool-replacement-and-framework-cleanup-ownership-2026-10-16) — 50 lines + - [Pool-cleanup slice review round 1 (2026-10-16)](#pool-cleanup-slice-review-round-1-2026-10-16) — 23 lines + - [Pool-cleanup slice review round 2 (2026-10-16)](#pool-cleanup-slice-review-round-2-2026-10-16) — 15 lines + - [Source-lifetime and facade continuation (2026-10-16)](#source-lifetime-and-facade-continuation-2026-10-16) — 21 lines + - [Core-phase and direct-facade qualification (2026-10-16)](#core-phase-and-direct-facade-qualification-2026-10-16) — 61 lines + - [Complete Step 4 implementation validation (2026-10-16)](#complete-step-4-implementation-validation-2026-10-16) — 21 lines + - [Full Step 4 review round 1 (2026-10-16)](#full-step-4-review-round-1-2026-10-16) — 42 lines + - [Full Step 4 round-1 correction validation (2026-10-16)](#full-step-4-round-1-correction-validation-2026-10-16) — 34 lines + - [Full Step 4 review round 2 (2026-10-16)](#full-step-4-review-round-2-2026-10-16) — 26 lines + - [Full Step 4 round-2 correction validation and closeout (2026-10-16)](#full-step-4-round-2-correction-validation-and-closeout-2026-10-16) — 53 lines + - [P02b-4 Step 5 — transactional owner and terminal audit (2026-10-16)](#p02b-4-step-5--transactional-owner-and-terminal-audit-2026-10-16) — 185 lines + - [P02b-4 Step 6 — tenant capacity reservations (2026-10-16)](#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) — 323 lines + - [Step 6 implementation and qualification (2026-10-17)](#step-6-implementation-and-qualification-2026-10-17) — 51 lines + - [Step 6 validation receipts (2026-10-17)](#step-6-validation-receipts-2026-10-17) — 71 lines + - [Step 6 full review round 1 (2026-10-17)](#step-6-full-review-round-1-2026-10-17) — 74 lines + - [Step 6 full review round 2 and local closeout (2026-10-17)](#step-6-full-review-round-2-and-local-closeout-2026-10-17) — 95 lines + - [P02b-4 external completed-failure proposal (2026-10-16)](#p02b-4-external-completed-failure-proposal-2026-10-16) — 55 lines + - [ADR-0061 revision after maintainer review (2026-10-17)](#adr-0061-revision-after-maintainer-review-2026-10-17) — 29 lines + - [ADR-0061 acceptance and Step 7 contract (2026-10-17)](#adr-0061-acceptance-and-step-7-contract-2026-10-17) — 32 lines + - [P02b-4 Step 7 — external stages and recovery (2026-10-17)](#p02b-4-step-7--external-stages-and-recovery-2026-10-17) — 1,084 lines + - [Native terminal and finalizer policy qualification (2026-10-17)](#native-terminal-and-finalizer-policy-qualification-2026-10-17) — 126 lines + - [Step 7 full review round 1 (2026-10-17)](#step-7-full-review-round-1-2026-10-17) — 90 lines + - [Step 7 full review round 2 (2026-10-17)](#step-7-full-review-round-2-2026-10-17) — 53 lines + - [P02b-4 Step 8 — durable recurrence and restricted fan-out (2026-10-18)](#p02b-4-step-8--durable-recurrence-and-restricted-fan-out-2026-10-18) — 658 lines + - [Step 8 full review round 1 (2026-10-18)](#step-8-full-review-round-1-2026-10-18) — 74 lines + - [Step 8 full review round 2 (2026-10-18)](#step-8-full-review-round-2-2026-10-18) — 80 lines + - [P02b-4 Step 9 — enforcement and packet closeout (2026-10-18)](#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) — 946 lines + - [Step 9 full review round 1 (2026-10-18)](#step-9-full-review-round-1-2026-10-18) — 76 lines + - [Step 9 full review round 2 (2026-10-18)](#step-9-full-review-round-2-2026-10-18) — 35 lines + - [P02b-4 local closeout (2026-10-18)](#p02b-4-local-closeout-2026-10-18) — 1,401 lines + - [Hosted CI qualification follow-up (2026-10-18)](#hosted-ci-qualification-follow-up-2026-10-18) — 1,316 lines + - [ADR-0062 revision and read-only baseline (2026-10-18)](#adr-0062-revision-and-read-only-baseline-2026-10-18) — 116 lines + - [ADR-0062 acceptance and CI implementation (2026-10-18)](#adr-0062-acceptance-and-ci-implementation-2026-10-18) — 1,132 lines + - [ADR-0063 review revision (2026-10-18)](#adr-0063-review-revision-2026-10-18) — 77 lines + - [ADR-0063 acceptance and implementation (2026-10-18)](#adr-0063-acceptance-and-implementation-2026-10-18) — 19 lines + - [ADR-0063 Step 1 — complete selector plan (2026-10-19)](#adr-0063-step-1--complete-selector-plan-2026-10-19) — 80 lines + - [ADR-0063 Step 2 — bounded shard execution (2026-10-19)](#adr-0063-step-2--bounded-shard-execution-2026-10-19) — 90 lines + - [ADR-0063 Step 3 — workflow and aggregate enforcement (2026-10-19)](#adr-0063-step-3--workflow-and-aggregate-enforcement-2026-10-19) — 490 lines + - [P02b-4 review corrections (2026-10-19)](#p02b-4-review-corrections-2026-10-19) — 374 lines + - [Additional verification and evidence reconciliation (2026-10-19)](#additional-verification-and-evidence-reconciliation-2026-10-19) — 169 lines + - [P02b-4 merge and closeout (2026-10-19)](#p02b-4-merge-and-closeout-2026-10-19) — 101 lines +- [P02b-5 — API authentication](#p02b-5--api-authentication) — 2,014 lines + - [P02b-5 decision package (2026-10-19)](#p02b-5-decision-package-2026-10-19) — 876 lines + - [Decision-pass review round 1 (2026-10-19)](#decision-pass-review-round-1-2026-10-19) — 22 lines + - [Decision-pass review round 2 and readiness (2026-10-19)](#decision-pass-review-round-2-and-readiness-2026-10-19) — 24 lines + - [Maintainer review follow-up (2026-10-19)](#maintainer-review-follow-up-2026-10-19) — 38 lines + - [Revised proposal review round 1 (2026-10-19)](#revised-proposal-review-round-1-2026-10-19) — 14 lines + - [Revised proposal review round 2 and readiness (2026-10-19)](#revised-proposal-review-round-2-and-readiness-2026-10-19) — 25 lines + - [Maintainer acceptance and implementation start (2026-10-19)](#maintainer-acceptance-and-implementation-start-2026-10-19) — 26 lines + - [P02b-5 Step 1 — token foundation (2026-10-19)](#p02b-5-step-1--token-foundation-2026-10-19) — 85 lines + - [Step 1 review round 1 (2026-10-19)](#step-1-review-round-1-2026-10-19) — 28 lines + - [Step 1 review round 2 and closeout (2026-10-19)](#step-1-review-round-2-and-closeout-2026-10-19) — 14 lines + - [P02b-5 Step 2 — real read-only application subject (2026-10-19)](#p02b-5-step-2--real-read-only-application-subject-2026-10-19) — 75 lines + - [P02b-5 Step 3 — attributed reconciliation and subject admission (2026-10-19)](#p02b-5-step-3--attributed-reconciliation-and-subject-admission-2026-10-19) — 92 lines + - [P02b-5 Step 4 — atomic HTTP activation and contracts (2026-10-19)](#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) — 93 lines + - [P02b-5 Step 5 — production enforcement and closeout (2026-10-19)](#p02b-5-step-5--production-enforcement-and-closeout-2026-10-19) — 145 lines + - [P02b-5 Step 5 — local implementation and review closeout (2026-10-19)](#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) — 45 lines + - [P02b-5 external review remediation (2026-10-20)](#p02b-5-external-review-remediation-2026-10-20) — 188 lines + - [P02b-5 second external review follow-up (2026-10-20)](#p02b-5-second-external-review-follow-up-2026-10-20) — 449 lines + - [ADR-0066 maintainer review revision (2026-10-20)](#adr-0066-maintainer-review-revision-2026-10-20) — 79 lines + - [ADR-0066 acceptance and implementation (2026-10-20)](#adr-0066-acceptance-and-implementation-2026-10-20) — 135 lines + - [P02b-5 systematic proof and document corrections (2026-10-20)](#p02b-5-systematic-proof-and-document-corrections-2026-10-20) — 399 lines + - [P02b-5 merge and closeout (2026-10-20)](#p02b-5-merge-and-closeout-2026-10-20) — 100 lines +- [P02b-6 — Realm and seed](#p02b-6--realm-and-seed) — 5,162 lines + - [P02b-6 decision package (2026-10-20)](#p02b-6-decision-package-2026-10-20) — 446 lines + - [P02b-6 Step 1 — executable realm and identity declaration (2026-10-21)](#p02b-6-step-1--executable-realm-and-identity-declaration-2026-10-21) — 97 lines + - [P02b-6 Step 2 — owned warm-realm reconciliation (2026-10-21)](#p02b-6-step-2--owned-warm-realm-reconciliation-2026-10-21) — 553 lines + - [Server-information response budget — proposal (2026-10-21)](#server-information-response-budget--proposal-2026-10-21) — 77 lines + - [Additional version-source investigation (2026-10-21)](#additional-version-source-investigation-2026-10-21) — 87 lines + - [Server-information allowance acceptance (2026-10-21)](#server-information-allowance-acceptance-2026-10-21) — 15 lines + - [Shared implementation and pre-review verification (2026-10-21)](#shared-implementation-and-pre-review-verification-2026-10-21) — 216 lines + - [Account-console self-service capability — proposal (2026-10-21)](#account-console-self-service-capability--proposal-2026-10-21) — 148 lines + - [P02b-6 Step 3 — shared seed/demo lifecycle (2026-10-21)](#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21) — 176 lines + - [P02b-6 Step 4 — real identity qualification and closeout (2026-10-21)](#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) — 3,888 lines + - [P02b-6 PR review corrections (2026-10-21)](#p02b-6-pr-review-corrections-2026-10-21) — 22 lines + - [P02b-6 systematic corrections and hosted qualification (2026-10-21)](#p02b-6-systematic-corrections-and-hosted-qualification-2026-10-21) — 473 lines + - [Further setup and proof corrections — 2026-10-21](#further-setup-and-proof-corrections--2026-10-21) — 75 lines + - [Dedicated issuance-carrier review corrections — 2026-10-21](#dedicated-issuance-carrier-review-corrections--2026-10-21) — 76 lines + - [ADR-0067 acceptance and carrier reconciliation (2026-10-21)](#adr-0067-acceptance-and-carrier-reconciliation-2026-10-21) — 101 lines + - [P02b-6 additional verification and correction pass (2026-10-22)](#p02b-6-additional-verification-and-correction-pass-2026-10-22) — 399 lines + - [ADR-0068 acceptance and implementation (2026-10-22)](#adr-0068-acceptance-and-implementation-2026-10-22) — 40 lines + - [ADR-0068 Step 1 — qualified stock assignment implementation (2026-10-22)](#adr-0068-step-1--qualified-stock-assignment-implementation-2026-10-22) — 120 lines + - [ADR-0068 Step 2 — owned visibility preparation (2026-10-22)](#adr-0068-step-2--owned-visibility-preparation-2026-10-22) — 233 lines + - [ADR-0068 Step 3 — complete historical-path qualification (2026-10-22)](#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) — 1,127 lines + - [P02b-6 closed-PR CI rerun correction (2026-10-22)](#p02b-6-closed-pr-ci-rerun-correction-2026-10-22) — 130 lines + - [P02b-6 native constructor-stop failure attribution (2026-10-22)](#p02b-6-native-constructor-stop-failure-attribution-2026-10-22) — 123 lines + - [First native-wait diagnostic review (2026-10-22)](#first-native-wait-diagnostic-review-2026-10-22) — 24 lines + - [Second native-wait diagnostic review (2026-10-22)](#second-native-wait-diagnostic-review-2026-10-22) — 15 lines + - [Diagnostic-source hosted A qualification (2026-10-22)](#diagnostic-source-hosted-a-qualification-2026-10-22) — 17 lines + - [P02b-6 fixture hint waits for actual prior cleanup (2026-10-22)](#p02b-6-fixture-hint-waits-for-actual-prior-cleanup-2026-10-22) — 91 lines + - [First fixture-handoff review and cancellation guard (2026-10-22)](#first-fixture-handoff-review-and-cancellation-guard-2026-10-22) — 24 lines + - [Second fixture-handoff review (2026-10-22)](#second-fixture-handoff-review-2026-10-22) — 18 lines + - [P02b-6 hosted browser dependency acquisition (2026-10-22)](#p02b-6-hosted-browser-dependency-acquisition-2026-10-22) — 85 lines + - [First browser-acquisition correction review (2026-10-22)](#first-browser-acquisition-correction-review-2026-10-22) — 19 lines + - [Second browser-acquisition correction review (2026-10-22)](#second-browser-acquisition-correction-review-2026-10-22) — 17 lines + - [P02b-6 public-demo outer budget allocation (2026-10-22)](#p02b-6-public-demo-outer-budget-allocation-2026-10-22) — 82 lines + - [P02b-6 OpenAPI fixture maintenance completion (2026-10-22)](#p02b-6-openapi-fixture-maintenance-completion-2026-10-22) — 66 lines + - [P02b-6 aggregate gate-refusal diagnostics (2026-10-22)](#p02b-6-aggregate-gate-refusal-diagnostics-2026-10-22) — 69 lines + - [P02b-6 Outbox startup ownership and isolated diagnostics (2026-10-22)](#p02b-6-outbox-startup-ownership-and-isolated-diagnostics-2026-10-22) — 59 lines + - [P02b-6 aggregate producer-state refusal attribution (2026-10-22)](#p02b-6-aggregate-producer-state-refusal-attribution-2026-10-22) — 73 lines + - [P02b-6 pending aggregate metadata acquisition (2026-10-22)](#p02b-6-pending-aggregate-metadata-acquisition-2026-10-22) — 110 lines + - [P02b-6 hosted browser dependency removal (2026-10-23)](#p02b-6-hosted-browser-dependency-removal-2026-10-23) — 45 lines +- [Status archive](#status-archive) — 112 lines + +<!-- END GENERATED INDEX --> + +## P02b-0 — Phase entry + +### P02b-0 entry verification (2026-10-12) + +**Complete.** This packet verifies entry premises and corrects current-state +claims. It writes no runtime code, drafts no ADR, accepts no later packet's gate +and introduces no glossary definition ahead of its owning decision pass. + +#### Baseline and inherited enforcement + +The audit used LearnStack `development` at +`3e86041dc32009ae6120c8cbb1533fd5d1325465`, tree +`7aac9df1ed19f0826b042fbd1a303dc92c9ab11a`. That commit reconciles the merged +P02d-7 source with PR #28's squash on `main`; the +[P7 merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) +owns the merge/tree comparison and the completed phase exit. + +The post-merge [CI run 38129121225](https://github.com/HodeTech/LearnStack/actions/runs/38129121225) +completed successfully on `main` at +`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`. A fresh branch-protection API read +on 2026-10-12 confirmed strict up-to-date protection and all seven required +contexts: `backend (build + unit + arch + contract)`, `frontend (typecheck + lint ++ build + test)`, `secret scan (leakwatch)`, `meta (compose + commit hygiene + +link audit)`, `backend integration (Testcontainers)`, `openapi diff`, and +`public demo + lighthouse`. This receipt does not claim a new local full-stack +run or change those settings. + +The Hub checkout was inspected read-only at +`6adf93638e76114eda9c18a5095d0fe3c0fd43b1`; fetched `origin/main` was +`310f718e5f2bad0dfb51e2c307c1ec361dab5952`. The checkout is an ancestor of that +main and their trees are identical: +`c5c380cfee42c6a32923d26d604ada7da2d5dc45`. Its roadmap still freezes P02c-2 +onward pending the documented billing/plan-gate demand and ADR-0034 invariants. +Its P02c-3 waits on LearnStack's durable event path, not the BFF session. +This audit neither opens that track nor changes its contract surface. + +The retained public baseline is native HTTPS, signed ingress, one live +middleware bootstrap and request-local immutable admission. Anonymous public +reads use the host boundary, physical read-only transactions, query filters and +RLS. They do not forward cookies or bearer credentials. The early limiter still +coordinates 60/min canonical visitors and 600/min physical-peer acquisitions/ +allocations; known visitor refusals do not debit that peer budget. P02b-5 must +decide authenticated accounting without weakening this pre-classification bound. + +#### Gate-premise audit + +All twenty register rows were checked against their cited records and the +current implementation. **Verified** below means the premise is confirmed; +it does not mean the proposed answer is Accepted. G15 remains the register's +already-answered replay boundary. Every other row retains its decision vehicle +and first dependent packet above. + +| Gate | Verified current premise and disposition | First decision consumer | +|---|---|---| +| G1 | No `IInboxGuard` declaration, inbox table or durable subscription failure state exists. ADR-0006/0010 still require a per-module, consumer-called inbox. Shared transport ownership remains a proposal requiring the registered record/amendments. | P02b-2 record; P02b-3 DDL | +| G2 | `OutboxFlushBehavior` only calls `next()`; no `IOutbox` exists. Immediate enqueue versus a buffer/flush policy remains undecided, including paths outside MediatR. | P02b-1 | +| G3 | The envelope requires a partition key and the in-process serializer orders invocation per key. The table has no durable sequence or retry ordering guarantee; key derivation and the dispatcher bound remain separate decisions. | P02b-1 derivation; P02b-2 bound | +| G4 | The table has `attempts`, `available_after` and `processed_at`, but no explicit terminal marker or lease columns. Five published retry delays do not themselves settle attempt counting or terminal state. | P02b-2 | +| G5 | Canonical DDL has a surrogate `id` but no `event_id`; ADR-0032 lists both. No durable type resolver or enqueue implementation resolves that mismatch yet. | P02b-1 identities; P02b-2 resolution | +| G6 | The bus restores the accessor and creates handler scopes without opening a transaction or audit frame. Pipeline audit ownership cannot simply be assumed for delivery/domain-event owners. No aggregate currently raises a domain event. | P02b-1; P02b-3 | +| G7 | No producer/subscriber terminal writer exists. The MUST durability contract, off-path caller restriction and transaction atomicity still apply; a multi-transaction alternative needs the vehicle the register names. | P02b-2; P02b-3 | +| G8 | The outbox-admin role and its bounded grants exist; a running dispatcher does not. No Accepted dispatcher-specific audit exemption has been added by this audit. | P02b-2 | +| G9 | No job runtime, package pin, storage, activator or enqueue guard is shipped. The closed four-role and tenant-context-writer contracts remain constraints, not implicit permission for a new runtime. | P02b-4, after P02b-3 | +| G10 | The API has no JwtBearer wiring. Dev users carry slug-valued tenant attributes without explicit protocol mappers; the scalar/array and actor-UUID choices remain open. | P02b-5 | +| G11 | The resolver's claim insertion point is reserved; membership reads still deny everyone. Tenant-only authentication on an organization host and a claimless valid token need explicit outcomes before activation. | P02b-5 | +| G12 | Delivered HTTPS/host/hop/bootstrap behavior is retained. Dev redirects still target localhost HTTP, and `make seed` polls realm readiness without reconciling mappers or warm users. | P02b-5 client; P02b-6 realm | +| G13 | No Auth.js session/helper exists. Access-token lifetimes in the realm and target documents differ; storage, refresh, CSRF and logout remain decisions before their first writes. | P02b-6 TTL; P02b-7 session | +| G14 | `AuthorizationBehavior` remains pass-through. Current HTTP product operations are public reads; anonymous coordinated admission already runs before classification. A protected read census and validated-subject quota do not yet exist. | P02b-5 | +| G15 | Replay remains an internal dispatcher operation for this phase; the operator URL/permission belongs to Phase 03. No recovery endpoint is shipped or authorized here. | Answered; P02b-3 implements | +| G16 | Only `LS0001` is shipped. `LS0002` needs scope, token-source parity, severity/escalation and its release/catalogue entries; it is not a current build-breaking guard. | P02b-8 | +| G17 | Metric carriers disagree on tenant-label spelling and cardinality. Dispatcher heartbeat and oldest-eligible-row age have no emitter yet. Resolve the label set before the first series ships. | P02b-2 | +| G18 | No shipped integration payload/job argument commits this phase to PII. `last_error` is unbounded text today; the future outbox, inbox, subscriber-failure and job stores need the registered erasure inventory. | P02b-1 payload; P02b-2 failure; P02b-8 erasure | +| G19 | No production integration event is published/consumed. Tenancy books three future topics while Audit consumes none. Typed settings are uncached, so a settings-invalidation consumer needs a real effect rather than an artificial cache. Provisioning also has an unresolved ambient context despite its transaction announcement. | P02b-1 | +| G20 | Only public product reads are routed. Existing non-public 404/401 and authenticated assertion-code questions remain unresolved; authentication must not silently choose framework defaults over the matrix. | P02b-5 | + +Implementation evidence was read in the pipeline's `OutboxFlushBehavior`, +`TransactionBehavior` and `AuditLogBehavior`; the platform infrastructure +migration; `InProcessEventBus`, `IntegrationEventEnvelope` and +`EventTenantContext`; API startup, resolver and rate limiter; the Keycloak realm +exports and `scripts/seed.sh`; the uncached `TenantSettingsAccessor`; and the +web middleware, admission/resource loaders and configured caller. Existing +architecture and integration tests were inspected to distinguish accessor +restoration from database announcement and durable delivery. + +#### Reconciliation and next packet + +Current-state corrections in this packet cover the separate seeder executable, +the already-delivered public browser proof, absent API authentication, the +organization-claim choice still owned by G11, logical session-version wording, +future auth examples, absent delivery transactions/audit frames, planned LS0002 +severity and the existing required-check/zero-skip enforcement. Architecture 13 +now labels its identity/session diagrams as targets; Architecture 15 separates +the shipped transport from its future inbox/transaction obligations. Accepted +ADR bodies and historical Phase 02d delivery records remain unchanged. + +Other target sketches that depend on an open gate remain target sketches. +Their packet-owned reconciliation is explicit in the register and deliverables: +P02b-1 updates producer/domain-event/payload carriers and the sample module +specs; P02b-2/3 update delivery, inbox, roles/grants, failure and metric carriers; +P02b-4 owns job storage/runtime carriers; P02b-5–7 own authentication, realm, +session and auth-skill carriers; P02b-8 owns analyzer and erasure closeout. +The Hub's per-module inbox reference remains consistent with the current +Accepted baseline; a different G1 decision must reconcile the cross-repo +reference without thawing the Hub roadmap. + +**Next: P02b-1 decision pass.** Prepare G2, G3's derivation, G5's stored +identities, G6, G18's payload rule and G19 as one reviewable package, including +the domain-event mutation/dispatch boundary and every owning frame's audit +duties. Define the first real cross-module effect before choosing its event. +Any required ADR/amendment must be drafted and approved before implementation. +Only then register its tests, split the implementation into reviewable steps +and begin producer code. P02b-0 requires no new product or architecture choice +from the maintainer. + +#### Validation + +Local Release architecture tests: **203 passed, zero failed, zero skipped**. +ADR lifecycle/disclosure tests: **7 passed**. The changed-document sweep checked +590 relative links and 164 Markdown fragments, with no broken target. Added +prose satisfies the 88-column rule; `git diff --check` is clean. The residual +scan found only CLAUDE.md's unchanged prohibition on local analysis references, +not a new dependency on a private document. No local full integration, browser +or Lighthouse rerun was needed for this documentation-only packet; the exact +post-merge CI receipt above owns that inherited evidence. + +<a id="p02b-1-proposed-decision-package-2026-10-12"></a> + +## P02b-1 — Producer + +### P02b-1 decision package (2026-10-12) + +**Accepted — 2026-10-12, @cemil.** The maintainer approves the revised package +and [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md). +This is the producer decision record. The +[Step 1 record](#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) tracks +the first runtime delivery; acceptance alone closes no implementation step. The +[Step 4 record](#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns +final validation, reviews and the packet closeout. +Only the gate parts listed below are Accepted. ADR-0057 supplies the authority +for the coupled producer choices. It explicitly +replaces ADR-0032's step-7 flush/separate event-ID column and ADR-0040's +absorbable-failure rule only for successfully produced work. Other Accepted +rules and historical delivery records stay intact. + +#### Document and code audit + +The decision pass re-read the inherited event, transaction and audit decisions +(ADR-0006/0010/0032/0033/0038/0040/0042/0044), the producer/consumer architecture, +Database/Observability/Audit/Infrastructure standards, the three module specs +and their matrices, the production pipeline and persistence seams, the existing +transport and both composition roots, and the actual provisioning/Seeder paths. +The [entry audit](#p02b-0-entry-verification-2026-10-12) remains the authority for +P02b-0 evidence; it is not rewritten as a P02b-1 delivery claim. + +Two independent read-only audits examined producer/audit boundaries +(GPT-6-astra, xhigh) and real subscriber usefulness/seed compatibility +(GPT-6.1-sol, xhigh). These pre-implementation code facts shape the decision: + +- The outbox DDL already exists; it has `id`, not a separate `event_id`. + `IOutbox` is absent and step 7 is a pass-through. A shared SaveChanges is + neither necessary nor sufficient; the one ambient transaction is the boundary. +- Provisioning deliberately leaves `ITenantContext` unresolved and announces + its new tenant on the transaction. The Seeder has neither a guaranteed + correlation value nor an Activity listener. An HTTP-only enqueue check fails + its first real producer. +- Joined UoW frames are not savepoints. Discarding an inner event queue cannot + undo its saved state or already inserted outbox row. +- Audit entry/reconciliation is currently specific to `AuditLogBehavior`. + A direct delivery needs common ownership rather than pretending a nested + request owns a transaction it only joined. +- Typed settings are uncached; definition reads probe fresh generations. Neither + needs an invented invalidation consumer. Audit already durably records source + changes, so an asynchronous mirror adds no honest useful effect. +- The existing generic defaults are real data with a declared product purpose. + Their automatic installation changes orchestration ownership; it is not a + currently implemented consumer. Current seed verification pins their IDs, + so P02b-3 needs an explicit handoff before enabling delivery races. + +#### Accepted gate answers and implementation boundary + +The ADR owns exact semantics and bounds; this table owns gate timing. Maintainer +approval accepts this package and ADR-0057 together. The decision-only acceptance +commit and Registered catalogue obligations precede runtime code. Acceptance is +not an implementation or passing-test claim. + +| Gate / part | Accepted answer | Acceptance carrier / remaining owner | +|---|---|---| +| G2 | Immediate ambient INSERT; step 7 checks enrollment, while the owner drains domain events before MUST audit/commit | ADR-0057 bounded supersession of ADR-0032 Sub-decision 2; dated supersession disclosure and architecture producer-pattern reconciliation | +| G3 derivation | Explicit aggregate-ID or declared tenant-wide source; canonical key and falsifiable structural/behavioral proof | ADR-0057 and existing `Integration_Event_Declares_PartitionKey`; publish ordering remains P02b-2 | +| G5 stored identities | Assembly-qualified type; `id = EventId`, no extra column; runtime-type JSON with existing frozen options | ADR-0057 bounded supersession of ADR-0032 Sub-decision 12 and the Phase 02b deliverables table in Implementation Notes; dated supersession disclosure and Database Standards alignment; resolver failure policies remain P02b-2 | +| G6 producer/common owner | One collector/drain and reusable audit entry; outbox-only domain reactions; absorbed fail-after-produced-work poisons the unit, including descendant receipts | ADR-0057 bounded ADR-0040 nested-failure supersession; separate additive UoW snapshot-reader amendment and ADR-0044/0033 clarifications; production delivery/inbox atomicity remains P02b-3 after G1 | +| G18 payload | Identifier-only additional fields, inclusive 256 KiB canonical UTF-8 application cap, SQL NULL JSON metadata, no copied personal data or serializer escape | ADR-0057 new producer policy with dated ADR-0038 cross-reference; no outbox-size DDL CHECK claimed; sanitized errors P02b-2, erasure inventory P02b-8 | +| G19 | Completed tenant provisioning produces `TenantCreatedIntegrationEventV1`; two Customization subscribers initialize `card@1` and `plain@1` without overwriting | This package and ADR-0057; module-spec reconciliation at acceptance, publisher P02b-1; G1 must settle independent subscription identities before P02b-3 subscriptions and Seeder handoff | + +The additional nested-refusal protection is deliberate, not a correction to an +old statement: ADR-0040's prior rule was valid when accepted. Its exception and +ordinary event-free refusal semantics survive. No independent scope may bypass +the producer/audit coordinator by opening a raw transaction and calling outbox. + +The acceptance carriers disclose ADR-0057's exact bounded supersessions and +separate additive/clarifying amendments. Current producer guidance in +architecture 15, standards 02/05/10/18/20, module specs and event/review skills +uses owner-only completion and outbox-only domain reactions. The five new +catalogue obligations are Registered, with Implemented counts unchanged. +Consumer target guidance remains under its existing decisions until P02b-2's +G1 pass. Typed settings are uncached and definition reads probe fresh +generations; there is no useful settings-invalidation or Audit-mirror sample. +A later settings cache needs its own measured need and freshness decision. + +#### Four authorized implementation steps + +All work stays on `development`. Each step includes implementation tests and +an explicit commit, then **two independent review rounds with fresh agents**. +Each round covers security/isolation, correctness/lifecycle, architecture/audit, +test falsifiability and carrier accuracy. Use GPT-6-astra xhigh for transaction/ +audit risks and GPT-6.1-sol xhigh for independent structural/test/doc review; +adjust scope rather than weakening critical review. Verify every finding before +fixing and commit confirmed fixes; close both rounds before the next step. + +| Step | Deliverable | Required evidence before its review closeout | +|---|---|---| +| 1 — Shared execution lifecycle | Named `GetTenantContextAnnouncement` reader and immutable transaction-generation snapshot, producer invocation receipts, common audit entry/owner coordinator and guaranteed no-listener trace context; request pipeline retains existing outcomes | Owner/joiner and descendant receipts, event-free absorbed control, no context/setter expansion, same-scope cleanup, existing audit/public read-only regressions, controlled direct non-MediatR owner | +| 2 — Immediate outbox | `IOutbox`, ambient parameterized implementation, identity/metadata/payload admission and step-7 invariant guard; both compositions wired | Real `learnstack_app` INSERT/rollback and cross-tenant refusal, exact persisted envelope/runtime round-trip and SQL NULL JSON metadata, inclusive/multibyte byte-bound proofs, duplicate/oversized/malformed/stale/read-only refusal, no extra connection or publish, MUST-audit failure atomicity | +| 3 — Domain completion and real publisher | Successful-save collection, owner-only FIFO drain, outbox-only translation and completed-provisioning publisher used by API and Seeder | Multi-save/detach/delete, save failure/cancellation, absorbed direct/descendant producer refusal, bounded drain, no replay after rollback/scope reuse, exact one event per successful provision and zero on rollback; response version remains accurate | +| 4 — Enforcement and closeout | Production-subject architecture sweeps with planted controls, end-to-end producer regression, all affected docs/skills/catalogue states reconciled | Release/format and applicable complete backend suites with zero skips; exact test evidence, links/anchors and immutable ADR history; inspect required CI on the eventual PR without claiming unrun results | + +Use the implementation workflow's `add-integration-event`, +`add-mediatr-handler`, `add-integration-test` and `add-architecture-test` skills +for the relevant surfaces, plus `run-tests-locally`, `standards-check`, +`code-review` and `commit-and-pr`. No producer schema change is authorized; +unexpected schema needs reopen planning rather than borrowing P02b-2's lease work. + +No step is complete with review findings or required evidence pending. Partial +step commits are review checkpoints, not packet delivery claims. The final PR +remains for maintainer review; a local pass does not imply merge. + +#### Named handoff to P02b-3 + +P02b-1 is authorized to supply the production publisher and pending rows. +Steps 1–3 implement producer runtime; dispatcher claims and delivery belong to +P02b-2/P02b-3. P02b-3 must deliver both named defaults in +separate one-root subscriber transactions after G1 settles distinct subscription +identities and delivery scope, preserve any authored/lifecycle decision +(including deletion), and prove redelivery and sibling failure recovery. +It also switches built-in seed verification to owner-resolved key/version +identity while preserving warm IDs and exact authored curriculum IDs. Fresh +seed/dispatcher races, repeated-run neutrality, affected audit fixtures and the +seed inventory must be verified together before that packet closes. That packet +also updates `BuiltInCustomizations.cs`'s creator/Seeder/Hub installation remarks +to the delivered subscriber ownership; no consumer is claimed delivered now. + +G1/G3-ordering/G4/G5-resolution/G7/G8/G17 and G18's remaining parts remain open +for their named packets. This approval neither decides inbox ownership nor adds +jobs, authentication, Hub integration, Dapr or another worker process. + +#### Decision-draft review and validation + +Two fresh independent draft reviewers (GPT-6-astra xhigh for runtime/transaction +semantics; GPT-6.1-sol xhigh for corpus/gates/seed scope) approved the proposal +for maintainer review. Neither found a blocking issue. The corpus review's +carrier reminder was verified and incorporated above: Backend Standards 02 and +this phase's domain-event sketch must be reconciled on approval. These are +decision-draft reviews, not the two review rounds each implementation step owes. + +**External-review revision — 2026-10-12.** The maintainer's review is not an +approval. ADR-0057 now classifies each normative supersession, additive seam +amendment and clarification separately; ADR-0041 correction mechanisms do not +authorize the changed decisions. It names the UoW snapshot getter and its +generation/cleanup obligations, closes the JSON metadata channel with SQL NULL, +and identifies the UTF-8 cap as application admission rather than a DDL CHECK. +G1 must settle independent subscription identities before consumer code; +P02b-3 explicitly owns the `BuiltInCustomizations.cs` remarks handoff. The event +version suffix already follows the authoring skill, so no event rename is +needed; its inconsistent input-order example is a named acceptance carrier. +Source-linked drivers, reopening criteria, deferred ownership and the missing +ADR references are also explicit. All P02b-1 gates remain open pending approval. + +Two fresh independent revision reviewers (GPT-6-astra xhigh for governance and +the UoW seam; GPT-6.1-sol xhigh for payload, G1/G19 and carriers) approve the +revised draft for maintainer review. The governance review caught an incorrect +provisioning-amendment attribution; the reference now points to the existing +`IUnitOfWork` provisioning seam, and the fix was rechecked. Neither reviewer +reports a remaining actionable finding. These reviews do not accept the ADR or +count as implementation-step reviews. + +The seven ADR lifecycle-parser tests pass. A local file-and-heading check resolves +all relative links/anchors in the changed draft carriers; it is not a new CI +anchor gate. Accepted ADR files and the P02b-0 entry record remain unchanged. +No backend runtime suite was needed or claimed for this documentation-only +preparation. Maintainer approval remains pending. + +#### Maintainer acceptance — 2026-10-12 + +The maintainer explicitly approved the externally revised ADR-0057 and this +package after the draft reviews recorded above. The pending-approval statements +in that dated draft history describe the earlier review state. This acceptance +closes only the six gate parts in the accepted table. Five canonical proofs are +Registered; no runtime implementation, step review or runtime test is claimed +by this decision record. + +### P02b-1 Step 1 — Shared execution lifecycle (2026-10-12) + +**Step 1 complete; both independent review rounds passed.** Work is +on `development`, following the Accepted four-step package. This is not P02b-1 +completion. No immediate enqueue, successful-save event collector, publisher or +production delivery is claimed by this step. + +- `IUnitOfWork.GetTenantContextAnnouncement` returns an immutable normalized + tenant/organization snapshot with its physical transaction generation. The + PostgreSQL unit captures the values actually sent to SQL, clears authority + before a fresh attempt and on every terminal path, and refuses absent/foreign + transactions. Joins reuse the owner's announcement without retargeting it. +- Scoped `ProducerExecution` records sticky successful-production receipts on + an invocation and every ancestor, separately from pending event counts. The + common transaction coordinator poisons a refusing invocation before resolving + its frame when it carries such a receipt. Ordinary event-free absorbed refusals + retain their previous behavior. Production needs a live writable announcement + and an enrolled owner. A W3C Activity exists even without telemetry listeners. +- `AuditLogBehavior` and `TransactionBehavior` are thin adapters over common + coordinators registered by the pipeline helper in both API and Seeder. Audit + classification precedes deferred direct-handler construction. Capture-owned + audit frames determine outer reconciliation; the UoW owner writes MUST rows + and reports actual commit durability. An independent DI scope has independent + ownership even inside another audit execution's async flow. +- Architecture/audit/security guidance and the glossary describe the common + ownership seams. The closed context-writer set, eight logical announcement + paths, pipeline order and public read-only mode are unchanged. + +**Verification before the implementation commit.** A fresh `CI=true` Release +build succeeds with zero warnings/errors. The focused pipeline unit run passes +83 cases; the complete unit rerun passes 1,713. The focused integration run +passes 125, including all UnitOfWork, +ambient UoW, tenant-context guard, audit pipeline/workflow/capture, public +read-only, provisioning, direct-producer and cross-cutting HTTP cases selected +for this step. Both runs report zero failures and zero skips. The integration +proofs use the application role; privileged connections only prepare fixtures. +The new direct-producer class contributes 13 cases. Its receipts are deliberately +recorded after positively observed writes; automatic INSERT/save-promotion +receipt sites are Step 2/3 obligations, not evidence supplied here. + +The snapshot matrix adds 21 cases, including successful SQL values versus a +mutated source context, unresolved provisioning, join/foreign/stale transaction +checks, pooled same-session reuse, failed/cancelled announcement/setup and every +terminal path. The final complete architecture run passes 203 cases with zero +failures/skips. The local carrier check resolves 719 relative links and 153 +Markdown fragments with no broken target; added prose width and +`git diff --check` are clean. +Required CI and final packet counts are not claimed by this local checkpoint. + +#### Step 1 review round 1 + +Two fresh independent reviewers examined `b157650..cbab31a`: GPT-6-astra xhigh +for lifecycle/security/audit and GPT-6.1-sol xhigh for proof/architecture/carriers. +Two findings were confirmed: public `BeginInvocation(true)` could assert raw +transaction ownership, and the receipt test did not distinguish all ancestors +from only the immediate parent. An isolated assembly mutant implementing that +weaker propagation still passed all original 13 direct-producer cases. + +Enrollment is now internal to core Application; only the common coordinator +opens frames. Raw announced owners and orphan joiners have explicit refusal +controls. A depth-four invocation case exercises receipt propagation past an +intervening successful ancestor. The UoW XML comment names the common coordinator +and adapter correctly. The reviewers' stale-ancestry observation was reproduced: +an old owner could lend ownership to a later transaction's joiner. The new test +failed on that behavior; inheritance now requires the parent's live announcement +generation to match. The same test passes only after that change, with outer +audit cleanup included. The fresh Release build has zero warnings/errors; +the expanded focused integration run passes 129 cases with zero failures/skips, +including all 17 direct-producer cases. The same isolated weak-propagation mutant +now fails exactly the depth-two-descendant case (1 failed, 16 passed); restoring +the unmodified assembly passes all 17. The complete architecture rerun passes +203 cases with zero failures/skips. The second independent review round remains +pending at this checkpoint. + +#### Step 1 review round 2 and closeout + +Two new independent reviewers examined `b157650..ab2c37d`: GPT-6-astra xhigh +for lifecycle/security/audit and GPT-6.1-sol xhigh for proof/architecture/carriers. +Both approve Step 1 with no Blocker/Major findings. Their independent reruns +pass 59 audit/transaction unit cases, 73 producer/UoW integration cases and +25 persistence architecture cases, with zero failures/skips. These are selected +subsets of the runs above, not additional distinct test totals. + +The confirmed minor carrier findings are corrected in this closeout: the +catalogue names coordinator delegation and the outer audit coordinator's clear +ownership; the Security derivation header includes ADR-0057. Canonical rule names, +statuses and counts remain unchanged. The full producer contracts still await +Steps 2–4; this closeout does not claim automatic production receipts, domain +collection or completed P02b-1 delivery. + +### P02b-1 Step 2 — Immediate outbox production (2026-10-12) + +**Implemented; both independent review rounds complete.** +`IOutbox.EnqueueAsync` persists immediately through the admitted producer's +existing connection and transaction. API and Seeder register `PostgresOutbox`; +no transport, extra connection, commit or schema migration is added. + +- Admission checks the unit's identity, live announcement/generation, writable + non-poisoned frame and event tenant before serialization and again immediately + before INSERT. Explicit aggregate or tenant-wide partition declarations must + match the actual canonical GUID key. Organization comes from announced SQL + authority, while the invocation captures the causal actor and full W3C span. +- The row retains producer `EventId`, concrete assembly-qualified type and all + admitted identifier payload properties. Serializer escape shapes are refused; + the complete canonical UTF-8 payload has an inclusive 262,144-byte bound. + JSON metadata is SQL NULL. A duplicate INSERT is an error. +- Only a successful INSERT records a sticky receipt in the invocation and all + ancestors. Step 7 checks live enrollment before and after dispatch; it does + not flush a buffer or dispatch domain events. Event-free unresolved and + public read-only work retain their admission semantics. + +**Verification before the implementation commit.** The `CI=true` Release build +passes with zero warnings/errors. All 1,757 unit and 203 architecture cases pass +with zero failures/skips. The new real-PostgreSQL outbox class passes all 29 +cases, including immediate visibility, atomic commit/rollback with business and +MUST audit rows, provisioning, stale transaction-object reuse, distinct-unit +refusal and exact canonical UTF-8 boundary values. Initial failures exposed two +fixture assumptions (telemetry subscription and SystemActor identity); both +fixtures were corrected before the passing run. No runtime defect is hidden by +those corrections. Domain-save collection and its first publisher are Step 3; +no dispatch or consumer delivery is claimed here. +The separate existing-flow regression passes 166 integration cases, including +the convergent seeder, audit, provisioning, UoW and public read-only paths, with +zero failures/skips. The carrier audit resolves 1,158 relative links and 216 +Markdown fragments with no broken target; added prose width, formatting and +`git diff --check` are clean. Required CI is not claimed by this local checkpoint. + +#### Step 2 review round 1 + +Two fresh independent reviewers examined `7541b73..db882e0`: GPT-6-astra xhigh +for transaction/security/envelope correctness and GPT-6.1-sol xhigh for +proof/architecture/carrier integrity. Both approve with no Blocker/Major +findings. The confirmed minor finding was an undated inherited-absence paragraph +still describing `IOutbox` and step 7 as absent. It now distinguishes the P02b-0 +entry baseline from Step 2 delivery; the frozen entry audit is unchanged. + +The lifecycle reviewer independently passes 79 focused unit and 29 real outbox +integration cases, with zero failures/skips. These overlap the implementation +runs above. The corpus reviewer independently resolves 723 relative links and +165 fragments in changed carriers, with no unresolved target. The second fresh +review round remains pending at this checkpoint. + +#### Step 2 review round 2 and closeout + +Two new independent reviewers examined `7541b73..37d95bd`: GPT-6-astra xhigh +for runtime/security and GPT-6.1-sol xhigh for proof/architecture/carriers. +Both approve with no Blocker/Major findings. Each independently passes 61 +focused unit, 203 architecture and 29 outbox integration cases, with zero +failures/skips. These overlap earlier runs and are not additive suite totals. + +The confirmed minor test gap was transport silence: an unsubscribed event would +not expose an accidental publish. A real API-root test now resolves a counting +transport, positively observes the pending and committed row, and proves zero +publishes through enqueue and owner completion. Calling that same resolved +transport afterwards proves the counter works. The fresh Release build has zero +warnings/errors; all 30 outbox cases pass with zero failures/skips. +Step 4 still owns the transitive producer/helper fence against publication, +extra connections and commit ownership, alongside the complete production +censuses. Step 3's save collector, domain causation and publisher remain pending. + +### P02b-1 Step 3 — Domain completion and provisioning publisher (2026-10-12) + +**Implemented; both independent review rounds complete.** + +- A shared SaveChanges interceptor snapshots only changed sources of its saving + context, then promotes facts after nonzero successful persistence. Failed, + canceled, suppressed and zero-row saves promote nothing. Separate source + retention clears uncollected or detached facts; it cannot promote them on an + unrelated save. Repeat saves do not duplicate successfully promoted facts. +- The transaction owner alone drains the FIFO queue before producer invariants, + MUST audit and commit. Saved facts retain their saving invocation, generation, + W3C span and causal human through child disposal. Translation mints a new + integration identity and records the domain identity as causation. Successful + promotion marks every ancestor; a produced-work refusal poisons before its + frame resolves. Total production is bounded at 256 domain events. +- API and Seeder install the same collector/interceptor. Owner termination and + scope disposal clear source lists, staged/queued facts and promotion state; + later successful transactions in the same DI scope cannot replay facts. +- The tenant's initial default-organization assignment raises + `TenantCreatedDomainEvent`. The final successful provisioning save qualifies + it for outbox-only translation into `TenantCreatedIntegrationEventV1`. + One pending row commits with tenant, default organization/back-reference and + both existing MUST audit rows. No dispatch or default subscriber is delivered; + existing seed orchestration remains unchanged until P02b-3's named handoff. + +**Verification before the implementation commit.** The fresh `CI=true` Release +build passes with zero warnings/errors; all 1,764 unit and 203 architecture cases +pass with zero failures/skips. The final focused producer/provisioning integration +run passes 68 cases with zero failures/skips, including both real API/Seeder +roots, exact metadata and successful/failed MUST provisioning. A separate +existing-flow run passes 152 integration cases with zero failures/skips, +covering audit, UoW, public read-only and convergent seed behavior. The focused +post-format unit rerun passes 28 provisioning/domain cases; it overlaps the full +unit total above. + +The initial focused integration run exposed two fixture defects: EF refused a +duplicate alternate key before SQL, and two fault cases tried to reuse an +irreversibly poisoned UoW. The corrected cases reach the real database uniqueness +failure and verify poisoned-scope refusal; a separate successful-owner case +proves later-generation reuse without replay. The full focused rerun above is +green. These corrections change no runtime policy and conceal no failing case. +Step 4 still owns complete structural enforcement and catalogue promotion; +required CI and packet completion are not claimed at this checkpoint. + +#### Step 3 independent reviews + +Round 1 reviewed `937e36a..d6fbd85` with separate GPT-6-astra xhigh +runtime/transaction and GPT-6.1-sol xhigh proof/corpus reviewers. Both approved +without a verified actionable finding. The proof reviewer independently reran +28 domain/provisioning integration and 28 focused unit cases with zero +failures/skips. Round 2 used two new agents with the same separate lenses; +both approved, and its proof reviewer independently repeated those same +28 integration and 28 unit cases with zero failures/skips. These focused repeats +overlap the implementation evidence; they are not added to its totals. + +The reviews checked real SQL/save qualification, retained child metadata, +ancestor receipts, FIFO/count bounds, owner/audit atomicity, terminal cleanup, +response versions and both production registrations. No runtime fix was needed. +Complete production censuses and catalogue promotion remain Step 4 work. + +### P02b-1 Step 4 — Producer enforcement and closeout (2026-10-12) + +**Step 4 complete; both independent review rounds passed.** Work remains on +`development`. The packet closeout below records full local verification; +the PR's required checks own fresh CI evidence. PR approval and merge remain +pending. + +- `IntegrationEventContractTests` independently checks the complete production + project/module-layer census, base record/required members, declared partition + sources and identifier-only payloads. Stored-source IL and independently + varied tenant/event/aggregate identifiers exercise key derivation. Invalid + declarations, unrelated/constant keys, hidden members, serialization overrides + and disallowed payload shapes have dirty/clean controls; concrete runtime JSON + round-trips preserve approved identifiers. Unsupported computed partition + derivations fail loudly rather than silently leaving the proof's scope. +- `DomainEventHandlerTests` follows assembly-scoped helpers, inherited/generic + interfaces and generated async/lambda bodies across every production project. + Planted roots/helpers exercise every module layer. Root/write-store mutation, + nested requests, further facts/notifications, connection/UoW access, provider + ports and service location are rejected; clean outbox translation stays clean. + Static IL analysis does not claim arbitrary reflection/dynamic-code coverage; + new provider ports need explicit capability controls. +- `OutboxProducerConventionTests` complements real transaction proofs with + transitive no-new-connection, no-commit and no-publication controls. The + topic-convention census now requires production events and rejects trailing + newlines. Eight producer catalogue rules move to Implemented; delivery/inbox, + dispatcher, jobs and auth rules keep their named later packets. +- Current carriers and event/architecture/review skills distinguish delivered + production from remaining dispatcher/inbox work. ADR-0057's dated Amendment 1 + links delivery without rewriting its Accepted body or prior decision records. + +**Verification checkpoint.** The Release build has zero warnings/errors and the +complete solution's format verification passes. All 1,764 unit, 261 architecture, +four contract and 1,148 integration cases pass: 3,177 total, zero failures/skips. +TRX counters were inspected per assembly; the 59 focused producer-guard cases +overlap the architecture total. The first full integration run had five failures +in two older test setups that called persistence registration without the +application pipeline, leaving the new collector dependency absent. Both fixtures +now install the shared application registration; the complete integration rerun +above passes. No runtime policy was weakened. Review fixes below have their own +verification and supersede affected counts at this checkpoint. + + +#### Step 4 independent review round 1 + +Round 1 reviewed `3473843..b6e3932` with separate GPT-6-astra xhigh +runtime/security and GPT-6.1-sol xhigh proof/corpus reviewers. The runtime review +found one Major structural backstop gap: both guard walks expanded interface +implementations but missed overrides reached through abstract or non-sealed +base-class helpers. No production handler currently uses the escaping path. +Both walks now include derived implementations and have separate dirty/clean +abstract and virtual dispatch controls. Reverting the walk to interface-only +makes two domain-handler controls and one outbox control fail; restored source passes +all 63 focused producer-guard cases and all 265 architecture cases, zero +failures/skips. Release build has zero warnings/errors and changed C# formatting +passes. These four additional architecture cases bring the complete backend +verification to 3,181 cases; unchanged unit/contract/integration evidence is the +full run above, not an additional rerun claim. + +The proof reviewer independently passed 261 architecture and 41 focused unit +cases at the implementation checkpoint. Its one Minor carrier finding is fixed: +the P02b-2 error/lease migration must account for existing P02b-1 producer rows; +its decision pass still owns descriptor handling. Both findings were verified +against source. The fixes were committed in `98c22a8`; the runtime reviewer +independently reran its exact twelve dirty/clean probes and confirmed both +formerly escaping paths are caught while clean paths remain legal. + +#### Step 4 independent review round 2 + +Two fresh reviewers (GPT-6-astra xhigh for runtime/security; GPT-6.1-sol xhigh +for proof/corpus) reviewed `3473843..98c22a8` and the adjacent producer/audit +lifecycle. Both approve with no additional runtime or guard finding. The runtime +reviewer independently passed all 63 focused architecture cases; the proof +reviewer independently passed all 265 architecture and 59 focused messaging +unit cases, zero failures/skips. These cases overlap the complete run above. +The proof reviewer's only Minor confirms the final carrier sweep: Architecture +15's stale conditional partition-proof wording now describes the delivered +persisted-value proof. + +### P02b-1 packet closeout (2026-10-12) + +**Complete on `development`; PR review and merge remain pending.** All four +implementation steps completed their commits, both independent review rounds +and verified fixes. Accepted ADR-0057 governs the delivered scope: + +- Shared producer/audit execution and immutable successful transaction + announcements, preserving ordinary event-free refusals while poisoning + failures after direct or descendant successful production. +- Immediate parameterized outbox INSERT on the existing announced writable + transaction, exact envelope/routing/identifier payload admission and no new + connection, commit or transport publication. +- Successful-save domain collection, bounded owner-only FIFO completion before + MUST audit/commit and one completed-provisioning publisher in API and Seeder. +- Nonempty production censuses with independent dirty/clean and mutation + controls; eight producer catalogue rules are Implemented. Current architecture, + standards, module specs, glossary and skills reflect the delivered boundary. + +**Local verification:** Release build has zero warnings/errors; complete solution +format verification and changed-code formatting pass. Per-assembly TRX counters +record 1,764 unit, 265 architecture, four contract and 1,148 integration cases: +**3,181 passed, zero failed/skipped**. Integration includes actual PostgreSQL +`learnstack_app` isolation/atomicity and the existing seed/public-renderer +regressions. Unit/contract/integration ran at the Step 4 implementation +checkpoint; the subsequent proof-only class-dispatch fix added four architecture +cases and reran that complete suite. Focused repeats and deliberately failing +mutation experiments are not added to the passing total. The five corpus checks +and seven ADR lifecycle tests pass. A local sweep of 33 changed Markdown files +checks 2,900 relative links and 700 fragments with no broken target; this is +manual/local validation, not a new CI anchor gate. Added closeout prose satisfies +the 88-column rule and `git diff --check` passes. + +No frontend production source, OpenAPI contract or schema migration changes. The PR's +seven required checks provide fresh CI evidence, including frontend and the +public demo/Lighthouse lifecycle; local success alone does not claim CI approval +or merge. Existing Accepted ADR changes are insertion-only dated disclosures; +ADR-0057's original acceptance content and P02b-0's entry record are preserved. + +#### PR #29 CI verification + +The first full [PR run](https://github.com/HodeTech/LearnStack/actions/runs/38228839007) +at `1e799a8` passes six of seven required jobs, including the public demo and +Lighthouse lifecycle. Docker integration reports 967 passed and one failed: +the existing stock-browser admission proof exits during its `browser 429` +phase. All other integration cases pass. The same focused proof passes locally; +the original CI diagnostic does not identify the failing browser operation. + +Test-only browser diagnostics now expose closed phase names for startup, +hydration, navigation, wire assertions and cleanup. Raw exceptions, browser +output, URLs and private values remain excluded. A verified review follow-up +also preserves the first proof failure if shutdown fails, while always running +cleanup. Assertions, deadlines and production behavior are unchanged. + +At `11871a2`, the [diagnostic run](https://github.com/HodeTech/LearnStack/actions/runs/38231443960) +passes all 968 Docker integration cases. Its non-Docker artifacts record 1,764 +unit, 265 architecture, four contract and 180 integration cases: 3,181 backend +cases pass with zero failures/skips across both jobs. The original stock-browser +failure did not recur; its cause remains unestablished, not claimed fixed. + +Both diagnostics and first-failure preservation completed two fresh independent +review rounds. Focused browser checks pass 18 cases; final guarded frontend tests +pass 1,542 cases across two packages with zero skips/todos. Lint/typecheck and +the real admission integration proof pass locally. Verified CodeRabbit findings +also reconcile delivered producer work, pending inbox delivery and process-local +versus durable ordering in architecture/glossary/XML guidance. Five corpus +checks and the changed-document link/anchor sweep pass after those corrections. +The [PR's required checks](https://github.com/HodeTech/LearnStack/pull/29/checks) +own the final-head CI verdict; passing local or intermediate evidence does not +claim approval or merge. + +**Next: P02b-2 decision pass.** Reverify G1, G3 ordering, G4, G5 resolver policy, +G7/G8, G17 and G18 error descriptors before implementation. ADR-0046 remains +reserved and undrafted; any new decision package/ADR needs maintainer approval. +That packet owns lease/grant migration, existing-row handling, dispatcher +credential/boot guard, claim/publish/mark, retry/terminal policy and metrics/health. +P02b-3 subsequently owns inbox/subscriptions, both Customization defaults and +the Seeder identity handoff after G1. Pending outbox rows do not claim delivered +consumption; no producer work is silently transferred to those packets. + +#### PR #29 external-review proof follow-up (2026-10-12) + +The review of `d37f46c..cb2bb6d` found three Minor proof gaps and no +Blocker/Major runtime finding. Commit `d8fd919` strengthens the existing cases: + +- The shared execution test enqueues through the registered `IOutbox` at + descendant depths 0, 1 and 2. It observes both business and outbox rows inside + the transaction, then verifies both disappear after the absorbed refusal. +- The committed-MUST reconciliation test requires one declared intent inside + the handler before checking that reconciliation writes no duplicate. +- The nested transaction test observes zero joiner writes and one owner write + in the same execution, including the actual commit-state transition. + +Three temporary mutations independently remove the real outbox receipt, audit +declaration and owner audit write. Their respective three, one and one target +cases fail. Production files are restored byte-for-byte, then all 62 audit/ +transaction unit cases and 71 producer integration cases pass again. + +Release build has zero warnings/errors; changed C# formatting and +`git diff --check` pass. The complete 1,764 unit and 265 architecture cases and +the 71 focused PostgreSQL cases pass with zero failures/skips; focused repeats +overlap these counts. This follow-up changes no production code or case count. + +The public-receipt suggestion needs no visibility change here: `PostgresOutbox` +is a real cross-assembly caller; invocation receipts also serve existing +integration proofs. A temporary probe of compiled `BeginInvocation` confirms +that a hierarchical ambient Activity receives a valid W3C child and is restored +on disposal. The suggested non-W3C fallback failure does not reproduce. + +Two fresh independent review rounds cover `cb2bb6d..d8fd919` and this follow-up +record. Each pairs GPT-6-astra high runtime/fixture review with GPT-6.1-sol high +proof/corpus review; all four reviewers approve without verified findings. +Five corpus checks, seven ADR lifecycle tests and the changed-document +link/anchor sweep pass. The PR checks own fresh final-head CI evidence. + +#### PR #29 systematic-review remediation (2026-10-12) + +The review against `75fc79b` identifies a valid pre-COMMIT audit classification +fault. Commit `c7dae0c` distinguishes a still-live transaction from a physical +COMMIT whose acknowledgement failed. A live frame refusal now enters the guarded, +uncancelled rollback path; the original error survives cleanup failure. Actual +COMMIT faults retain the existing Indeterminate behavior. + +The PostgreSQL regression first fails against the old code: a leaked frame +produces a permanent `indeterminate` audit row despite never attempting COMMIT. +After the fix, owner and absorbed-joiner cases observe actual business/outbox +INSERTs, then prove their rollback, a single `failed` audit row, cleared authority +and refused same-scope reuse. Scope disposal already collapsed leaked frames in +the old code; the review's claim that they stayed live after unwinding is not +reproduced. Two unit cases also preserve the frame error when rollback succeeds +or throws. API and Seeder tests document and enforce producer enrollment before +event-bearing saves, with successful event-free raw-save controls. + +Other verified changes reconcile the current uncached-settings handoff without +promising a settings event, correct ADR-0032 clause locators through ADR-0041 +errata, refresh amendment/index/example links and name concrete proof methods. +The parallelism census includes shared Application, Infrastructure and the +separate audit infrastructure project, with planted controls and exact-path +exceptions for singleton cache and pre-admission host lookup flights. Test-only +browser diagnostics distinguish launch, DevTools readiness and private-carrier +failures; cleanup preserves the first +failure and exposes only closed phase tokens. + +The remaining runtime suggestions do not demonstrate a current failing path: +domain dispatch validates enrollment before owner access; outbox ancestry and +JSON shape are guarded before serialization checks; the Seeder test positively +observes promotion before its deliberate refusal; reflection and log-trigger +changes fail their existing controls loudly. Provider-port recognition remains +an explicitly enumerated limitation, not a future-port discovery claim. No +runtime visibility/marker, serializer, scheduling or ConfigureAwait refactor is +needed. The final announcement check remains defense in depth after drain. +The earlier temporary mutations are recorded manual experiments; their target +regression cases are permanent, without a new automated mutation-runner claim. + +Two fresh independent review rounds pair GPT-6-astra xhigh runtime review with +GPT-6.1-sol xhigh proof/corpus review. Round 1 checks `75fc79b..3f4c121` and +identifies one additional Minor in the outer browser proof: a caller-supplied +closed phase token can masquerade as a sanitized error. Commit `9b2fcf6` requires +the existing private brand at that boundary. Its paired actual-export cases +first fail for the forged token, then pass while retaining genuine branded +error identity. The first-round proof reviewer verifies the fix. Both fresh +Round 2 reviewers approve `75fc79b..9b2fcf6` without findings. + +Full local verification passes 1,766 unit, 266 architecture, four contract and +1,152 integration cases: 3,188 backend cases, zero failed/skipped. Focused +verification passes 75 producer integration and 64 audit/transaction unit cases, +overlapping those totals. Guarded frontend tests pass 1,550 cases across two +packages, including 26 browser diagnostics cases, with zero skips/todos. Release +build has zero warnings/errors; solution format, frontend lint/typecheck, seven +ADR lifecycle checks, the changed-document link/anchor sweep and +`git diff --check` pass. Original Accepted Status/Decision/prior amendments and +the frozen P02b-0 entry record remain byte-preserved. The +[PR checks](https://github.com/HodeTech/LearnStack/pull/29/checks) own the exact-head +CI verdict; local results do not establish that verdict or merge approval. +PR review and merge remain pending. + +#### PR #29 outbox INSERT and ownership follow-up (2026-10-12) + +All four follow-up comments reproduce against `b561c8f`. Commit `96e6f4d` +marks the existing unit rollback-only when the immediate outbox INSERT throws, +then rethrows the same exception. Only a successful INSERT records produced +work; validation refusals before execution retain their existing behavior. + +The existing duplicate-EventId regression now covers propagation and absorption +of a real PostgreSQL INSERT failure. Both cases first fail against the old code +at the immediate rollback-only assertion, before coordinator unwinding can +poison the unit. The fixed cases retain the successful parent's receipt, create +no failed-child receipt, prove original exception identity or absorbed-error +refusal, and verify rollback and shared-state cleanup. All 31 outbox cases pass. + +Architecture 31 records Steps 2–3's delivered enqueue, successful-save +collection/promotion and owner-only drain. Standards 02/18 distinguish UoW-owned +domain collector/source cleanup from reconciliation and audit capture cleanup +owned exclusively by the outermost `AuditExecutionCoordinator` frame. The +catalogue no longer claims inbox parity for `InProcessEventBus`. Dispatch and +consumer delivery/inbox remain P02b-2 and P02b-3; no ADR decision changes. + +Two fresh independent review rounds pair GPT-6-astra xhigh runtime review with +GPT-6.1-sol xhigh proof/corpus review. Round 1 approves `b561c8f..96e6f4d` +without findings. Round 2 covers the same code/document changes and this dated +closeout; both reviewers approve without findings. + +Full local verification passes 1,766 unit, 266 architecture, four contract and +1,153 integration cases: 3,189 backend cases, zero failed/skipped. Focused outbox +repeats overlap that total. Release build has zero warnings/errors; solution +format, seven ADR lifecycle checks, the changed-document link/anchor sweep and +`git diff --check` pass. No frontend source, schema, credential or accepted ADR +changes. The [PR checks](https://github.com/HodeTech/LearnStack/pull/29/checks) +own final-head CI evidence; PR review and merge remain pending. + +### P02b-1 merge and closeout (2026-10-12) + +The maintainer merged [PR #29](https://github.com/HodeTech/LearnStack/pull/29) at +2026-10-12 13:47:58 UTC. GitHub records final PR source +`8a97cd2b7c19bf54a1b0b1f1ad75175256417c9c` and squash merge +`b1f6f21cab556ee7ba497dfc0d64e51b8cf1dad8`, whose parent is the previous main +`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`. Source and squash merge have the +identical tree `ba6f9b552c17598ec219ec9d2fc04ef5f235eec0`. Development incorporates +the main merge without switching branches or rewriting published history. + +All seven required checks pass in the +[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38255804801) +for that source; CodeRabbit also reports success. The tested synthetic merge is +`50fe60560b7966a23c14ab359531aadfbf59a442`. Verified downloaded artifacts record: + +- **3,189 backend passes**, zero failures/skips: 1,766 unit, 266 architecture, + four contract, 180 Docker-free integration and 973 Docker integration cases. +- **1,550 guarded frontend passes**: 1,490 web and 60 SDK, zero + failures/skips/todos; frontend lint, typecheck and builds also pass. +- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, nine + screenshots and matching source/checkout identities and report digests. + Automated accessibility is 1 throughout, CLS is 0 and maximum normalized + initial JS gzip is 106,552 bytes. Owned cleanup passes; timing medians remain + advisory. These are final PR-run results, not a claim about a post-merge run. + +**P02b-1 is closed.** All four steps and verified review fixes are delivered; +their two independent review rounds remain recorded in the +[packet closeout and follow-ups](#p02b-1-packet-closeout-2026-10-12). Earlier dated +delivery/review records retain their historical pre-merge wording. Accepted ADRs +and P02b-0's entry record are unchanged. Phase 02b remains in progress. + +**Next: P02b-2 decision pass.** Reverify G1, G3 ordering, G4, G5 resolver policy, +G7/G8, G17 and G18 failure descriptors before dispatcher implementation. +ADR-0046 remains reserved and undrafted; the decision package and any new ADR +require maintainer approval before implementation. P02b-2 owns the lease/grant +migration, existing-row handling, dispatcher credentials/boot guard, +claim/publish/mark, retry/terminal policy and metrics/health. P02b-3 owns inbox +delivery, the two Customization defaults subscriptions and the Seeder handoff. +Producer rows are durable but do not yet claim delivered consumption. Background +jobs, API authentication, realm reconciliation, BFF sessions and phase-exit +enforcement remain with P02b-4–8 in the [packet table](phase-02b-events-auth.md#packets-and-decision-gates). + +**Documentation-only closeout validation.** All 266 local Release architecture +cases and seven ADR lifecycle/workflow controls pass, zero failures/skips. The +five changed Markdown files resolve 585 relative links and 186 fragments without +errors; added prose wrapping and whitespace checks pass. Prior dated delivery +records and all Accepted ADR files are byte-preserved. Full runtime suites are +not rerun locally for this documentation-only change; the final PR artifacts +above supply their evidence. + +## P02b-2 — Dispatcher + +### P02b-2 decision package (2026-10-12) + +**Accepted — 2026-10-12, @cemil.** The revised decision package and ADR-0046 +are approved, including all four implementation steps and their review loop. +The documentation/code audit used `development` +at `b1f6df34b1d0db9dff77b355743d7bf8885947b3`, the P02b-1 merge closeout. +Three independent read-only audits covered delivery, privilege/audit and runtime/ +observability. They ran no tests and changed no files. The accepted package uses +[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); earlier +Accepted ADR bodies and prior dated delivery records remain intact. The dated +acceptance record below distinguishes approval from implementation evidence. + +The dated P02b-1 closeouts' "Next" and "reserved and undrafted" descriptions +record the state before this package. This current package and the Active index +replace those historical navigation instructions; the old records remain intact. + +#### Review findings and accepted answers + +The current bus's zero-handler success is unsafe for P1's real provisioning rows: +their consumers do not exist until P3. Separately, the outbox role cannot write +the MUST audit required by terminalization, and cancellation alone cannot bound +a callback that ignores its token. ADR-0046 explicitly resolves these gaps. + +| Gate / concern | Accepted answer | Delivery owner | +|---|---|---| +| G1 subscriber identity and isolation | Shared transport-owned inbox keyed by tenant, stable subscription ID and event ID; separate delivery ledger owns attempts, terminal state and targeted replay | Contract now; implementation P02b-3 | +| G3 ordering | Deterministic eligible selection by availability, occurrence and ID within one processor; no enqueue, commit, retry or cross-process ordering promise | P02b-2 | +| G4 attempts and terminal state | Six committed normal claims; five published retry delays; fresh-token crash recovery; explicit terminal request and audited terminal timestamp; no seventh publish | P02b-2 | +| G5 type and zero-subscriber policy | Declared concrete types/compatible aliases only; invalid/retired/unknown records terminalize; Pending required subscriptions preserve rows; only intentional absence acknowledges without publication | P02b-2; Active durable subscribers P02b-3 | +| G7 terminal audit | Fenced state transition plus MUST security-event on one transaction through `WriteEventTerminalAsync`, with a restricted transition witness binding audit tenant/org/event to the actual UPDATE result; `platform.outbox.dead_letter` now, reserved Tenancy-owned `platform.delivery.dead_letter` when P3's writer ships; failed audit retries terminalization without delivery | P02b-2 producer; P02b-3 subscriber | +| G8 bypass | Explicit routine-dispatch exception, confined credential and exact grants; existing platform-scope entry audit unchanged | P02b-2 | +| G17 metric dimensions | No tenant labels; registry-bounded event types; separate backlog, eligible age, deferred backlog and heartbeat; immutable gauge snapshots | P02b-2 | +| G18 failure storage | Closed descriptor, at most 256 UTF-8 bytes with CHECK; replace free-form legacy descriptors without changing fact/state | P02b-2; erasure inventory P02b-8 | +| Credential topology | API-owned keyed lazy source; exact physical outbox-role checks; boot connectivity; no Seeder/web credential propagation | P02b-2 | +| G6/G19 dependency | Preserve common owner, envelope organization and effective SystemActor; activate both real defaults subscriptions only with durable acceptance and Seeder handoff | P02b-3 | + +The exact normative replacements and additive audit seam are enumerated in +[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#bounded-supersession-and-additive-seams). +They are not ADR-0041 errata. At acceptance, append dated disclosures to +ADR-0006/0010/0038, ADR-0003's unchanged role model and extended grant-budget +navigation, the bounded audit-grant replacement disclosure and +separate fifth-writer seam amendment to ADR-0044, and the same-transaction +clarification to ADR-0033. Keep original acceptance blocks, +decisions and earlier amendments byte-preserved. G1's rule changes are recorded +now but their implementation remains Registered for P3. + +#### Runtime bounds and observation + +These approved bounds are not implemented defaults yet. Options reject invalid +or unbounded values at composition; tests can inject time and tighter positive +bounds. Lease ownership always uses PostgreSQL time, never a caller's clock. + +| Setting / policy | Approved initial bound | +|---|---| +| Worker and claim capacity | One worker; one just-in-time normal claim | +| Idle poll | 200 ms | +| SQL operation / complete terminal transaction deadline | 5 s | +| Publish wait deadline | 10 s | +| Lease | 30 s; validate margin for publish plus fenced transition | +| Progress health bound | 45 s without actual completed progress | +| Snapshot refresh | After completed iterations; idle target 5 s; stale at the 45 s health bound | +| Cancellation-ignoring callbacks | At most four retained tasks; block their partitions; unhealthy while any remain; stop new claims at four | +| Shutdown wait | At most 30 s; retain live task-owned resources until completion or process exit | +| Attempts and backoff | Six normal claims total; 1 s, 5 s, 30 s, 5 min, 1 h | +| Durable failure descriptor | Closed vocabulary, at most 256 UTF-8 bytes | + +A publish timeout cancels the callback and persists its fenced failure, or leaves +an unknown outcome for expired-lease recovery if persistence fails. The callback +keeps ownership of its scope until actual completion; its late result cannot +acknowledge the row. Exclude its partition from new local claims until it finishes. +Unrelated partitions can progress within the four-task allowance. Saturation +stops acquisition and reports unhealthy; no unbounded detached-task replacement +or forced managed-task termination is claimed. P3 must also fence its business +transaction before enabling Active production subscribers. + +Its completion gate must reject a canceled/timed-out attempt before COMMIT even +if failure persistence did not replace its token. Cancellation after physical +COMMIT starts remains Indeterminate under ADR-0033; P3 recovers from atomic +business/inbox/ledger state rather than promise rollback at that boundary. + +Pending count includes all unprocessed, nonterminal rows, including delayed, +leased, terminal-requested and manifest-deferred work. Eligible age uses the exact +normal-publication claim predicate: it excludes terminal requests, exhausted +attempts, future availability, live or unrecovered expired claims, and held/locally +blocked partitions. It is zero when none qualify and never negative. Deferred +count exposes manifest-held work. +Heartbeat advances only after actual bounded loop work, including an empty poll, +not from an independent timer. Failed refresh retains the last snapshot and +marks observation stale. Terminal-audit failure is unhealthy, never a fabricated +successful empty queue. `/healthz` remains liveness-only. + +Standards 10 owns the final metric inventory at acceptance. Preserve existing +outbox duration/failure/dead-letter/lease-loss names with registry-bounded +`event_type` where applicable. Add unlabelled +`learnstack_outbox_oldest_eligible_age_seconds`, +`learnstack_outbox_deferred_count` and +`learnstack_outbox_heartbeat_age_seconds`; pending count becomes unlabelled. +Inbox counters remain reserved for P3, and job metrics for P4. Gauge callbacks +perform no SQL. Dispatcher-owned logs, traces and failure descriptors use validated +correlation and bounded outcomes, without exception text, payload, raw stored type +or connection data. Current bus/consumer exception telemetry is a separate P3 +reconciliation obligation before Active production subscriptions; this packet +does not claim that existing transport diagnostics are already minimized. + +#### Four approved implementation steps + +Each step implements and commits on `development`, then runs two fresh independent +review rounds. Verify findings against current code, fix valid findings, validate +and commit fixes before the next round/step. A clean review needs no empty commit. +The loop continues automatically unless a blocker or new maintainer decision +requires input. No branch switch or history rewrite is part of this package. + +1. **Decision reconciliation, schema and confined composition.** Accept ADR-0046 + and the gate parts above before code. Register catalogue obligations; update + canonical Outbox DDL/indexes/grants, metric labels, audit policy, architecture + and glossary. Add Platform-chain lease/terminal/descriptor/identity migration + and Audit-chain INSERT-grant migration. Declare registry/aliases/readiness, + keyed credential validation and physical-role guard. Adapt test-owned host + composition explicitly; production registration stays enabled. Validate exact + privilege sets, forward/down/reapply and invalid legacy input. No handler or + arbitrary type is constructed to discover subscription metadata. +2. **Durable transitions and terminal audit.** Implement parameterized claim, + recovery, success, backoff, terminal-request and atomic terminal-audit paths. + Add the confined fifth store method, off-path catalogue/matrix row and narrow + call-site/transition-witness guards. Prove token/expiry fences, same-worker + reclaim, six-claim crash, + no seventh publish, uncertain completion and audit rollback on real PostgreSQL + using actual outbox/application roles. Intentional absence and Pending holds + must have distinct non-vacuous controls. +3. **Hosted lifecycle and observability.** Activate the API BackgroundService; + implement bounded waits/overruns/shutdown, progress health, safe traces and + snapshot metrics. Adapt the API launcher/demo environment allowlist and its + proofs without forwarding the credential to web/Seeder. Prove production + registration, startup rejection/valid controls, poison-row progress, ignored + cancellation, safe disposal and continued unrelated work within the bound. +4. **Enforcement and closeout.** Complete production-census and planted controls, + full Release regression/format, mandatory Docker proofs and applicable demo/ + frontend tooling checks. Reconcile current-state docs, actual test counts, + catalogue status and seven existing CI checks at the exact PR head. Create the + PR for maintainer review only after every step/review is complete; claim no + merge or P3 delivery from P2 closeout. + +#### Decisive proof obligations + +- Two independent processors contend under live leases; a release-on-read mutant + fails. Expiry allows redelivery; both stale success and stale failure lose the + token fence, including reacquisition by the same worker identity. This is not + a claim of two separate processes or exactly-once publication. +- Retry boundaries use controllable time/database availability, not wall-clock + sleeps. Crash recovery after claim six and audit refusal cannot cause a seventh + publish. Reconcile lost/uncertain terminal COMMIT before retrying so a completed + terminal audit is not duplicated. Terminal, delayed, leased, deferred and due + rows distinguish all queue gauges. +- Audit refusal on a terminal request with fewer than six attempts never makes + that row publishable again. Its pending contribution remains; its contribution + to oldest publish-eligible age is excluded. +- Known V1 payloads remain readable after declared deployment aliases. Reverse + commits, equal occurrence times and retry overtaking falsify stronger ordering. + Unknown/retired/malformed/mismatched rows do not trigger arbitrary type loading. +- Real TenantCreated rows survive repeated Pending polls without attempts or + constructions. P3's activation proof must later deliver them to both stable IDs. +- Missing/malformed/wrong-user credentials refuse without secret text; valid + configuration is lazy; real physical guards reject elevated/transitive roles. + Audit INSERT is allowed; audit read/update/delete and business access are not. +- Against the real bypass role, replace an audit draft's tenant, organization or + event while retaining the successful fenced transition's restricted witness. + Each mismatch must leave neither terminal state nor audit row committed. Prove + a matching organization-scoped success and rejection of stale/wrong-transaction + witnesses; GUC/RLS assertions cannot substitute for these controls. +- Cancellation-ignoring operations retain safe resource ownership, cannot write + late acknowledgements and cannot grow beyond the approved bound. A blocked or + saturated loop becomes unhealthy while `/healthz` still returns 200. +- Before P3 activates subscribers, its proof must include failed timeout + persistence followed by late business completion and timeout during physical + COMMIT on the final subscriber claim; atomic ledger/inbox state decides recovery. +- Structural censuses include production subjects and planted clean/dirty cases + for each key's resolution, publication, type loading and write confinement. + Behavioural controls mutate lease/terminal/audit safeguards to prove sensitivity. + +The P02b-2 publication proof uses the shipped BackgroundService, registry and +transition/audit stores on real PostgreSQL and actual roles. Keep real TenantCreated +subscriptions Pending. Only isolated test composition supplies an Active synthetic +contract and controlled transport/handler to exercise publish/mark, failures, +recovery and deadlines; intentional absence is a separate control. Assert nonempty +production machinery, without inventing a production subscriber. P3 owns handler +and durable-acceptance censuses when those production subjects exist. + +#### Scope retained by later owners + +P3 owns shared Inbox/delivery DDL and RLS, per-subscription business/audit frames, +retries, terminal audit and targeted replay, both Customization defaults and +Seeder identity handoff. That boundary is required by the packet dependency, +not an unowned deferral. The companion Hub roadmap's per-module inbox reference +needs a coordinated dependency-pointer update before P3 closeout; Hub remains +roadmap owner and this package adds no Hub endpoint or runtime work. P4 owns jobs; +Phase 03 owns operator routes/permissions; P02b-8 owns erasure inventory; Phase 11 +owns brokers, cross-process evidence, purge and readiness exposure. + +#### Proposal review and validation (2026-10-12) + +At proposal commit `cc5de26`, two independent review rounds completed before +maintainer approval. Round 1 used +separate GPT-6.1-sol xhigh delivery and security/corpus reviewers. Verified fixes +separate the audit-grant replacement from the additive fifth seam, allow safe +terminal auditing of malformed causal metadata, scope diagnostic minimization to +the dispatcher, and require atomic subscriber ledger completion plus a sticky +timeout gate. Cancellation after physical COMMIT starts remains Indeterminate. +Both reviewers approved the corrected proposal. + +Round 2 used fresh GPT-6.1-sol xhigh delivery and GPT-6-astra high corpus/privilege +reviewers. Both approved without actionable findings. Reviews were read-only; +they did not run runtime suites or claim implementation evidence. + +Documentation-only validation passes: 266 local Release architecture cases, +seven ADR lifecycle/workflow controls, 329 local links and 119 fragments across +the four changed Markdown files, prose wrapping and `git diff --check`. Prior +P02b-0/P02b-1 dated delivery records and all Accepted ADR files are byte-preserved. +Full runtime/Docker suites remain implementation-step obligations; no dispatcher, +inbox or gate delivery is claimed by this proposal. + +#### External proposal review reconciliation (2026-10-12) + +Two external reports were checked against the current draft, accepted contracts, +canonical DDL and production code. Their reported line numbers are not authority. +This revision remains Proposed and changes no runtime or Accepted ADR body. + +| Finding | Verified disposition | +|---|---| +| Erasure assigned to Phase 11 | Already corrected in `cc5de26`: privileged redaction and its bounded caller contract belong to Phase 03; only retention purge belongs to Phase 11 | +| Two subscription IDs conflict with `card@1` / `plain@1` | Rejected: `BuiltInCustomizations.Card` is a `BuiltInContentType`; `Plain` is a `BuiltInTaxonomy`. ADR-0057 freezes those two independent effects, not two content types. The ADR now maps each ID explicitly | +| Bypass audit INSERT lacks row-bound identity proof | Valid: the seam now receives a restricted witness from the actual fenced UPDATE result; draft tenant/org/event/subscription must match it. Forged-identity and matching-success proofs are explicit | +| Terminal-request normal eligibility and undefined release | Explicit predicates now exclude terminal requests/exhausted attempts; recovery is separate. Pending holds precede payload validation, even for malformed payloads. Removed the unexplained release transition; success/retry/terminal paths clear leases | +| Inbox completion, identity grammar and replay ambiguity | Clarified uncommitted claim and atomic completion/rollback; completed inbox rows never reset; subscription IDs version deduplication semantics | +| Grant locator, legacy batch/exactly-once/DLQ designs and metric/off-path carriers | Named exact authorities and acceptance replacements. ADR-0003's role model remains unchanged; Database Standards owns actual grants. No competing current dead-letter design remains after acceptance | +| Envelope storage, narrow P3 SELECT, subscriber audit owner and P2 proof subjects | P3 must name durable envelope copies/references before DDL and inventory them for erasure; scheduler cannot read payload; subscriber audit is Tenancy-owned. P2 exercises shipped machinery with isolated test contracts while real subscriptions stay Pending | +| Final acceptance/handler failure and roadmap target checks | Failed/unknown durable acceptance consumes producer attempts; only accepted deliveries isolate business retry budgets. The phase's own undated zero-subscriber/replay sketches are now named acceptance replacements | +| Missing references and historical Next navigation | Added applicable ADR links and the ADR-0047 reservation link; added current navigation without rewriting dated P1 records. ADR-0045 is not used by this ADR and needs no artificial reference | + +The internal executor performs delivery, not publication; it receives no exception +to the outbox-only publisher rule. SecurityEvent records a consequential bypass +terminal transition, not routine polling. The selected order receives matching +normal-claim and recovery/terminal indexes. These are contract clarifications, +not claims that the proposed mechanisms have shipped. + +The revision received read-only GPT-6-astra high audit/privilege verification and +a fresh GPT-6-sol xhigh delivery/corpus review. The latter identified the Pending +validation priority, acceptance-failure budget and phase-carrier gaps recorded +above. Both reviewers approved after the verified fixes; neither claimed runtime +execution evidence. + +Revision validation passes: 266 Release architecture cases, seven ADR workflow +controls, 337 local links and 124 fragments across the four proposal Markdown +files, prose wrapping and `git diff --check`. Accepted ADR files and dated +P02b-0/P02b-1 delivery records remain byte-preserved. Only this package and the +Proposed ADR changed in the revision. Maintainer approval still precedes runtime +implementation and acceptance-carrier edits. + +### P02b-2 acceptance (2026-10-12) + +**Accepted by @cemil.** The maintainer approves the revised ADR-0046 and this +decision package, and authorizes all four implementation steps on development +with two fresh independent review rounds per step. The accepted decision is +committed before runtime edits. G1, G3's ordering, G4, G5's resolver/readiness, +G7, G8, G17's event metrics and G18's failure-descriptor parts are Accepted. +P02b-3 still owns durable acceptance, inbox/ledger DDL, independent subscriber +execution/retries, both real default subscriptions and Seeder handoff; job and +erasure gates retain their later owners. + +Acceptance appends bounded supersession disclosures and additive seams to the +named Accepted ADRs, reconciles the current standards/architecture/glossary/skill +carriers, and registers six catalogue obligations. Original ADR acceptance +metadata, decisions and prior amendments remain intact. Dated P02b-0/P02b-1 +records remain byte-preserved. Registered rules and planned audit operations +claim no runtime enforcement; delivery evidence belongs to each step below. + +### P02b-2 Step 1 — Decision, schema and confined composition (2026-10-12) + +**Implemented; both independent review rounds and fresh fix review complete.** +Decision commit +`192810b` precedes runtime edits. Step 1 adds the Platform-chain migration +`20261012180355_add_outbox_dispatch_state` and Audit-chain migration +`20261012180433_grant_outbox_terminal_audit`. Existing migration bodies remain +unchanged. New state/identity/UTF-8 CHECKs and eligibility/recovery/terminal +indexes accompany exactly eight outbox status-column UPDATE privileges and +INSERT-only audit access. Legacy diagnostic replacement spans both tenants; +invalid legacy identities reject the migration and roll back its owner-only +backfill. Disposable-schema down/reapply preserves event facts and retains +redaction; live rollback requires a forward fix. + +The API registers a keyed, lazy, DI-owned outbox source with exact configured +username checks and physical session/current-role, attribute and membership +checks. Missing configuration fails upon resolution; Step 3's mandatory worker +startup will resolve it and prove connectivity. Seeder/web receive no new source. +The immutable contract/alias/readiness registry constructs no handlers. Real +TenantCreated has its two distinct Pending subscriptions; Active, intentional +absence, unknown and retired identities have separate controls. The two existing +connection-resolution censuses explicitly admit the approved dispatcher builder +and composition root, without wildcard exemptions. + +**Verification before review:** `CI=true` Release build has zero warnings/errors. +TRX counters and process exit codes record zero failed and zero skipped cases: + +| Suite | Passed | Scope | +|---|---:|---| +| Unit | 1,800 | Complete unit suite, including registry/composition/configuration controls | +| Architecture | 266 | Complete non-skippable suite | +| Contract | 4 | Served OpenAPI/public SDK contract suite | +| Integration, no Docker | 180 | Complete HTTP suite | +| Integration, Docker | 128 | Migration/role/schema/grant/rollback classes affected by Step 1 | + +The Docker slice includes `OutboxDispatchMigrationTests`, +`OutboxDispatcherRoleGuardTests`, `PlatformSchemaTests`, `TenancySchemaTests`, +`AuditSchemaTests` and `MigrationRollbackTests`. Role-mutation proofs own a +separate container; destructive schema probes own disposable databases. These +counts describe this step's completed checks, not a full Docker regression. +The six new catalogue rules remain Registered: transition/audit/worker proof +lands in later steps. No dispatcher execution or P02b-3 delivery is claimed. + +#### Step 1 review round 1 + +Fresh read-only GPT-6-astra xhigh security/schema and GPT-6.1-sol xhigh +corpus/test reviewers examined `192810b..d9bc77b`. Security review found no +actionable defect. Corpus review found a stale handler-owned inbox instruction +in the code-review skill and an unqualified historical per-module inbox note in +Architecture 10. Both were verified and reconciled to ADR-0046's transport-owned +P02b-3 target. Original dated notes remain intact. No runtime change was needed; +the existing test evidence above remains applicable. The correction passes local +file/fragment checks, prose wrapping and `git diff --check`. + +#### Step 1 review round 2 + +Fresh GPT-6.1-sol xhigh security/composition and GPT-6-astra high corpus/proof +reviewers examined `192810b..6a13455`. Corpus review approved without findings. +The composition review verified that an open generic Active handler could match +the discovery census despite being unconstructible. Active admission now requires +a closed type. A regression proves discovery sees the open generic offender, +refuses its matching manifest and accepts a closed generic control. The complete +Release unit suite passes 1,801 cases; the complete architecture suite passes +266, both with zero failures/skips. A fresh focused review checks this correction +before Step 2 begins. Removing the closed-type check makes the new regression +fail; restoring it makes all 17 registry cases pass. No migration, grant or +Pending policy changed. + +Fresh GPT-6.1-sol high focused review of `6a13455..b6fc714` approved the correction +without findings and independently checked its accepting/rejecting controls and +saved TRX counters. The completed Step 1 commits are `d9bc77b`, `6a13455` and +`b6fc714`; the next authorized implementation step is durable transitions and +terminal audit. + +### P02b-2 Step 2 — Durable transitions and terminal audit (2026-10-12) + +**Implemented; both independent review rounds complete.** `OutboxDispatchStore` uses +short parameterized database-time transitions. Normal acquisition commits one +fresh token and one attempt before returning; expired ownership requires a fresh +recovery token without another attempt. Success, failure, terminal request and +terminalization require the current token and an unexpired lease. Five backoffs +follow six counted normal claims; exhausted or requested work never reenters +normal publication. Pending identities and aliases are excluded before payload +validation in every acquisition path. Local blocked partitions receive the same +exclusion. + +`OutboxEnvelopeReader` uses only the registry's concrete type and frozen options. +It compares persisted fact/routing/time, tolerates PostgreSQL microsecond +truncation and checks the canonical reserialization byte cap, rather than jsonb +whitespace. Complete envelope admission precedes intentional acknowledgement; +Pending, unknown, retired and invalid outcomes remain distinct. + +The fifth `IAuditStore` method preserves the existing four writes. Only +`OutboxDispatchStore.TryTerminalizeAsync` derives the minting capability and calls +it. The private immutable witness reads all identity and causal values from the +actual fenced UPDATE result, including the old acquisition token. The real audit +store requires the declared producer MUST/SecurityEvent, matching draft identity +and the same live connection/transaction. Both writes commit together. Invalid +causal values are omitted; invalid correlation uses a validated attempt trace. +No audit SQL is added outside `PostgresAuditStore`. Tenancy registers the producer +operation; the subscriber operation remains planned for P02b-3. + +Terminal SQL plus audit share one five-second deadline. A lost COMMIT response +triggers a separate bounded durable-state read before returning/retrying; it +cannot insert a second audit into a completed terminal row. A test-owned TCP +proxy drops the real PostgreSQL COMMIT acknowledgement after physical commit, +proves reconnection and checks one durable terminal/audit pair. Production has no +fault hook. Failed audit retains the terminal request, including below attempt +six, and never permits another publication. + +Tests use actual `learnstack_app` inserts with announced tenant/org and the +guarded `learnstack_outbox_admin` source for transitions. Disposable databases +isolate grant and state mutations. Nonempty whole-production Cecil censuses and +clean/dirty controls cover witness shape, minting/fifth-write callers, async and +delegate helpers, required catalogue injection and named dynamic type-loading +APIs. This is a bounded IL capability check, not arbitrary reflection/dataflow +analysis. SharedKernel has no friend assembly. + +Four behavioural mutation controls each fail as intended: removing lease expiry, +admitting terminal requests for publication, omitting MUST audit and discarding +successful uncertain-COMMIT reconciliation. Every edit is restored before the +clean validation run. Six-attempt tests start at zero and commit all six claims; +they cover both an explicit sixth failure and an expired sixth claim. Snapshot +proofs distinguish due, future, leased, expired, requested, exhausted, deferred, +locally blocked, processed and completed-terminal rows. + +The four transition/audit/type catalogue rules are Implemented. Hosted lifecycle, +publication/overrun proofs, credential caller enforcement and observation remain +Steps 3–4. Real default subscriptions stay Pending; no P02b-3 business effect, +inbox or delivery ledger is claimed. + +**Verification before review:** Release solution build has zero warnings/errors; +formatting covers all 21 changed C# files. TRX counters and process exit codes +record zero failures/skips: complete unit 1,825, complete architecture 273, +contract 4, complete Docker-free integration 180 and affected Docker integration +110. The Docker slice covers `OutboxDispatchStoreTests`, `AuditStoreTests`, +`PlatformAdminScopeTests`, `TenantAssertionAuditTests` and +`PublicReadTransactionTests`; it is not a full Docker-suite claim. All four +behavioural mutants fail their named tests, then the restored code passes. +Local file/fragment, historical-record/Accepted-ADR preservation, prose-width and +`git diff --check` controls pass. + +#### Step 2 review round 1 + +Fresh read-only GPT-6-astra xhigh security/concurrency and GPT-6.1-sol xhigh +proof/corpus reviewers examined `c6ceaa9..7976113`. The proof review approved; +its independent rerun passed 273 architecture and 24 focused unit cases. The +security review reproduced a stored-routing gap: deserialization regenerates +get-only Topic/PartitionKey values, masking changed or absent payload members. +The reader now checks those required string members in the original JSON before +using the declared CLR contract, then compares the reconstructed routing with +the row. Ten unit mutation cases and four real-database cases cover changed, +missing and malformed routing, terminal-only progression and minimized audit. +The unchanged payload remains an admitted control. Removing the original-field +check makes all ten new unit cases fail. After restoration, the complete unit +suite passes 1,835 cases, architecture passes 273 and the four new Docker cases +pass, all with zero failures/skips. Round 2 follows the verified correction; +hosted lifecycle remains Step 3. + +#### Step 2 review round 2 + +Fresh read-only GPT-6.1-sol xhigh security/concurrency and GPT-6-astra high +proof/corpus reviewers examined `c6ceaa9..ffce05f`. Both approved without verified +findings. Independent Release no-build reruns passed 34 envelope/options unit +cases, 19 dispatch/audit architecture cases and all 53 dispatch-store Docker +cases, with zero failures/skips. The proof reviewer independently passed all seven +dispatch capability facts and checked the real COMMIT-response-loss result in +the restored database receipt. Both inspected the actual row-bound audit and +routing correction rather than accepting review notes as evidence. Step 2 is +closed; Step 3 may activate the mandatory worker and observation. No P3 delivery +or inbox effect is claimed. + +### P02b-2 Step 3 — Hosted lifecycle and observability (2026-10-12) + +**Complete; both independent review rounds passed.** The API owns +its mandatory `OutboxProcessor` BackgroundService, guarded dispatcher-source +startup resolution/connectivity, bounded publication lifecycle and retained +overrun ownership. Observation supplies immutable gauge snapshots, bounded +producer diagnostics and the registered, unmapped `outbox` health check. +`/healthz` remains liveness-only. Paired API launchers supply application and +confined dispatcher credentials; every Seeder invocation uses an explicit +application-only environment, and web receives neither database credential. + +**Verification before review:** the Release solution build reports zero +warnings/errors. TRX counters record zero failures/skips in the complete unit +suite (1,845), contract suite (4), Docker-free integration suite (182), restored +architecture suite (273), and the actual-host PostgreSQL `OutboxProcessorTests` +slice (16). Worker helper/observation unit cases are included in the unit total. +The initial architecture run exposed the newly registered worker in the global +keyed-resolution allowlist; the exact outbox-key allowance is corrected and the +restored 273-case run passes. This is a focused Docker-runtime receipt, not a +full Docker-suite claim. All three actual API-launcher cases also pass after +correcting the environment reader to accept the explicit dispatcher credential. +The two affected frontend files pass 116 tests; web lint and typecheck pass. +Whitespace verification passes for all 39 changed C# files; affected TypeScript +and runtime-script Prettier checks, script syntax, diff whitespace and 2,172 +relative links/396 fragments pass. Historical producer delivery records and +Accepted ADR bodies remain byte-preserved. + +`OutboxProcessorTests` covers actual registration/guarded boot, invalid credential +refusal, real provisioning Pending holds, poison/ordinary failure progression, +explicit intentional absence, retained callback/cleanup ownership, four-task +saturation and finite shutdown. Observation tests cover monotonic stale health, +failed-refresh retention, terminal-audit failure, finite metric labels and fresh +trace identity, with bounded canonical correlation reconstructed from parsed +identity rather than optional traceparent extensions. Two independent actual API +workers prove no second publication/claim while the first live lease is held. +Never-blocks, live-ownership and Pending catalogue rules are Implemented. The full +health production census/planted controls remain Step 4; that rule is Registered. + +Two behavioural mutations fail in the intended executed test: removing local +partition admission permits a sibling claim before retained cleanup completes; +removing live-lease admission permits a competing worker to claim the held row. +Both source files are byte-restored before the clean build/unit/worker rerun. +Step 3 completed both independent rounds and the verified corrections below. +Steps 1–2 completed both rounds in their +records above. Step 4 owns full credential/publication censuses, catalogue +enforcement and packet closeout. P02b-3 still owns durable acceptance, shared +inbox/ledger, independent subscriber retries, both real default subscriptions and +Seeder handoff. Real required subscriptions remain Pending; no consumer business +effect is claimed. + +#### Step 3 review round 1 + +Fresh read-only GPT-6-astra xhigh security/lifecycle and GPT-6.1-sol xhigh +proof/corpus reviewers examined `d4c06a46..756c8523`. Security approved without +verified findings. The proof reviewer found that the demo's pre-existing +`--validate-demo-config` invocation forwarded all four credentials to Seeder, +contradicting the new confinement claim. Validation now runs inside the launcher +with a closed local connection grammar; the obsolete Seeder mode is removed. +Manifest and convergence modes share the same explicit child allowlist, and +standalone `make seed` uses it too, excluding ambient aliases and role passwords. +Stale role/password/database/host/port and malformed configuration controls move +with their owner instead of weakening the check. The complete Docker integration +regression at the implementation commit passes 1,083 cases with zero failures or +skips. This supplements the focused pre-review receipt above; final packet +verification will rerun the changed tooling and actual PR-head CI. +The correction's Release build has zero warnings/errors; the Docker-free +integration run passes 175 cases after seven obsolete parser cases moved to the +launcher suite. The guarded complete frontend run passes 1,608 cases (1,548 web +and 60 SDK), with zero skips/todos; 91 demo lifecycle cases include all four-role +configuration and actual shell/child-environment controls. Typecheck, affected +formatting, script syntax, diff whitespace and the delivery-record link check +pass. These are correction receipts, not a new full-Docker rerun. + +#### Step 3 review round 2 + +Fresh read-only GPT-6.1-sol xhigh security/lifecycle and GPT-6-astra xhigh +proof/corpus reviewers examined `d4c06a46..da637e35`. Neither found a Blocker or +Major. Security identified one operability gap: the safe startup refusal omitted +the configuration key/form required by the accepted completion criterion. The +fixed message now names `ConnectionStrings:OutboxDispatcher`, Npgsql key/value +syntax and `learnstack_outbox_admin`, without provider or supplied-value text. +The real-host negative theory asserts that guidance for missing configuration; +all four credential cases pass after the correction. Independent review reruns +passed 91 demo lifecycle cases, 11 focused outbox unit cases and two construction +host cases; the security reviewer separately passed nine helper/observation cases. +Both inspected the prior receipts and production paths. They did not claim a new +full build or Docker rerun. Step 3 is closed; Step 4 may add the complete +credential/publication/health censuses and close the packet. + +### P02b-2 Step 4 — Enforcement and closeout (2026-10-12) + +**Implementation and local closeout complete; both independent review rounds +passed.** Current CI/review/merge state belongs to the +[PR handoff](#p02b-2-pr-handoff-2026-10-12). +Steps 1–3 completed both independent review rounds; Step 3 is closed at `02540d0`. +Step 4 adds nonempty whole-production credential/publication censuses, exact +keyed factories and consumer bindings, and planted helper/delegate/async controls. +Only the processor constructs the task-owned publication attempt; its private +callback is the sole event-bus publication path. The existing canonical module +bus rule now also enforces that complete production fence. + +The five-subject observation graph follows async and production-owned +polymorphic contracts, rejects persistence/service-locator capabilities, and +inspects actual gauge callbacks. Actual DI controls reject missing/duplicate +workers/checks and wrong factories. Round 2 fixes at `606362b` pin exact credential +reader signatures, the external System clock and actual health/observation binding. +All 26 focused/corpus cases and both fresh fix reviews pass. +The literal-SQL census admits only exact producer enqueue, dispatcher +status-transition and migration backfill methods; quoted/schema/case/CTE and +missing/extra-writer controls prove its reach. These are bounded IL/literal-SQL +checks, not arbitrary reflection or dynamic-SQL dataflow analysis. + +**Verification before review:** the full Release solution build reports zero +warnings/errors, and solution-wide `dotnet format --verify-no-changes --no-restore` +passes. All 21 focused census/publication cases pass with zero skips, +including compiled actual production subjects and every planted control. Role +and Health catalogue rules are Implemented; Retry also names its canonical +architecture method. The source/catalogue recount is 193 architecture test +methods, 192 Implemented rules, 118 in that assembly and 74 elsewhere. + +The full Release backend regression passes 3,393 cases with zero failures/skips: +1,845 unit, 286 architecture, four contract, 175 Docker-free integration and +1,083 Docker integration. TRX counters were inspected directly; the nonempty-run +guard passes. The three additional case-insensitive credential-alias controls +also pass in the focused seven-case run. Step 3's corrected launcher/frontend +receipt remains the applicable local evidence: 91 lifecycle cases and 1,608 +frontend cases. These checks are not claimed as new Step 4 frontend reruns. +The full PR-range documentation check passes 2,555 relative links/459 fragments, +and all seven ADR-status script tests pass. Historical records and Accepted ADR +text remain preserved. All four implementation steps and both independent review +rounds are locally complete; post-fix verification is recorded below. The +[PR handoff](#p02b-2-pr-handoff-2026-10-12) owns current CI/review/merge state. + +P02b-3 still owns durable acceptance, shared inbox/ledger, independent subscriber +retries, both real default subscriptions and Seeder handoff. Required production +subscriptions remain Pending; test-owned Active contracts prove producer runtime +without claiming consumer business effects. + +#### Step 4 review round 1 + +Fresh read-only GPT-6-astra xhigh boundary and GPT-6.1-sol xhigh proof/corpus +reviewers examined `02540d05..d2531f2`. They reproduced three structural test gaps, +without finding a current production dispatcher defect. Captured key/provider +fields could be reassigned after their original capture; valid comment-separated +SQL and a later `TRUNCATE` target escaped the literal matcher; an additional +factory-based hosted worker escaped the descriptor type filter. + +The fixes close all three: captured-field mutations are restricted to the exact +factory parameter assignment, SQL recognizes those literal token separators and +all listed truncate targets, and the actual hosted descriptor set includes only +the singleton dispatcher and framework health publisher. Added dirty controls +cover key/provider writes in the factory, callback and helper, field/argument +address escapes and argument reassignment, SQL variants, and factory/instance +worker duplicates. No test method or catalogue count is added. All 21 focused +cases pass after the three corrections; the final seven boundary cases pass +again after the adjacent argument-mutation controls, with zero failures/skips. +The full regression above predates these test-only changes. The proof reviewer +independently passed 26 existing focused/corpus cases, with zero failures/skips; +neither reviewer claimed a new full suite. Round 2 remains pending. + +#### Step 4 review round 2 + +Fresh read-only GPT-6.1-sol xhigh boundary and GPT-6-astra xhigh proof reviewers +examined `02540d05..2f8693e`. They verified three test-guard gaps without finding +a current production defect. Named worker/store source-reader overloads could +self-authorize; an external `TimeProvider` subclass was invisible to the +production-owned contract graph and DI checks; a same-type health factory detached +from the singleton observation passed the returned-type check. + +The fixes are delivered at `606362b`: pin unique literal source-reader method +signatures, visibility and staticness with overload controls; require the actual +`TimeProvider.System` singleton instance with missing/duplicate/alternate-instance +and factory controls; and exercise the actual DI-registered health check through +Healthy → Unhealthy → Healthy against the singleton observation, with a detached +factory dirty control. The polymorphic graph covers production-owned contracts; +the external clock is admitted only through the explicit System-instance pin. +No test method, catalogue rule or published count is added. + +Post-round-1 verification at `2f8693e` passes the full 286-case architecture suite +and five Corpus cases; the Release build has zero warnings/errors. After the +round-2 fixes at `606362b`, all 26 focused/corpus cases pass with zero +failures/skips. Fresh GPT-6.1-sol xhigh boundary and GPT-6-astra xhigh observation +fix reviewers both approve with no remaining verified findings. The boundary +reviewer independently rejects both named-method overload plants (two offenders +each), observes zero clean/restored offenders and passes three focused Release +cases. The observation reviewer independently detects the SQL-capable external +clock and detached same-type health factory, observes zero restored graph +offenders and passes two focused Release cases. Neither claims a new full suite. + +The full post-fix Release build has zero warnings/errors, all 286 architecture +cases pass with zero failures/skips, and solution-wide format verification +passes. The final local documentation check passes 2,575 relative links and +479 fragments with zero errors. The 3,393-case regression above predates these +test-only guard fixes; its +TRX counters and the 26-case focused/corpus counters were checked directly. No +test method, catalogue rule or published count changes. All four P02b-2 +implementation steps and both independent review rounds are locally complete. +PR-head CI and merge remain pending; this closes producer dispatch/enforcement +without claiming any P02b-3 consumer delivery. + +### P02b-2 PR handoff (2026-10-12) + +[PR #30](https://github.com/HodeTech/LearnStack/pull/30) opens development → main +from local closeout `7bf14a0`. All four implementation steps and both independent +review rounds per step are complete. The PR's checks and current-head evidence +in its description own live CI state; its review and merge state remain on the +same PR. Earlier pending statements in dated local receipts are as-of records, +not the current check verdict. No merge is claimed by opening the PR. + +The seven existing required contexts and strict up-to-date protection were read +back from GitHub unchanged. Final verification must use the PR's actual current +head, not an earlier passing run. The PR description records run URLs and suite +counters after that verification. Five final local corpus checks pass with zero +failures/skips; this is not a CI result. + +P02b-3 is next after P02b-2 review/merge and its own decision pass: shared inbox +and delivery ledger, durable acceptance, independent subscriber retries/audit, +both real defaults subscriptions and Seeder handoff. No consumer delivery, +background-job or authentication completion is claimed here. + +### P02b-2 PR review follow-up (2026-10-13) + +All seven required jobs pass on PR head `a80e06d`, including the complete +3,393-case backend regression and 1,608 frontend cases, with zero failures/skips. +[Run 38306262165](https://github.com/HodeTech/LearnStack/actions/runs/38306262165) +also supplies 27 matching Lighthouse JSON/HTML report pairs and nine screenshots. +All reports have zero CLS, accessibility score 1 and normalized gzip JavaScript +between 106,359 and 106,553 bytes. Proof finishes in 646.454 seconds; owned process, +Compose, private-file, environment and lock cleanup all pass. These are receipts +for that head, not evidence for a later correction. + +Automated PR review identified a local-launcher validation defect: omitting both +a role's connection-string password and its selected password variable compared +two absent values as equal. Independent reproduction accepts that invalid state +for all four roles. Four new regression cases fail against the previous validator +and pass after requiring a nonempty configured string password. Existing quoted +password, whitespace and alias controls remain green; diagnostics remain fixed +and contain no supplied configuration. No runtime dispatcher or API contract +changes. + +Local verification passes 95 lifecycle cases and the guarded frontend suite's +1,612 cases (1,552 web and 60 SDK), with zero failures/skips/todos; lifecycle cases +are a subset, not an additional suite count. Workspace lint/typecheck pass. +Fresh sequential GPT-6.1-sol high and GPT-6-sol high correction reviewers both +approve `a80e06d..a851b7c` with no findings. Each independently reproduces the four +parent/current differences and passes all 95 lifecycle cases. Five Corpus cases +and seven ADR-status script tests also pass; the final link check covers 2,586 +relative links and 490 fragments with zero errors. Final correction-head CI +remains pending in this local receipt. +The [PR handoff](#p02b-2-pr-handoff-2026-10-12) continues to own live PR state. + +### P02b-2 external review remediation (2026-10-13) + +Both external reports against `44089707` were treated as review evidence and +checked against current code and Accepted ADR-0046. No new decision, consumer +delivery or grant change is part of this correction. Existing migrations and +Accepted ADR bodies remain unchanged. + +- Recovery now states its index predicate explicitly, without relying on + PostgreSQL to infer the lease CHECK. A new Platform migration replaces only + the recovery index: both expired leases and unleased exhausted rows retain + `(available_after, occurred_at, id)` order. Real migrated-database plans with + 50,000 Pending rows distinguish the predecessor's scan from indexed recovery; + admission exclusions, ordering and down/reapply are asserted. +- A failed durability probe after uncertain terminal COMMIT preserves both + exceptions, in COMMIT/probe order. The real response-dropping proxy exercises + that failure and independently verifies one durable terminal/audit pair and + no duplicate on retry. The unused persisted shutdown outcome was removed; + shutdown continues to leave ownership for expiry recovery. +- The launcher exposes only the exact fixed local database diagnostic, with + secret-bearing prefix/unknown-message controls. Absent configuration uses the + same diagnostic. Root runtime-script formatting is restored. The audit marker + count, transport-owned inbox wording, historical batch discussion, catalogue + proof kind, glossary and later-phase navigation now match implementation. +- The generic iteration diagnostic no longer mislabels every exception as a + storage failure. Normal dispatch avoids its unused registry lookup. Contention + warms both independent hosts before its live-lease deadline. Shutdown advances + exactly one controlled deadline with four retained callbacks; an isolated + second-budget mutant fails, and the rebuilt clean control passes. + +The remaining report suggestions were checked rather than adopted as new policy: + +| Concern | Disposition | +|---|---| +| Final `44089707` CI remains outstanding | Already resolved: all seven required jobs pass in [run 38309098697](https://github.com/HodeTech/LearnStack/actions/runs/38309098697). The earlier local receipt is dated evidence, not live state; this correction needs its own head verification | +| Failure metric precedes a successful fence; gauges may straddle a refresh | Metrics observe attempts, not durable transitions. Every gauge reads an immutable snapshot; no scrape-wide atomicity is promised. The phase criterion below now names that exact invariant | +| Disabled test worker leaves outbox health unhealthy | Intentional and now documented in factory remarks. The private check reports the absent worker; static `/healthz` remains liveness-only | +| Invalid options are reported as credential failures | Not on the shipped DI path: the store validates the shared options before worker construction | +| Alternate worker registration, duplicate short type labels, permissive terminal-request kind | No current production violation: composition census pins the sole worker; the registry has one production contract; the worker requests terminal state only from Normal claims. Recovery is deliberately used by a store fixture | +| Witness acquisition is not compared with audit metadata | SQL fences the actual token and returns it into the transaction-bound witness. The audit draft has no acquisition field; adding one is not required by ADR-0046 | +| Invalid causal metadata changes the original correlation | Matches ADR-0046: invalid correlation/causation/actor uses a validated attempt trace and omits invalid causal values | +| Role guard should reject other principals inheriting dispatcher rights | The guard validates the dispatcher's effective role and escalating memberships. Reverse grant auditing is outside that connection contract; changing it would not sandbox compromised privileged SQL | +| Ambient local credentials, migration-child environment, quoted passwords | Ambient overrides are explicit existing loader policy and tested. The administrative migration child is distinct from the confined web/Seeder children. Single/double-quote parsing is the declared closed local grammar, with existing controls; no provider mismatch was demonstrated | +| Audit seam needs duplicate tests in another file; sub-microsecond and census optimization suggestions | The real transition tests already exercise the fifth seam and rollback substitutions. Quantization has explicit envelope controls. Duplicate tests or census caching do not repair a demonstrated contract violation | +| ADR navigation date, test placement and optional trace descriptor | Historical ADR navigation is preserved; local-loader tests sit with that loader. Standard 09 and ADR-0046 allow optional trace data without requiring its persistence | + +Local validation passes 1,845 unit, 286 architecture, four contract and 175 +Docker-free integration cases, plus 97 focused Docker cases (54 store, 27 +migration, 16 worker), with zero failures/skips. Guarded frontend passes 1,616 +cases (1,556 web, 60 SDK), with zero failures/skips/todos; lint/typecheck pass. +Release build reports zero warnings/errors; format, seven ADR-status script +controls, 2,587 relative links and 491 fragments pass. Planner predecessor and +isolated second-budget mutant controls fail; clean counterparts pass. Both fresh +independent correction review +rounds and complete correction-head CI remain pending in this local receipt; +the PR description owns live head/check evidence. + +#### External correction review round 1 + +Fresh GPT-6-astra xhigh store/security and GPT-6.1-sol xhigh proof/corpus +reviewers approve `44089707..13cd632` without introduced findings. Independent +verification passes seven focused PostgreSQL cases and 99 lifecycle cases. +The PostgreSQL rerun uses the existing Release binaries after a whitespace-only +source correction; a fresh committed-source build and CI remain separate checks. + +The corpus reviewer finds a pre-existing adjacent source-comment contradiction: +`IIntegrationEventHandler` still requires handler-owned per-module inboxes. +Its remarks now name ADR-0046's transport-owned shared inbox and P02b-3 boundary. +The adjacent `IIntegrationEvent` remarks also stop promising unconditional +partition ordering or describing the implemented contract guard as Registered. +These are documentation corrections, with no interface or runtime change. + +#### External correction review round 2 and local closeout + +Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus +reviewers independently approve `44089707..41ac2924`, with zero findings across +all 29 changed files. Both read the complete correction and the first round's +source-comment fix. The runtime reviewer independently inspects the completed +TRX counters; neither repeats the root's complete suites or mutation experiment. +Both correction review rounds are complete. No Accepted ADR text, grant or +consumer-delivery contract changes in this remediation. + +Complete local backend verification passes 3,396 cases: 1,845 unit, 286 +architecture, four contract, 175 Docker-free integration and 1,086 Docker +integration, with zero failures/skips. The 97 focused Docker cases above are a +subset, not additional cases. Guarded frontend passes 1,616 cases (1,556 web, +60 SDK), with zero failures/skips/todos; lint/typecheck pass. A fresh Release +build of `41ac2924` reports zero warnings/errors after the source-comment and +whitespace corrections. Five corpus controls, seven ADR-status script controls, +2,693 relative links and 500 fragments pass; historical P02b-0/P02b-1 records +and Accepted ADR text remain preserved. + +Correction-head PR CI and its real demo artifacts still require independent +verification after publication. This local receipt does not reuse the earlier +green head as evidence; the PR description owns live head/check evidence. + +### P02b-2 review of 3531a2eb (2026-10-13) + +The next external report was checked against `3531a2eb`, not adopted as an +instruction source. That baseline's seven required jobs and complete demo +artifacts pass in [run 38318773974](https://github.com/HodeTech/LearnStack/actions/runs/38318773974). +This follow-up requires its own review and CI evidence. No Accepted ADR body, +migration, grant, consumer-delivery contract or dependency changes here. + +- The earlier reverse-membership disposition is reconsidered using a real + direct/transitive `SET ROLE` control. The app guard already rejects elevated + memberships on new app connections; an administrator's later grant can still + elevate an existing app session. The dispatcher now detects incoming grants + on its next physical connection, enforcing the existing four-role boundary. + Superusers are excluded from that predicate because PostgreSQL implicitly + treats them as members of every role. This is grant-drift detection, not + continuous revocation. Four sync/async direct/transitive cases prove actual + escalation, refusal and healthy reconnection after restoration. An isolated + PostgreSQL comparison distinguishes the predecessor and corrected predicates. +- Credential census now rejects explicit configuration indexers with a + same-body `ConnectionStrings:` key/prefix, including compiled concatenation, + interpolation, formatting and static-readonly names. Unrelated configuration, + dictionary indexers and diagnostic text remain clean. This bounded check + does not claim arbitrary cross-method key dataflow. A separate planted control + closes `Assembly.CreateInstance`; `Activator.CreateInstanceFrom` was already + covered. Both omissions were reproduced against the predecessor detector. +- The constraint/RLS statement, shared-inbox and fifth-writer statuses, settled + ordering pointers and catalogue proof references now match current code. + Skills use a shipped public assembly marker in explicitly abridged examples. + The architecture method count is 194; Implemented rule count remains 192. +- Publication tests now cover successful/throwing completion, cleanup and + repeated/late cancellation. Wrong-kind store calls must leave the actual row + and audit unchanged. Test shutdown and publish timeouts use distinct values. + A source comment explains exact Npgsql microsecond truncation; the local API + environment comment names all three forwarded credentials. + +The remaining claims were checked against their actual scope: + +| Concern | Disposition | +|---|---| +| Startup options failure is reported as a credential error | Not on the shipped DI path: `OutboxDispatchStore` validates the same options before worker construction or source resolution | +| Broaden COMMIT catch to cure sticky terminal health | No demonstrated shipped exception escapes the existing provider/network/cancellation set. The dispatcher configures no custom driver logger. Failed reconciliation remains an unknown outcome even with catch-all; conservative health clears after successful terminalization | +| Non-admitted Normal claim hot-loops | Immutable registry and SQL exclude Pending identities before acquisition; unknown/retired/invalid rows already request terminalization. No current path reaches that invariant arm | +| Reject every unmapped JSON member | ADR-0046 explicitly uses the frozen payload options and compares declared facts; producer contracts enforce identifier-only fields. Unknown fields are not passed to the handler. A new stored-wire rejection policy is not inferred from this suggestion | +| Producer witness kind/subscription should anticipate subscriber minting | The current closed minting census admits only the producer store. P02b-3 owns a distinct subscriber capability and its identity controls; no subscriber factory is introduced early | +| Legacy-row diagnostics, blocking migration and attempt constants | Invalid facts deliberately refuse migration. Existing migrations remain immutable; checks/index creation need an owner maintenance window, with no online-migration claim. Tests pin six claims and the full backoff/DDL state; copying a new constant into historical migrations would not eliminate drift | +| UTF-8 SQL literals escape the literal census | Npgsql's command entrypoints accept strings. Decoding bytes is dynamic construction/dataflow outside this explicitly bounded literal census; raw byte data alone is not an executable SQL call | +| Platform credential rule is no longer independently sufficient | The whole-production credential/factory/consumer census independently pins both exact roots and their distinct sources. Repeating it inside the companion source rule adds no uncovered current boundary | +| COMMIT/probe stack assertions are redundant | Both failures are `NpgsqlException`; the stage-specific stack assertions distinguish their order. They supplement the physical outcome/no-duplicate proof and currently pass with the pinned driver | +| Ambient public-api overrides and seed validation should cover four credentials | Explicit ambient API overrides are an existing tested local-loader policy. Standalone seed consumes only Default and Migration; other ambient credentials never reach its child. Shared demo validates all four before startup | +| Forward proxy/cache/home environment into Seeder | The narrow child allowlist deliberately excludes ambient credentials/diagnostics; proxy values can themselves contain credentials. No failure on the documented restored-dependency path was demonstrated; the API's separate allowlist intentionally excludes `DOTNET_CLI_HOME` | +| Print the failed connection-string suffix | The fixed diagnostic is now safely visible. More detailed refusal messages are optional; values remain excluded and no further operational regression was reproduced | +| Ingress env tests depend on file order | Each loader test writes its own selected file before reading it; they are sequential, not concurrent. The later configuration test uses an explicit object, not that file | +| Duplicated construction-only factory helper | The remarks explain the intentionally absent worker/unhealthy private check. Sharing helpers across separate test assemblies would add a dependency without correcting behaviour | +| Skill index claims handler-owned inbox | Not reproduced: its generic inventory names an inbox guard but assigns no handler ownership; detailed skills now identify the shipped/P02b-3 boundary | +| Persist traceparent or measure recovery/terminal as publication duration | Trace persistence is optional. The duration histogram measures publication; recovery and terminal transitions do not publish and retain their own spans/outcomes | +| Retained partition also delays terminal acquisition | Deliberate local ownership: no further acquisition for that partition until callback and scope cleanup actually finish, including terminal work; ADR-0046's four-overrun saturation applies | +| Assembly-qualified identities, closed generics and invalid disposition label | Exact assembly-qualified identity plus explicit compatible aliases is Accepted. A declared closed generic is a concrete known type, not arbitrary loading. Invalid-envelope reason and the fixed `invalid` label remain distinct from unknown-type reason | +| Legacy non-NULL metadata should be backfilled | ADR-0057 requires new producer metadata to be SQL NULL; ADR-0046 deliberately terminalizes invalid legacy envelopes rather than silently rewriting their facts | +| Alternate health-registration dedupe and audit trigger | The sole production composition is pinned. A new trigger/privilege design is Phase 11 work, not an unreviewed replacement for the Accepted row-bound terminal seam | +| Squash migrations or mechanically gate published fragment counts | Existing migrations/history are preserved. Link/fragment totals are explicitly local checks, not CI enforcement claims; the prior and current source scans remain separate evidence | + +Local Release build reports zero warnings/errors; format verification passes. +Unit passes 1,847, architecture 287, contract four and Docker-free integration +175 cases, all with zero failures/skips. Twenty role controls and six focused +claim-kind/shutdown cases pass. The new compiled-probe helper's initial deferred +Cecil-body failure was corrected before the successful full architecture rerun; +the guard expectation was preserved. Seven ADR-status controls, 2,711 relative +links and 505 fragments pass. Historical delivery records and Accepted ADR text +remain unchanged. Complete Docker validation, both fresh independent review +rounds and correction-head CI remain pending in this initial local receipt; +the PR description owns final head/check evidence. + +#### Review of 3531a2eb: verification closeout + +Both fresh independent review rounds approve `3531a2eb..a5b1e723` with zero +findings across all 17 changed files. Each round uses a fresh GPT-6-astra xhigh +security/runtime reviewer and GPT-6.1-sol xhigh proof/corpus reviewer. All review +lenses were covered. Reviewers inspect source and TRX evidence without repeating +the root's full suites; the second proof reviewer independently confirms 194 +architecture methods, 192 Implemented rules and all 13 explicit method links. +No further runtime correction was required after the implementation commit. + +Complete local backend verification passes 3,408 cases: 1,847 unit, 287 +architecture, four contract, 175 Docker-free integration and 1,095 Docker +integration, with zero failures/skips. The 20 role and six focused claim-kind/ +shutdown cases are subsets of Docker integration, not additional cases. Release +build, format, seven ADR-status controls and the 2,711-link/505-fragment local +check pass. Historical delivery records and Accepted ADR text remain preserved. +No frontend source or dependency changed in this correction; the next real CI +run re-verifies frontend and demo artifacts along with the corrected backend. + +Both correction rounds and local validation are complete. Exact correction-head +CI remains pending in this local receipt; the PR description owns live checks +and artifact-backed evidence after publication. + +#### Snapshot interval correction (2026-10-13) + +The dispatch loop no longer forces a full queue snapshot after every successful +claim. It checks `SnapshotInterval` after completed iterations, while `didWork` +still controls idle polling. A controlled monotonic-clock integration case +dispatches three real rows: the initial snapshot survives successful work and +the last tick before the interval; the exact boundary refreshes it after the +next completed dispatch. Release build reports zero warnings/errors; format, +1,847 unit, 287 architecture and all 17 worker integration cases pass, with zero +failures/skips. Two fresh sequential independent reviews of `3620b421..3baf3a22` +approve with no findings. In an isolated tracked-source copy, reverting only the +production call to forced refresh makes the new case fail its retained-snapshot +assertion (one executed, one failed); the corrected case passes. New-head CI +remains pending in this local receipt; the PR description owns live checks and +artifact-backed evidence after publication. + +### P02b-2 merge and closeout (2026-10-13) + +The maintainer merged [PR #30](https://github.com/HodeTech/LearnStack/pull/30) at +2026-10-13 07:43:06 UTC. GitHub records final PR source +`4b4e3e40cf9147262934652c4eb9621258356f4c` and squash merge +`6a277770e46a7f4ea3574d9d6891d1802cb8fa90`, whose parent is previous main +`b1f6f21cab556ee7ba497dfc0d64e51b8cf1dad8`. Source and squash merge have the +identical tree `c3d02e3368365a108cb8321ccb3fcbc9cec2e575`. Development incorporates +the main merge without switching branches or rewriting published history. + +All seven required checks pass in the +[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38358520310) +for that source; CodeRabbit also reports success. The tested synthetic merge is +`d347a60a36fc0001656c3d95d7551bc35d818b91`. Verified artifacts record: + +- **3,409 backend passes**, zero failures/skips: 1,847 unit, 287 architecture, + four contract, 175 Docker-free integration and 1,096 Docker integration cases. + The snapshot-interval regression passes on that exact source. +- **1,616 guarded frontend passes**: 1,556 web and 60 SDK, zero + failures/skips/todos; frontend lint, typecheck and builds also pass. +- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, nine + screenshots and matching source/checkout identities and report digests. + Automated accessibility is 1 throughout, CLS is 0 and normalized initial JS + gzip is 106,357–106,552 bytes. Proof finishes in 631.094 seconds and owned + cleanup passes; timing medians remain advisory. +- OpenAPI base/head specifications are byte-identical, with SHA-256 + `69333252a95d4179e319512e5f45db2781d12eb003d405a509fa047d64e8e012`. + +These are final PR-head results, not a claim about a new post-merge or local +full-stack run. **P02b-2 is closed.** All four steps and verified review fixes +are delivered, including recovery-index alignment, credential confinement, +terminal COMMIT reconciliation and interval-bound observation. Two independent +review rounds per step and correction bundle remain recorded above. Earlier +dated receipts retain their pre-merge wording; all Accepted ADR files remain +unchanged by this closeout. Phase 02b remains in progress. + +**Next: P02b-3 decision pass.** Reverify the Accepted G1/G6/G7 subscriber +contract and G19 handoff against the merged code, then plan delivery and its +proofs before implementation. P02b-3 owns durable acceptance, shared inbox and +independent delivery ledger, subscriber retries/terminal MUST audit, targeted +internal replay, both real Customization defaults subscriptions and semantic +key/version Seeder handoff. The effects remain `card@1` content type and +`plain@1` taxonomy, preserving existing authored/lifecycle state. Required +production subscriptions remain Pending until that boundary is implemented; +producer dispatch does not claim durable consumer effects. + +Background jobs, API authentication, realm reconciliation, BFF sessions and +phase-exit enforcement remain P02b-4–8 in the +[packet table](phase-02b-events-auth.md#packets-and-decision-gates). Operator recovery permissions/routes +remain Phase 03; broker adapters and production readiness remain Phase 11 on +their recorded triggers. This closeout starts no later packet and makes no new +architectural decision. + +**Documentation-only closeout validation.** Five local Release corpus controls +and seven ADR lifecycle/workflow controls pass, zero failures/skips. The 14 +changed Markdown files resolve 1,577 relative links and 333 fragments without +errors; added prose wrapping and whitespace checks pass. All prior P02b +delivery/review receipts and every ADR file are byte-preserved. Runtime suites +are not rerun locally for this documentation-only change; the final PR artifacts +above supply their evidence. + +## P02b-3 — Consumer + +### P02b-3 decision package (2026-10-13) + +**Accepted — 2026-10-13, @cemil.** The maintainer approves the complete package +and six implementation steps, each with commit and two independent review rounds. +Acceptance precedes runtime implementation; it claims no delivered subscriber. +The audit baseline is `development` at +`652004290c9696e65e68817f223839d4a0f02137`, after PR #30's verified merge. +Three independent read-only audits covered the accepted contracts, storage/ +privilege/owner lifecycle, and Customization/Seeder convergence. Their findings +were checked against current source; they report inspection, not passing tests. + +[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) +already accepts G1/G6/G7's shared transport-owned inbox, stable subscriptions, +durable acceptance, independent retries, atomic terminal audit and targeted +internal replay. [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) +accepts both create-only default effects and the Seeder handoff. This package +concretizes the storage, runtime and enforcement details those records assign to +P02b-3. It does not reopen their decisions or authorize jobs/authentication. + +#### Document and code review + +The review follows the roadmap entry reading, then ADR-0003/0006/0010/0017/0023/ +0033/0036/0038/0040/0042/0043/0044/0046/0057, applicable Backend, Database, +Testing, Observability, Security, Documentation, Audit, Infrastructure and +Architecture-test standards, architecture 03/09/10/15/29/31/32, the Tenancy/ +Customization/Audit specs and matrices, and event/seed/migration/test skills. +The actual producer, bus, registry, transaction/audit coordinators, terminal +witness/store, Customization writers/readers and Seeder are the implementation +premises. Acceptance history remains the authority for any proposed ADR erratum. + +| Verified premise | Required P02b-3 action | +|---|---| +| `InProcessEventBus` invokes and constructs handlers immediately; it owns no durable acceptance or inbox | Replace that publication outcome with durable acceptance; execute only through the independent delivery owner | +| `OutboxEventRegistry` owns stable IDs/readiness; the handler registry carries only concrete handler metadata | Preserve one manifest identity source; bind each Active ID to exactly its declared contract and handler | +| Common owner completion drains events, writes MUST audit and commits without a delivery completion participant | Add a closed delivery-specific final fence/gate while preserving request ownership and all existing announcement methods | +| `EventTerminalTransition` and the fifth audit seam accept only producer terminalization | Extend the restricted actual-row witness and operation census to the subscriber terminal writer | +| Customization's current readers exclude deleted rows and discover by ID or Active key | Add owner-local, tenant-protected concept history across every revision/status, including soft deletion | +| Register uniqueness protects one revision, not concurrent initialization versus another revision | Serialize initialization and concept registration on the same transaction-owned semantic key | +| Seeder requires fixed built-in IDs; its counts assume separate register/publish acts | Resolve built-ins semantically, preserve warm IDs, share initialization, and update inventory/fixtures without weakening authored-ID checks | +| Direct delivery production has no incoming-event causation source | Carry a trusted delivery entry through nested producer frames; keep tenant/org authority in the announcement | +| Existing aggregate/audit request censuses omit integration handlers | Add nonempty production-consumer coverage and planted violations before marking consumer rules Implemented | +| Existing bus logs raw exceptions and adds exception details to spans | Replace transport-owned diagnostics with bounded codes before enabling production subscriptions | + +These gaps are expected P02b-3 work; they are not retroactive P02b-2 failures. +Required production manifests stay Pending until acceptance, execution and Seeder +handoff are ready together. Test-owned Active contracts exercise earlier steps. + +#### Accepted storage and authority details + +1. **Two shared infrastructure tables.** `event_deliveries` retains one copy of + the validated producer envelope per `(tenant_id, subscription_id, event_id)`. + `inbox_messages` holds the completion identity for that same tuple, with no + surrogate UUID. Neither depends on a live producer row. A producer purge + cannot remove a pending delivery's payload. No third dead-letter store/topic + or arbitrary metadata is added. Retained copies and their retention dependency + enter the P02b-8 inventory; actual purging remains Phase 11. +2. **RLS and classes.** The ledger is tenant-owned and organization-scoped because + its envelope carries organization metadata and payload. Use the canonical + tenant-and-organization policy, ENABLE and FORCE, with explicit WITH CHECK. + The inbox is tenant-wide identity machinery with no payload/org authority. + Both use explicit tenant predicates in application SQL. No foreign key to + `outbox_messages` or cascade from business tables controls retention. The + executor restores the stored organization before reading the envelope; + an unmarked event never widens a present organization to null. +3. **Closed grant budget.** `learnstack_app` receives RLS-protected acceptance + INSERT/SELECT and only the ledger completion-column UPDATE. Inbox claim is an + INSERT of an immutable completion marker inside the uncommitted business + transaction; uniqueness serializes duplicates before construction. Only owner + success makes that marker durable; rollback removes it. Its timestamp records + the claim; ledger completion records business completion. Successful app-role + completion retains token/expiry as inert provenance because it cannot UPDATE + those fields. Completed rows are excluded from acquisition, recovery, + terminalization and replay. The bypass scheduler + receives column SELECT for tenant/subscription/event identity, organization, + declared type/topic/partition, occurrence, attempts, availability, lease, + completion, terminal/replay state and bounded diagnostics; UPDATE covers only + scheduling/status columns. It receives no payload or causal-envelope SELECT, + no ledger INSERT/DELETE and no inbox privilege. Application INSERT grants name + acceptance columns only, excluding caller-supplied scheduling/terminal state. + The existing Audit-chain + INSERT-only grant is reused; no fifth role or business-table grant is added. +4. **Canonical detail before code.** Standards 05 owns complete DDL, constraints, + exact column grants and matching pending/recovery/terminal indexes. A new + Platform-chain migration implements it; historical migrations stay intact. + Identity, subscription grammar, nonnegative attempts, lease pairing, + mutually exclusive completion/terminal state and the 256-byte error cap have + CHECKs. Completion and terminal UPDATE predicates match the actual grants; + tests run them as the real roles, not merely inspect grant text. No P3 role + purges these stores; Phase 11 must decide the minimal retention grants and + ordering before installing its purger. +5. **Accepted envelope is immutable.** Publication validates the envelope and + Active manifest, restores its scope, and inserts every required delivery in + one app-role acceptance transaction without constructing business handlers. + An existing identical identity/envelope is idempotent; a conflicting envelope + refuses acceptance without overwriting the first copy. Canonical serialized + data, including organization and causal metadata, determines equality, not + raw `jsonb` whitespace. An existing accepted subset can be completed safely. + An uncertain acceptance COMMIT leaves the producer retryable; subscriber + execution failures never flow back into the producer's retry budget. + +Scoped application completion is a constrained call path, not a claim that column +grants sandbox arbitrary compromised app SQL. Likewise, the terminal audit's +tenant binding is the row witness, not BYPASSRLS GUCs. No tenant-status lookup is +added as an asynchronous hold/drop policy; Phase 02c retains that decision. + +#### Accepted execution, retries and replay + +Each attempt owns a fresh app-role scope. Announce the validated routing tenant/ +organization before resolving a module context, read and revalidate the retained +envelope by its claimed identity/token under RLS, then claim the inbox before +handler construction. Completed duplicates skip construction. Effective actor is +SystemActor; original causal actor and incoming EventId remain trusted producer +metadata. Ordinary execution refuses privileged subscriptions. Phase 03's +erasure execution contract remains separate. + +The outer audit coordinator classifies the declared handler before construction; +nested commands retain their own classified intents. No module writes audit SQL. +The common transaction owner drains domain events, writes pending MUST audit, +performs the delivery completion UPDATE with tuple/token/unexpired database lease, +and atomically admits physical COMMIT against a sticky completion gate. A failed +fence or a gate closed by cancellation poisons and rolls back all work. The gate +arbitrates Open -> Closed versus Open -> Committing; cancellation after commit +admission is an unknown/Indeterminate outcome, not guaranteed rollback. Durable +inbox/ledger state decides recovery, including an uncertain sixth-attempt COMMIT. +This adds no IUnitOfWork session setter, retargeting or independent business commit. + +| Policy | Accepted initial bound | +|---|---| +| Host and acquisition | API-owned subscriber worker; one just-in-time normal claim; reuse the confined keyed dispatcher source | +| Normal claims | Six per subscription/event, including claims whose execution outcome is unknown | +| Five retry delays | 1 s, 5 s, 30 s, 5 min, 1 h, using database availability time | +| SQL / terminal transaction | 5 s | +| Complete execution wait | 10 s, including construction, handler and owned cleanup; timeout closes the commit gate | +| Lease | 30 s, with validated execution/transition margin; no renewal promise | +| Idle poll / snapshot interval | 200 ms / 5 s; successful work does not force a scan | +| Progress / stale health | 45 s | +| Cancellation-ignoring work | At most four retained tasks; block their local partition, unhealthy while retained, stop acquisition at capacity | +| Shutdown | One total 30 s wait; live task resources remain owned until actual completion or process exit | + +The worker retains and observes cancellation-ignoring tasks with their live scope; +it does not dispose a running callback or promise managed-code termination. +This is one additional in-process subscriber worker in the existing API host; +it neither creates a new host nor changes the producer's existing bounds. Its +four-task and 30 s bounds apply to this worker, not an added whole-host shutdown +guarantee. All stop waits also observe the host's shared shutdown cancellation. +If scope disposal faults or times out after acknowledged business COMMIT, the +completed ledger/inbox remain definitive; cleanup cannot undo or rerun that +effect. Unknown completion reconciles durable state. Overrunning cleanup remains +task-owned and consumes capacity until actual disposal finishes. +Recovery replaces expired ownership before transitions and spends no additional +attempt. Ordinary failed/unknown outcomes use independent backoff. Expired claim +six requests terminalization without a seventh invocation. Requests for terminal +state are never normal execution candidates. Audit refusal retries terminalization +alone. Closed reasons distinguish invalid envelope/subscription from exhaustion; +descriptors expose bounded stage/category codes, never raw exception text. + +Subscriber terminalization uses the same fifth audit seam and a subscriber witness +minted only from its successful fenced UPDATE result. It binds actual tuple, +organization, token, attempts, reason and live connection/transaction. The +Tenancy catalogue/matrix registers `platform.delivery.dead_letter` as off-path +MUST/SecurityEvent when this writer ships. Subscriber terminal audit uses the +validated attempt trace and bounded event/subscription/reason/attempt metadata; +it does not grant the bypass scheduler causal-envelope or payload access merely +to reuse the producer witness. Business execution retains original causality. + +Internal replay takes exactly one declared tenant/subscription/event tuple. It +admits an Active ordinary subscription and completed terminal ledger row only; +live claims, pending terminalization, unknown/retired/Pending subscriptions and +completed business deliveries are refused. The fenced reset clears that row's +terminal request/timestamp, attempts and bounded error, makes it due and invalidates +old ownership. It never deletes/resets an inbox or republishes a broadcast. +The scheduler later invokes only that subscription. A completed inbox still +short-circuits business construction if an earlier uncertain attempt committed. +No replay HTTP route, permission grant or operator producer reset ships here. + +Standards 10 owns subscriber metric names/dimensions and the registered, unmapped +health check. Keep no tenant/event/partition/trace labels; subscription/event-type +labels are finite declared-registry values only. Snapshot gauges perform no SQL; +refresh failure preserves the prior snapshot and reports stale/unhealthy state. +Producer and subscriber attempt/failure/terminal/dedup signals remain distinct. +The API's `/healthz` and anonymous public contract remain unchanged. + +#### Accepted defaults and Seeder handoff + +The two stable identities remain +`customization.initialize-content-type-default.v1` (`card@1` content type) and +`customization.initialize-taxonomy-default.v1` (`plain@1` level taxonomy). +Each effect owns exactly one root. New roots are validated, created and made +Active in one transaction/save, with a Customization-owned UUIDv7, one generation +increment and one classified initialization MUST audit. Shared owner-local +initialization commands let the Seeder use the same logic without a worker, +dispatcher credential, raw SQL or new tenant-context setter. Event handlers +coordinate only their own effect through those commands; they do not combine roots. + +A transaction-owned semantic concept lock serializes each initializer with the +ordinary registration writers for `(tenant, aggregate-kind, key)`. Under that +lock, any revision in Draft/Active/Deprecated or soft-deleted history means +preserve, not initialize. A successor-only concept also counts as touched. +Whichever writer commits first defines whether the concept was untouched; +initialization never overwrites, republishes, revives or fills a missing revision +of an already touched concept. Parameterized owner-local history reads retain +explicit tenant predicates and RLS; no query-filter bypass is introduced. +Same-key locks do not create a cross-tenant authority path. + +The initialization operation classifies preserved/no-op attempts explicitly; +it changes no root or generation. A new delivery may record an initialization +attempt without entity changes; a completed duplicate constructs no handler and +creates no second business audit. Seeder pre-verifies completed built-ins before +sending an initializer, so a completed rerun remains write/audit-neutral. +Fresh inventory counts reflect one initialization audit/bump per built-in, +not the old two register/publish acts. That is the uncontended creation count; +separately classified preserved attempts after a seed/delivery race may add an +audit without a generation bump. Tests distinguish creation from no-op attempts, +and count the actual deduplicated delivery identities rather than asserting that +every asynchronous interleaving has the Seeder-only audit total. Historical +receipts are not recounted. + +Built-in Seeder verification discovers semantic key/version, then validates exact +Active state and built-in shape while retaining the stored ID. Existing matching +non-demo IDs pass. Preserved Draft, deprecated, deleted, successor-only or +mismatched definitions remain untouched; if they cannot satisfy the declared +demo inventory, seeding refuses with a bounded mismatch instead of claiming +completion. Tenant-authored definitions/courses/lessons retain exact declared +IDs and exact pins. Consumer and fresh Seeder races converge in both winning +orders; an unexpected database failure is not a blind retry/overwrite. + +#### Decision vehicles and documentation actions + +No new architecture decision is proposed: these details fit ADR-0046/0057's +explicitly delegated P02b-3 boundary. If implementation disproves that fit, stop +and prepare a new decision for maintainer review before changing the contract. +Acceptance of this package authorizes the following already-required changes, +with original Accepted bodies/metadata and historical receipts preserved: + +- **ADR-0023:** verify the inbox minting-list wording at its acceptance commit; + add the ADR-0041 inline erratum and its own dated amendment, because inbox + identity reuses the producer EventId rather than minting a surrogate. This + corrects the listed table, not the UUIDv7 decision. +- **ADR-0044:** append the additive capture-exclusion clarification for the + shared inbox and delivery ledger; add subscriber fifth-seam/operation navigation + already authorized by ADR-0046. Explicit business intents remain audited. +- **ADR-0046/0038/0057:** dated delivery/navigation notes when their P3 obligations + actually ship; no premature completion claim or replacement of earlier bodies. +- **Mutable carriers:** canonical Inbox/ledger DDL and grant matrix in Standards + 05; lifecycle/diagnostics/audit rules in 02/09/10/11/18/20; canonical tests in 21; + architecture 03/09/10/15/29/31/32; glossary; module specs/matrices; event/seed/test + skills; Seeder inventory/fixtures and `BuiltInCustomizations` creator remarks. + Reconcile only touched claims; do not duplicate an ADR or RLS template. +- **Hub pointer:** verify the sibling repository's per-module inbox dependency + and coordinate its documentation pointer before P3 closeout, as ADR-0046 requires. + The current sibling `docs/roadmap/README.md` P02c-3 row still names per-module + inbox tables; replace only that dependency with a link to ADR-0046's shared + transport-owned inbox contract when coordinating the documentation change. + No Hub runtime, HTTPS contract or branch change is authorized by this package. + +At acceptance, Standards 21 registers the following additional canonical rules +as Registered, with their behavioural/structural owners; no passing enforcement +is claimed before code: + +- `Integration_Event_Publication_Is_Durable_Acceptance` — real-role acceptance, + immutable duplicate/collision handling, partial/unknown COMMIT and no construction. +- `Delivery_Retries_And_Replay_Are_Subscription_Scoped` — independent budgets, + terminalization, completion gates, final-claim recovery and targeted replay. +- `Delivery_Terminal_Audit_Identity_Is_Row_Bound` — restricted subscriber witness + census and atomic matching/mismatched identity/transaction proofs. +- `Delivery_Execution_And_Observation_Are_Bounded` — actual hosted execution, + retained resources, shutdown, closed diagnostics and snapshot/health emitters. +- `Customization_Default_Initialization_Preserves_Touched_Concepts` — one-root + useful creation, all lifecycle preservation and serialized registration races. +- `Seeder_BuiltIns_Use_Semantic_Identity` — generated/warm IDs, exact shape and + authored IDs, no-worker operation, rerun neutrality and real delivery races. + +Extend the existing `Integration_Event_Handlers_Use_InboxGuard` and +`Integration_Event_Handler_Restores_Tenant_Context` obligations rather than +inventing alternate names for their claim/owner/scope assertions. Extend the +existing credential confinement census only for the named subscriber scheduler/ +store; business handlers and application execution never receive bypass access. + +#### Six accepted implementation steps + +Each step commits on `development`, then completes two fresh independent review +rounds. Verify findings against current code, fix valid findings, validate and +commit fixes before the next round/step. A clean review needs no empty commit. +Continue automatically unless a real blocker or new maintainer decision arises. + +1. **Accepted detail, schema and privileges.** Record approval before runtime; + register canonical proof obligations, reconcile the named ADR instruments, + implement Platform migration/table classes/RLS/grants/indexes and test + forward/down/reapply, actual role permissions and tenant/org isolation. + Production subscriptions remain Pending. +2. **Durable acceptance and inbox primitives.** Replace immediate broadcast + execution with validated transactional acceptance; implement immutable envelope + collision/duplicate semantics and transport-owned inbox claims. Prove partial + and uncertain acceptance, independent identities, concurrent duplicates and + construction-free publication with real PostgreSQL. +3. **Business owner and completion gate.** Implement fresh application scopes, + restoration before resolution, classification, incoming-event causation, + common owner completion and sticky commit arbitration. Prove business/inbox/ + outbox/MUST-audit/ledger atomicity, canceled/expired/stale attempts, no-listener + metadata, owner cleanup and unknown COMMIT without activating production defaults. +4. **Subscriber scheduling, terminalization and replay.** Implement independent + leases/attempts/recovery, witnessed terminal MUST audit, targeted reset, bounded + task ownership, minimal diagnostics and snapshot health/metrics. Prove sibling + independence, sixth-claim recovery, late completion, audit rollback, identity + substitutions, safe shutdown and replay fences using the actual worker. +5. **Useful consumers and convergent seed.** Add the two one-root initializers, + concept serialization/history reads and semantic verification; migrate Seeder + and fixtures, then activate both real subscriptions together. Prove untouched + creation, every preservation lifecycle, warm IDs, strict authored pins, repeated + seeding and concurrent fresh seed/delivery in both winning orders. +6. **Enforcement and PR closeout.** Complete production-handler/call-path censuses + with planted clean/dirty controls, full Release build/format/backend regression, + affected frontend/launcher tests and real demo/Lighthouse proof. Reconcile all + current-state docs and accurate test counts; open the PR only after every step + and both reviews finish. Verify all seven required CI checks at the exact head; + never claim merge or delivery of P02b-4–8. + +#### Decisive acceptance proofs + +- Actual app-role tenant/org isolation and real bypass column grants: scheduler + payload/inbox reads and app retry/reset writes fail; allowed acceptance and + completion succeed. Completed inbox rows persist across replay and producer purge. +- Two same-module subscriptions and concurrent duplicates yield one business + effect each. A duplicate waits for the first transaction; rollback permits a + new claim. Handler construction failure is independent of acceptance success. +- Fenced ledger completion, business changes, produced events and MUST audit all + roll back on a stale/expired token or closed gate. Kill the fence/gate in a + controlled mutant to prove sensitivity, including timeout persistence failure + followed by an ignored-token late callback. +- Real lost-COMMIT acknowledgement recovery, including the final subscriber + claim, does not repeat committed business work or terminal audit. Cancellation + after commit admission never claims certain rollback. Postcommit disposal fault + and timeout controls retain durable completion, prevent effect replay and keep + live cleanup resources safely owned. +- Subscriber terminal draft tenant/org/event/subscription/operation/transaction + substitution rolls back both transition and audit; matching org-scoped work + commits. Audit refusal never makes terminal-requested work executable again. +- Targeted replay changes one terminal row only; completed sibling/inbox rows + and producer attempts stay unchanged. Stale pre-replay callbacks cannot complete. +- Nonempty production censuses cover every module layer and the actual handler, + manifest, owner, inbox, terminal-witness and credential sites. Planted direct/ + interface/helper bypasses and clean controls distinguish enforcement from an + empty or narrowed subject set. Extend one-root and audit-registration coverage + to integration handlers; do not only count request handlers. +- Logs/spans/descriptors/artifacts reject planted payload, secret, raw type and + exception values. Finite telemetry labels, prior-snapshot retention, exact + refresh cadence and no SQL gauge callbacks have positive/negative controls. +- Runtime proof includes actual TenantCreated backlog activation, both defaults, + ordinary app-role isolation and warm/fresh Seeder races. Test-only subscribers + alone cannot close the packet's useful-flow requirement. + +#### Decision-package reviews and validation + +Two fresh, sequential, read-only reviews examined the proposed working-tree +package against baseline `65200429` and the current accepted contracts/code: + +- **Round 1 — GPT-6-astra, high:** Approve, no Blocker/Major. Clarifications for + postcommit disposal, inert completed-row lease provenance and creation/no-op + audit counts were verified and incorporated before round 2. +- **Round 2 — GPT-6.1-sol, high:** Approve, no Blocker/Major/Minor. Independently + checked the completion/grant model, defaults/Seeder policy and ADR-0023's + acceptance-time natural inbox identity. It found no additional decision gap. + +Root validation passes all five `CorpusConsistencyTests` and seven ADR-status +controls, with zero failures/skips. The changed phase document has 184 checked +relative links and 98 fragments, with no missing targets/anchors. Added prose +passes the 88-column check with documented link/table exceptions; whitespace is +clean. Every Accepted ADR and all earlier P02b delivery/review receipts remain +byte-preserved. This is documentation validation, not a P02b-3 runtime test run. +The package remains Proposed until explicit maintainer approval; that approval +and the registered obligations precede the first runtime implementation commit. + +#### Maintainer acceptance (2026-10-13) + +The maintainer's explicit answer, "Paketi onaylıyorum; implementasyona geç", +accepts this package after both decision-package reviews. Their preceding receipt +records the pre-approval state. The six steps and two-round loop are authorized +on development. G1/G6/G7/G19 keep their accepted architectural answers; concrete +storage, authority, execution/replay, default and Seeder details now have this +accepted vehicle. Catalogue additions remain Registered until their proofs ship. +The decision acceptance, ADR-0023 erratum and ADR-0044 capture clarification are +committed before the first P02b-3 runtime change. + +### P02b-3 Step 1 — shared storage and privileges (2026-10-13) + +**Complete; both independent review rounds complete.** Decision acceptance +`63363ac` precedes this runtime change. EF generated Platform migration +`20261013083903_add_event_delivery_and_inbox`; its raw infrastructure tables add +no EF entity or model snapshot change. Standards 05 owns the complete applied +DDL, table classes, constraints, total-order indexes and exact column grants. + +The org-scoped ledger retains a subscription envelope independently of producer +retention. The tenant-wide inbox uses the producer event identity and subscription +without a surrogate; database guards refuse UPDATE, DELETE and TRUNCATE even as +the owner. No P3 role receives purge privileges. The app role accepts only immutable +envelope columns and completes only `processed_at`; the scheduler receives routing/ +status columns and nine scheduling UPDATE columns, excluding payload, causal +metadata, inbox access and business completion. Completed rows retain inert lease +provenance and are excluded from every scheduler index. Real subscriptions remain +Pending; this step claims no acceptance or business-delivery runtime. + +`EventDeliveryMigrationTests` exercises 73 real-PostgreSQL cases: permitted SQL, +exact grants and forbidden capabilities, tuple identity/ASCII grammar/state, +immutable guards with removed-trigger dirty controls, matching index/order plans, +producer-retention independence, canonical-document catalog parity and disposable +Down/reapply. The existing all-table fixture now seeds both stores for both tenants, +including distinct ledger organizations, and marks fixture ledger canaries complete. +The general tenant-isolation, foreign-write and grant sweeps include them. +Ledger-specific organization and scope-hatch proofs are recorded below. +Standalone Platform migration proofs install Tenancy's shared organization guard +first, matching the documented deployment sequence; historical migrations are intact. + +Validation before the implementation commit: Release build with `CI=true` has +zero warnings/errors; 164 focused schema/migration integration cases and all 287 +architecture cases pass, zero failures/skips. The seven ADR-status controls pass. +Format and whitespace validation pass; 1,180 relative links and 286 fragments +resolve without errors. Earlier receipts and Accepted ADR text remain intact. +Unit/frontend/runtime-worker suites are +not rerun for this schema-only step. Subsequent steps own acceptance, execution, +subscriber scheduling, useful defaults and full packet regression. + +#### Step 1 review round 1 + +Fresh GPT-6-astra/high reviewed every file in `63363ac..ad57a1b` through the +standards and code-review lenses. It requested changes for one missing required +proof: existing cross-organization/scope-hatch behavior tests name other tables, +so they do not establish the new ledger's organization boundary. Root independently +confirmed this gap; the current migration predicates were not found defective. + +The correction adds app-role ledger read, exact/null/mismatched acceptance and +fenced completion tests, with and without the tenant read hatch. Five live leased +canaries distinguish tenant-wide, own/sibling organization and foreign-tenant rows. +Own-scope controls remain writable. Disposable policy mutants prove a missing +organization read term leaks the sibling, a read hatch copied into WITH CHECK +admits forbidden acceptance, and removing only the restrictive UPDATE guard +changes zero matched rows into the remaining WITH CHECK's RLS refusal. The last +control does not claim a write bypasses both protections. No production policy or +grant changes are needed. The correction passes 125 focused ledger/organization +integration cases, zero failures/skips, with `CI=true` Release. Review round 2 +follows the correction commit. + +#### P02b-3 Step 1 review round 2 and closeout + +Fresh GPT-6-sol/high independently reviewed all 13 files in `63363ac..fe6f9c7`, +including the correction rather than only its receipt. Verdict: Approve, no +Blocker/Major/Minor. It verified the real-role organization proofs and weakened +policy controls, exact grants, RLS, immutable tuple inbox, ordered indexes, +canonical DDL parity, reversal and documentation scope. It made no edits and +inspected the tests; it did not independently rerun the reported suites. + +Root's correction run passes 125 ledger/organization integration cases, including +all 83 current `EventDeliveryMigrationTests`, zero failures/skips. Earlier Step 1 +verification passed the 164-case schema/migration group and 287 architecture cases. +The correction changes tests and their record only; format, documentation and +whitespace checks pass. Implementation commits are `6b1efef` and `ad57a1b`; +`fe6f9c7` closes the verified round-one proof gap. Step 2 follows automatically +under the accepted package; production subscriptions remain Pending. + +### P02b-3 Step 2 — durable acceptance and inbox primitives (2026-10-13) + +**Implemented; both independent review rounds complete.** `InProcessEventBus` now +validates the concrete canonical contract and required Active manifest, restores +publication context before creating a fresh application scope, and commits all +subscription envelope copies in one announced transaction. It constructs no +business handler. Exact identity plus canonical immutable fields distinguishes +idempotent duplicates from conflicting or inaccessible organization copies. +Matching subsets complete; a later collision rolls back earlier new copies. +Uncertain acceptance COMMIT remains producer-retryable. Only explicit intentional +absence may acknowledge without deliveries; Pending/unknown/retired contracts +refuse rather than silently reach zero handlers. + +`IInboxGuard`/`PostgresInboxGuard` claim only the tuple on the live, writable, +unpoisoned announced app-role transaction. PostgreSQL uniqueness waits for a +competing transaction: commit yields an existing identity; rollback permits a new +claim. The primitive owns neither connection nor commit. Business completion, +classification, independent execution and timeout gates remain Steps 3–4; +production default subscriptions remain Pending until Step 5's complete path. + +`DurableEventAcceptanceTests` and `InboxGuardTests` exercise 36 PostgreSQL cases: +construction-free acceptance, immutable-field collisions and JSON key-order +equivalence, matching/conflicting subsets, independent publishers and forced +unique-key waits in both commit/rollback orders, uncertain COMMIT acknowledgement, +actual tenant/org scope, fresh owner transactions, cancellation and inbox admission. +The fixture uses the production AsyncLocal accessor; a forced blocked publication +shares its provider with another tenant's independent successful publication. +Their blocker observers own finite cancellation deadlines. Root corrected the +initial duplicate test's shared process serializer before claiming SQL concurrency. +The canonical durable-acceptance catalogue rule is Implemented; the larger handler/ +inbox ownership and production census rules remain Registered. + +The former 32 immediate-handler bus unit cases no longer describe publish success. +Eight publication unit cases cover refusal boundaries, canonical runtime routing, +context before scope construction and restoration, intentional absence and queued +cancellation. Actual handler construction, invocation, internal handler dispatch, +per-subscription scopes, causal actor/trace, foreign cancellation, async faults and +cleanup are explicit Step 3/4 obligations; this step claims none of those execution +proofs. Existing producer worker timing/cleanup proofs use a disclosed scoped +publication wrapper around the real acceptance adapter. It deliberately models +cancellation-ignoring publication and real DI cleanup ownership. A separate +unwrapped-worker case proves durable acceptance without business construction. + +#### Step 2 validation before review + +The final `CI=true` Release solution build reports zero warnings/errors. The unit +suite passes 1,823 cases and architecture passes 287, with no failures/skips. +The 36 acceptance/inbox cases plus all 18 producer-worker cases pass together +(54 Docker cases). Foundation's canonical manifest registration replaces two +old Persistence-only composition fixture assumptions; the fixtures now exercise +the actual registration without opening a database or adding a second manifest. +The focused composition/corpus run also passes seven cases. Seven ADR-status +controls, format verification and whitespace checks pass. These are local receipts; +no PR-head CI or subscriber-owner delivery is claimed. Both fresh review receipts +follow below before Step 3 begins. + +#### Step 2 review round 1 + +A fresh GPT-6-astra/high reviewer examined every file in `80a3261..78992fc` and +approves with zero Blocker/Major findings. It independently passes all 36 new +acceptance/inbox Docker cases; the other local receipts above were inspected, +not rerun. One Minor catalogue link still named the renamed immediate-handler +worker proof. Root verifies the method rename and updates the label to the actual +acceptance proof. No runtime change is needed. Documentation links/fragments, +historical-record preservation and whitespace checks pass after the correction. +The second fresh review follows the correction commit. + +#### Step 2 review round 2 and closeout + +A fresh GPT-6.1-sol/high reviewer independently examines all changed files in +`80a3261..bce0bc7` and approves with zero Blocker/Major findings. It independently +passes 36 acceptance/inbox, 18 producer-worker, ten focused publication/composition +unit and all 287 architecture cases, with zero failures/skips. It reports one +Minor XML-comment grammar error; root verifies and removes the extra word. +Documentation/fragment, historical-preservation and whitespace checks pass. +Implementation is `78992fc`; `bce0bc7` corrects the verified round-one reference. +No runtime fixes were required. Step 3 follows automatically under the accepted +package; production subscriptions remain Pending. + +### P02b-3 Step 3 — business owner and completion gate (2026-10-13) + +**Complete; both independent review rounds complete.** +The closed prepared-owner entry announces the routing tenant/org and binds the +actual frame, unit, transaction and generation before retained-envelope loading. +Full validated event context replaces any inherited caller context before module +resolution. Inbox claim precedes classification/handler construction. A duplicate +skips business classification/construction and completes under the same final fence. + +Requests and deliveries share the common owner body: successful-save domain drain, +producer invariants, MUST audit, exact-row lock and fresh expiry check, sticky gate +admission, then physical COMMIT. No delivery opens a raw frame and calls the old +entry as a joiner. Incoming-event causation reaches nested production; immediate +domain-event identity takes precedence. SystemActor remains effective while closed +audit metadata preserves original causal actor and incoming event identity in both +writing paths. Shared audit fallback/reconciliation diagnostics suppress raw +exceptions only in event context; ordinary HTTP diagnostics remain unchanged. + +The one-use completion gate distinguishes cancellation before admission, unknown +COMMIT after admission and acknowledged durability. Npgsql retains successful +transaction disposal for owned cleanup, so an acknowledged commit reaches its +receipt before disposal faults or hangs. Cleanup before reuse and stale-frame +protection remain enforced. The executor retains its callback, frame and scope +through actual cleanup; scheduling deadlines/capacity/shutdown remain Step 4. +Ordinary versus privileged execution is explicit manifest metadata; P3 supplies +no privileged executor. Retained Active work may execute despite a Pending sibling, +while the producer's whole-event Pending hold remains unchanged. + +Production defaults remain Pending. Two fresh sequential review receipts follow +before Step 4 begins. + +#### Step 3 validation before review + +The `CI=true` Release solution build has zero warnings/errors. All 1,847 unit and +289 architecture cases pass, zero failures/skips. The 33 new delivery execution +and four physical Npgsql cleanup cases pass together as 37 Docker cases. They +exercise constructor/invocation/null-task failures, caller versus foreign +cancellation, SystemActor and original causal metadata before construction and +through cleanup, direct/nested/domain-event production, atomic five-leg rollback, +duplicate short-circuiting, ownership loss after saved work, expiry behind an +unchanged row lock, lost COMMIT acknowledgement at attempts one/six, and cleanup +faults/hangs after acknowledged durability. Unit proofs separately exercise the +closed capability/gate, fallback Activity, causal audit composition, capture +exclusions and actual nonempty bounded audit-failure diagnostics. + +An isolated source copy passes all six gate/token/expiry controls before mutation. +Removing gate refusal admits a late callback when its token is deliberately not +canceled; the corresponding test fails. Removing only the final expiry check +fails both expired-work and blocked-lock-expiry cases while the token/gate controls +remain green. Removing token equality fails its ownership-loss case while the +other two controls remain green. These are compiled behavioral mutations, not +source-string assertions; production source is never mutated for this experiment. +The restored isolated baseline passes all six controls after the mutations. +Required format verification, whitespace, seven ADR-status controls and the +1,623-link/372-fragment corpus sweep pass. The broader integration regression, +excluding the long frontend rendering proof, is still running at this commit; +its outcome must be recorded before this step closes. Neither this local +receipt nor the held production manifests claims an active production consumer +or PR-head CI. Step 4 retains independent scheduling, timeout and replay proofs; +Steps 5/6 retain actual defaults, Seeder convergence and full packet closeout. + +#### Step 3 review round 1 + +Two fresh complementary reviewers inspect `81ab105..77890ea` against the accepted +package and current code. GPT-6-astra/high approves the runtime/security path with +zero Blocker/Major/Minor findings. It independently passes 22 gate/audit-metadata/ +diagnostic unit and two owner-census cases; integration/mutation evidence is +inspected, not rerun. GPT-6.1-sol/high independently passes those 22 unit, all 37 +new PostgreSQL integration and two owner-census cases, zero failures/skips. It +approves with one Minor: the catalogue's updated 196-method total omits P02b-3 +Step 3 from its delivery attribution. Root verifies the two new methods and adds +that provenance; no runtime correction is needed. + +The broader integration run finishes after the implementation receipt: all 1,373 +additional cases pass, zero failures/skips. This excludes the 37 new cases already +run and `PublicServerRenderingTests`, whose long frontend proof remains in the +full Step 6 regression. Together these runs pass 1,410 integration cases. The +catalogue correction and review record pass link/fragment, historical-preservation +and whitespace checks. Fresh round 2 follows the correction commit. + +#### Step 3 review round 2 and closeout + +Two new reviewers independently inspect `81ab105..5a8b85d`, including the verified +round-one correction. GPT-6-sol/high approves the runtime/security/concurrency +path with zero actionable findings and independently passes 22 focused unit and +37 integration cases. A fresh GPT-6-astra/high evidence reviewer approves with +zero Blocker/Major/Minor findings and independently passes those 22 unit, 37 +integration and two owner-census cases. All reruns have zero failures/skips. +Full-suite and compiled-mutation receipts are inspected rather than rerun by +these reviewers. The initially selected evidence reviewer could not start because +its model was at capacity; it supplies no review evidence and was replaced by +the fresh reviewer named above. + +Implementation is `77890ea`; `5a8b85d` records the broader regression and fixes the +verified catalogue attribution. No runtime review fix is required. Earlier +Accepted ADR text and historical delivery records remain intact. Step 4 follows +automatically under the accepted package; no new decision or privilege expansion +is needed for its independent subscriber scheduler. + +### P02b-3 Step 4 — subscriber scheduling, terminalization and replay (2026-10-13) + +**Complete; both independent review rounds and the verified correction complete.** +The API-owned subscriber worker shares the existing confined keyed data source, +with no new role, migration or credential reader. Its store claims one exact +tenant/subscription/event tuple, selects routing/status columns only, and uses +the existing ordered indexes. Pending and privileged targets are held by exact +type/subscription pair; an accepted Active sibling remains runnable. Normal +claims spend independent attempts, expired claims recover without execution or +another attempt, and the sixth claim never authorizes a seventh invocation. + +The subscriber terminal writer extends the restricted actual-row witness and +fifth audit seam. Tenancy registers `platform.delivery.dead_letter` with that +writer; the terminal UPDATE and matching MUST/SecurityEvent audit share one +transaction. Targeted internal replay admits one completed terminal Active +ordinary tuple, invalidates its old ownership and never resets an inbox or +republishes a broadcast. Operator HTTP/permissions remain Phase 03. + +Task-owned controlled execution closes its sticky gate before asynchronous +cancellation callbacks, retains the actual application scope through those +callbacks and cleanup, and rejects control reuse before acquiring cleanup +ownership. Acknowledged durability survives faulted or overlong cleanup; retained +tasks continue to block their local partitions and consume the four-task capacity. +The shutdown wait uses one budget and the host token. Snapshot refresh follows +the configured cadence even after failure; gauges read immutable memory only. +Finite event/subscription labels and bounded diagnostics add no envelope read to +the scheduler. The private delivery health check leaves `/healthz` unchanged. + +Real-role store/worker tests and exact production-capability censuses with planted +controls pass local validation. Production defaults remain Pending until Step 5's +initializers and Seeder handoff are ready. Final test and two fresh sequential +review receipts follow before that step begins. + +#### Implementation validation + +The CI-equivalent Release build passes with zero warnings/errors. The final +candidate passes 1,855 unit, 298 architecture and 238 focused integration cases, +with zero failures/skips. The integration set includes 45 new store and 21 new +worker cases plus 172 producer/acceptance/inbox/owner/role regressions. TRX files +record each run; Docker-dependent tests use actual PostgreSQL and the guarded +application or confined scheduler role appropriate to the boundary. + +The final replay control first terminalizes four real rows, then resets one; +terminal neighbours differing in tenant, subscription or event remain byte-for-byte +unchanged. Business execution also carries a distinct human causal actor while +effective audit actor remains SystemActor. No-listener trace proof asserts the +actual source has no listeners before checking a fresh canonical attempt ID. + +Final format verification, all seven ADR-status controls, all five corpus guards +and whitespace checks pass. The changed-document sweep checks 1,818 relative +links and 398 fragments with zero missing targets/anchors; added prose passes +the 88-column check. Earlier Accepted ADR bodies and dated P02b receipts remain +byte-preserved. + +Three catalogue rules become Implemented with their behavioural/structural owners. +The catalogue now records 205 architecture methods and 196 Implemented rules, +120 in the architecture assembly and 76 elsewhere. Consumer-handler censuses, +production activation and defaults/Seeder proofs remain Steps 5–6. Earlier dated +receipts retain their original counts and pending status. + +#### Step 4 review round 1 + +Two fresh read-only reviewers inspected `3411424..262d4b2`: + +- **Runtime/security — GPT-6-astra, high:** one verified Major. Subscriber + execution and durable acceptance used the same singleton/raw partition lane; + a retained handler or postcommit cleanup could delay producer acceptance and + consume producer timeout/capacity. Its independent rerun passed 66 focused + PostgreSQL and eight focused unit cases, showing the missing combined scenario. +- **Proofs/docs — GPT-6-sol, high:** Approve, no Blocker/Major/Minor/Suggestion. + It inspected production capability censuses, actual-role/worker tests and + documentation/history without independently rerunning the suites. + +Root verified the shared lane and separates only the internal execution lane +with a fixed `delivery:` prefix. Validated event partitions remain canonical UUIDs; +consumer serialization and raw scheduler partition holds remain intact. A live +subscriber cannot delay a new same-partition publication's durable acceptance. +Two real-bus/PostgreSQL regressions hold the actual handler or acknowledged-COMMIT +cleanup and accept a second same-partition event before releasing the first. +In an isolated source copy, restoring the shared raw lane makes both cases fail; +no production source or branch is mutated for that control. This implements the +accepted independent failure domains and introduces no new policy or ADR. +Correction validation passes the Release build with zero warnings/errors, 1,855 +unit cases, 41 affected architecture cases and 101 store/worker/executor PostgreSQL +cases, with zero failures/skips. Both isolated restored-baseline cases pass again. +Format, whitespace and the 1,818-link/398-fragment document sweep pass; the next +fresh review round follows the correction commit. + +#### Step 4 review round 2 and closeout + +Two new read-only reviewers independently inspected `3411424..14d5f93`, including +the complete Step 4 implementation and round 1 correction: + +- **Runtime/security — GPT-6-astra, high:** Approve, zero + Blocker/Major/Minor/Suggestion. Independently passed 101 PostgreSQL cases, + 16 lifecycle/observation/commit-gate unit cases and 36 architecture cases, + with zero failures/skips. It verified lane separation, fresh-clock fences, + row-bound terminal audit, exact replay and actual resource ownership. +- **Proofs/docs — GPT-6.1-sol, high:** Approve, zero + Blocker/Major/Minor/Suggestion. Independently passed 101 PostgreSQL cases, + 41 architecture cases including all five corpus guards, and eight unit cases, + with zero failures/skips. It verified the corrected binary's new tests/lane, + planted census controls, catalogue counts and preserved historical records. + +Both reviews used existing Release artifacts without independently rebuilding or +rerunning the isolated mutant. Their receipts distinguish actual reruns from +inspection of root's earlier build/format/link/mutant evidence. Neither changed +files or GitHub. The correction is committed at `14d5f93`; root's restored mutant +baseline passes both cases after the old-lane mutant failed both. Step 4 is closed; +Step 5 follows automatically with useful consumers and semantic Seeder handoff. + +### P02b-3 Step 5 — useful defaults and semantic seed handoff (2026-10-13) + +**Complete; both independent review rounds complete.** +Step 4 is closed before these changes. This step implements the accepted pair of +one-root initializers and shared transaction-owned concept serialization, then +moves built-in seed verification to semantic identity. Authored identities and +exact pins retain their existing contract. Both production subscriptions activate +together only after the initializer and Seeder paths are ready. + +The initial implementation supplies two Off-classified subscriber coordinators +and two MUST-classified initializer commands. Both production manifests are Active +and bind the discovered handlers exactly. Each untouched concept is published +before its single save, with one generated UUIDv7 identity, generation bump and +resource audit. Every existing lifecycle/revision is preserved under the same +transaction-owned concept lock used by ordinary registration. + +Seeder discovers the exact Active built-in by key, verifies its full shape and +retains the discovered identity. Authored identities/pins remain strict. Fresh +seed inventory retains all definitions/content but uses six customization +generation bumps per tenant and 86 audit rows, replacing the earlier two-step +register/publish treatment of four built-ins. The P02d seed receipts remain +historical evidence of their original behavior. + +Initial validation: full CI-mode Release build has zero warnings/errors; all +1,862 unit and 298 architecture cases pass. Focused app-role integration passes +24 initialization cases, 83 Seeder/audit/projection/manifest cases and eight real +API delivery cases, all with zero failures/skips. The real flow covers stored +backlog, fresh provisioning, audit-failure rollback/recovery, duplicate acceptance +and Seeder/subscriber races for both concepts in both winning orders. Test-owned +database gates coordinate real writes without a production registration hook. +The race observer uses the app role so PostgreSQL exposes its own role's lock +waits; the earlier owner-role observer could not see app-role activity and failed +the fixture, rather than detecting a product defect. The corrected full flow +passes all eight cases. The existing publication concurrency suite also passes +all ten cases, and the guarded frontend run passes 1,616 cases with zero +skips/todos. Two fresh sequential review receipts follow before Step 6. + +#### Step 5 review round 1 + +Three fresh read-only reviewers examined `94d7d6b..d53ae27` before the second +round. GPT-6-astra xhigh reviewed production correctness, isolation and races; +GPT-6.1-sol xhigh reviewed proof quality and Seeder convergence; both approve with +no findings. They independently reran 92 integration cases and 100 focused +integration/unit cases respectively, all passing with zero skips. These overlap +root's receipts and are independent reruns, not additional distinct test cases. + +GPT-6-sol high identified four mutable Architecture 31 passages still describing +real defaults as Pending, and the standards-check skill still describing inbox +acquisition as pending. Root verified both against the Active bindings and owner +path, corrected those current-state carriers and extended the phasing table to +Step 5. The historical ADR and Step 1–4 receipts remain unchanged. Root's updated +document check passes 2,209 relative links and 480 fragments with no errors; +the reviewer independently passes all five corpus guards. No runtime correction +was needed. Missing full-packet ADR delivery notes are not a Step 5 finding: +Step 6 owns them after production-census enforcement and final regression. + +#### Step 5 review round 2 + +Fresh GPT-6-astra high and GPT-6.1-sol high reviewers independently reviewed +`94d7d6b..0302d8a`, including implementation and the R1 correction. Both approve; +no runtime finding remains. The runtime reviewer independently passes 92 focused +integration and 97 unit cases, with zero failures/skips. The proof/corpus reviewer +independently passes 92 integration cases and all five corpus guards, including +the final correction below. These are overlapping independent reruns. + +The second reviewer found the Pending-policy catalogue entry still naming the +renamed production-composition test and calling actual subscriptions Pending. +Root verified the surviving test and explicit Pending fixture registrations, +then corrected the reference and separated the policy proof from current Active +bindings. The reviewer rechecked that correction and the 198/120/78 catalogue +counts with no open finding. Release binaries are unchanged. Root's document +check has zero link/fragment/width errors and preserves earlier receipts and ADR +text. Step 5 is closed. Step 6 follows with production censuses, remaining current +carriers, full regression, demo/Lighthouse and PR-head CI verification. + +### P02b-3 Step 6 — production enforcement and PR closeout (2026-10-13) + +**Implementation and both independent review rounds complete.** +[PR #31](https://github.com/HodeTech/LearnStack/pull/31) is open for maintainer +review; merge remains pending. +Step 5 is closed at `ac7bbee` before these changes. This step completes nonempty +production handler/manifest and call-path controls, extends aggregate/audit +coverage to integration handlers, reconciles current carriers and performs full +Release regression plus the real shared demo/Lighthouse lifecycle. The earlier +five delivery/review receipts remain unchanged. + +The authorized Hub dependency pointer is reconciled in the existing sibling +`docs/hub-agent-handoff` branch at `dd243a0`: its P02c-3 dependency now links to +ADR-0046's shared transport-owned inbox. This is a local documentation-only commit; +no Hub runtime, HTTPS surface, branch change, push or PR is part of that update. +The Hub track remains frozen under its existing owner decision. + +#### Step 6 implementation and local proof scope + +The canonical inbox rule now discovers concrete integration handlers in every +production assembly/layer, compares inherited/explicit event contracts with the +actual API's two scoped Active bindings, and checks typed construction, +invocation, generic DI, helper, async and delegate capabilities. Missing assembly, +handler, registration and actual invocation subjects fail the same predicates. +The lifecycle companion pins exact typed unit/frame and raw transaction +completion owners, including site multiplicity and missing-owner controls. +These checks do not infer arbitrary reflection, raw SQL transaction control or +control-flow dominance; the app-role behavioural suites own execution order and +atomicity. They introduce no production runtime hook. + +Audit discovery now fails on assembly/type load errors and classifies each +concrete handler, rather than its shared event. Actual API/Seeder catalogues must +include both Off coordinators even when their operation entries are unchanged; +an omitted-handler control and integration-only module control can fail. +The aggregate constructor-port census includes inherited integration handlers, +fused ports and separate-root controls. It does not infer nested ISender +request dataflow; the real default effects supply the one-root runtime proof. + +The canonical restored-context test checks constructor/callback timing, inbox, +prior context cleanup, effective SystemActor and separate causal human identity. +It also reads the committed outgoing trace, tenant/org and exact nonempty +partition. A new test-only HTTP controller sends the existing provisioning +command through the real API pipeline and production outbox, then reads the +committed quartet from a separate app-role connection. This proves producer +tracing, not authorization or admission of a new production endpoint. + +Self-check corrected test-harness overload/fixture lifetime issues without +weakening assertions. The first full architecture run reported the new partial +HTTP test file missing a source-visible Docker trait; the runtime class already +inherited it from its other part. The method now declares the trait explicitly. +No failing or partial run is counted as passed evidence. + +Local Release proof receipts: + +- Build: zero warnings/errors; solution-wide format verification passed. +- Unit: 1,862; contract: 4; full integration: 1,550, all passed with zero skips. + The final integration receipt includes the new HTTP and strengthened delivery + quartet proofs; its subsequent source change adds only the explicit method + trait. The final full architecture rerun passes all 311 cases, zero skips; + the source convention requires the shared `RequiresDocker` constants. The + combined backend receipts total 3,727 passing cases. Catalogue self-checks + confirm 218 architecture methods and 200 Implemented rules: 121 in that + assembly and 79 elsewhere. Five focused HTTP/context/composition controls + also pass on the final candidate build. +- The unchanged frontend passed its guarded 1,616-case suite, lint and typecheck + in Step 5; those receipts remain applicable, without claiming a Step 6 rerun. +- A fresh isolated development clone at `ac7bbee` ran the full shared demo. Step 6 + changes only tests/docs, so its production runtime is identical. The proof + finished in 580,109 ms with 27 JSON/HTML report pairs, nine URLs and three runs + each: maximum normalized gzip JS 106,573 bytes, maximum CLS 0 and every + automated accessibility score 1. Nine timing advisories remain warnings, not + production p95 claims. Cleanup passed and every originally running external + container was restored. This local receipt is not an exact final-PR-head CI + claim; the required CI job reruns the actual head. +- Relative document links/fragments and 88-column prose checks pass. Earlier + P02b delivery/review receipts and Accepted ADR bodies are byte-preserved; + authorized dated delivery notes are additive. ADR parser/disclosure tests: 7. + +#### Step 6 review round 1 + +Three fresh independent agents reviewed `ac7bbee..82623d8`: GPT-6-astra/xhigh +covered typed invocation/lifecycle capabilities; GPT-6.1-sol/xhigh covered +aggregate/audit discovery, actual roots and HTTP/delivery proofs; GPT-6-sol/high +covered the corpus and governance. Independent runs passed eight capability +cases, twenty aggregate/audit cases and five actual root/HTTP/context cases. +The whole backend/demo receipts above were inspected, not independently rerun. + +They found four enforcement gaps: a same-simple-name integration handler could +hide inside the provisioning exception; a handler could inherit implementation +from a base without the interface; a closed generic helper could hide typed DI +resolution; and EF transaction completion APIs could bypass the typed lifecycle +census. Root read the actual predicates and independently reran both compiled +scratch reproductions, confirming dirty cases were missed and matched controls +were detected. No current production-runtime defect was demonstrated. + +The fix pins the exact provisioning Type and adds independently failing name +collision controls. The capability fixes map inherited implementations, follow +closed generic helper specialization to known DI capabilities and enumerate EF +transaction/facade completion APIs. Existing Facts gain compiled dirty/clean +controls without increasing counts. Root's corrected Release build has zero +warnings/errors and all nine focused guard cases pass, including independent +same-name and recursive/ordinary generic controls. Rerunning the original +compiled capability probe now detects both inherited/generic misses and every +EF completion case, while the actual production baseline remains clean. The +first fix build caught instance-only probe methods that used no instance state; +their instance task fields preserve the intended inherited call shape without +an analyzer waiver. Full architecture passes all 311 cases with zero skips; +solution-wide format verification and document checks pass. The fix changes +tests/docs only; prior full unit/contract/integration and demo receipts retain +their explicitly recorded scope. +Current README, processor and skill guidance also retained delivered-as-pending +claims; those verified carriers are corrected. The new ADR-0046 delivery note +stays only in its dated Amendment 3, with mutable-index navigation; no new top +navigation is inserted into the Accepted body. + +#### Step 6 review round 2 and local closeout + +Three new independent agents reviewed the full `ac7bbee..84995d3` Step 6 range: +GPT-6-astra/xhigh covered capability/lifecycle enforcement; GPT-6.1-sol/xhigh +covered audit/aggregate/root/tracing proofs; GPT-6-sol/high covered the corpus. +The technical slices approve without an actionable finding. Independent runs +pass eight capability cases, twenty aggregate/audit cases and five real root/ +HTTP/delivery cases, all with zero skips. A separate compiled probe detects +seven additional dirty generic/inherited/async/iterator/closure/local-function/ +permutation shapes and leaves two unused-handler-argument controls clean. + +The corpus reviewer approves with minor current-pointer corrections in +architecture 10/15, Standards 20 and the producer catalogue entry. Root verified +and fixed them, preserving Step 5 as dated evidence and linking current status +to this record; the reviewer rechecked the edits. A final glossary clarification +states context precedes business construction/DI resolution, while metadata +registry discovery happens earlier. Root verified the actual executor ordering. +Five corpus consistency cases and link/fragment checks pass; these final fixes +change documents only. No open verified finding remains from either round. + +All six P02b-3 steps completed their implementation commits and both independent +review rounds. The local full-suite, focused fix and demo receipts retain the +explicit scopes above; no final-head CI success is inferred from them. The PR +handoff below will own the live seven-check verification and maintainer review. +This completes P02b-3 implementation and local review, not a merge or the whole +Phase 02b. P02b-4–8 remain unimplemented; the next packet is P02b-4's background- +job decision pass, including the reserved ADR-0047 before runtime work. + +### P02b-3 PR handoff (2026-10-13) + +[PR #31](https://github.com/HodeTech/LearnStack/pull/31) compares `development` +with `main`. The six-step implementation and both independent review rounds +are complete; initial enforcement is `82623d8`, verified first-round fixes are +`84995d3`, and local review/document closeout is `a8e9c9d`. The +[Step 6 record](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +owns scoped local validation, independent receipts and corrected findings. +This handoff changes documents only and introduces no new implementation scope. + +The [live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own +exact-head CI results. All seven required contexts remain active with strict +up-to-date protection: backend, frontend, secret scan, meta, backend integration, +OpenAPI diff and public demo/Lighthouse. The initial published head started CI; +this documentation receipt receives its own final-head run. No pending or +superseded run is counted as success. Maintainer review and merge remain pending. + +P02b-4's background-job decision pass is next after this packet's review. It +must draft and obtain approval for the reserved ADR-0047 before runtime work. +Authentication, realm reconciliation, BFF/session and phase exit remain +P02b-5–8; Phase 02b is not complete. + +### P02b-3 external review follow-up (2026-10-15) + +The external PR #31 review compares `6a277770..683ea537`. Findings are review +inputs, not authority; each was checked against current code, Accepted ADR-0046 +and the approved P02b-3 package. Earlier dated receipts and Accepted ADR bodies +remain unchanged. No new runtime decision, migration, role, endpoint or replay +permission is introduced by this follow-up. + +Verified corrections: + +- Live P02b-2 pointers now name its merge closeout; P02b-3 status points to Step 6 + and the PR handoff. Shared handler/audit remarks, canonical Inbox prose, + glossary, decision index and review guidance describe delivered behavior. +- Failed snapshot reads no longer advance the successful refresh timestamp. + Recovery is tested after restoring SELECT without advancing the fake clock. + A normal claim's uncertain completion records `execute:unknown:commit`; + expired-lease recovery retains `recovery:unknown:expired`. +- The existing lifecycle census now enumerates actual tenant-announcement calls + through both the interface and concrete adapter, including inherited, async + and delegate shapes. Missing real calls and planted extra callers fail it; + ADR-0040's eight logical setter paths remain unchanged. +- Catalogue discovery reads the declared Status block rather than any bold + Implemented mention elsewhere. A Registered entry with misleading Implemented + prose is a negative control. The scheduling-index proof reads actual production + eligibility/admission constants and includes time, lease, locking and LIMIT. +- Removed the duplicate executor registration. Added actual-store wrong-kind + controls and producer terminal audit cases for absent versus invalid causal IDs. + Composition/factory remarks and seed-audit count explanation are aligned. + +Verified dispositions for the remaining review items: + +| Review item | Disposition and current evidence | +|---|---| +| Health should tolerate one retained overrun | Rejected: the approved P3 runtime table and Standards 10 require unhealthy while any callback/cleanup overrun remains. Capacity four separately stops acquisition; ordinary running work is not this count | +| SQL NULL causal IDs should invalidate a valid original trace | Rejected: optional absence is valid; only empty IDs are invalid. Real terminal regressions now pin both outcomes; audit prose explicitly distinguishes absence | +| Unclassified delivery log should include raw handler type | Kept minimized: existing delivery proofs prohibit handler type text. The scheduler's correlated attempt already names finite subscription/event labels and outcome; no raw stored type or exception detail is added | +| Queue snapshot lacks a dedicated aggregate index | No schema change: the exact count/minimum covers all unfinished ledger states at the approved cadence, under the SQL deadline. Claim-index applicability is now tested against actual selection. This is not a claim of constant-time counting; Phase 11's existing retention/scale work owns aggregate cost tuning | +| Initializers need ordinary AggregateConflictException handling | No defect: initialization and registration share the concept lock, with both winning orders tested. Unexpected ID/constraint faults abort and follow subscriber retry | +| Initializer exception should include Result.Error detail | Kept bounded: actual consumers throw fixed effect-specific failures, tested on refusal. Raw details do not belong in delivery diagnostics | +| No-change initializer audit lacks a business snapshot | Accepted behavior: preservation attempts remain classified MUST successes without mutation or entity snapshots; creation separately requires captured Active state | +| Preserved non-Active built-in causes untested Seeder divergence | Rejected: Draft/Deprecated/deleted and successor/history tests preserve every business field, then refuse the exact Active demo postcondition; the seed skill already documents it | +| Seed skill implies old built-in registration | Rejected: its write-order step explicitly uses separate shared initialization commands and distinguishes authored registration/publication | +| Concept-history SQL duplicates mapping names | No refactor: owner-local constant SQL intentionally reads tombstones through explicit tenant predicates and RLS; actual schema/history/isolation/race tests cover it | +| Five-second acceptance/inbox command timeouts | Match the approved fixed SQL bound. No shared mutable configuration contract is promised | +| Per-subscription acceptance statements | Two declared subscriptions; separate equality reads deliberately obtain a fresh READ COMMITTED snapshot after a concurrent conflicting insert | +| Repeated writable-announcement checks | Deliberate boundary validation: detect changed transaction, context generation and tenant/org before SQL and commit | +| Retained envelope needs an owner trigger | Existing exact column grants implement the approved immutability boundary and have real-role forbidden-write controls. Inbox's owner trigger is a separate marker contract; no new owner-level policy is inferred | +| Capture exclusions name currently unmapped SQL machinery | Intentional ADR-0044 Amendment 11 policy; mapped probe types exercise actual interceptor exclusions even though production storage uses SQL | +| Integration friend assembly exposes all internals | C# friendship is assembly-wide; it enables actual internal execution/lifecycle proofs without exposing production APIs | +| DeliveryAttemptTests name, worker-test title and options binding | Naming/configuration suggestions only: the tests deliberately cover attempt cancellation control and exactly one OutboxProcessor; dispatcher options use approved fixed bounds, not a promised configuration section | +| Lifecycle/owner Facts need separate canonical rows | Existing Integration_Event_Handlers_Use_InboxGuard entry already names both companions. The expanded announcement proof is recorded there; no duplicate rule is added | +| Producer/subscriber rules share TerminalOffenders | Intentional common witness authority, with distinct producer and subscriber dirty controls; not a missing independent failure path | +| Bare First/Single in planted controls | Missing fixtures fail loudly rather than pass. No absent-subject success was reproduced; production subject and signature checks remain explicit | +| Nonempty/derived-capability assertions | Existing required-type, method, signature and exact-owner checks fail before mutation loops when a production subject disappears | +| Ignored consumer ActivityContext.TryParse result | Immutable envelope construction and the retained-envelope reader validate the trace before this call | +| Internal delivery partition lane needs explanation | Existing comment explains acceptance/execution separation and canonical UUID collision avoidance; the approved local-ordering bound remains | +| Subscription grammar copies need consolidation | Equivalent current contract, already tested through registry, storage and witness admission; optional refactor, no divergent behavior demonstrated | +| CancellationToken.None after commit admission | Accepted cancellation/unknown-outcome tradeoff; do not replace the approved sticky gate and reconciliation contract | +| Decision-index amendment numbering gaps | Selected navigation links do not enumerate all historical amendments; complete dated sections remain in each ADR | +| Built-in enumeration, meter factory and health Degraded suggestions | Optional abstractions/observability policy changes; no demonstrated current defect in the approved two-default, binary-health contract | +| Earlier P02d seed receipts and ADR-0046 top navigation | Historical evidence stays intact. P02b-3 Step 5 owns current generated built-in identities and semantic verification; current index links the preserved ADR-0046 Amendment 3 | +| Replay/privileged execution and future strict ordering | Existing Phase 03/new-decision triggers remain explicit; no operator entry point or privileged subscription is activated | +| Retention, inbox-trigger purge exception and erasure inventory | Existing Phase 11 retention/grant decision and P02b-8 inventory obligations remain; this follow-up does not grant purge or bypass access | + +The original source head `683ea537` passed all seven required CI contexts in +[run 38424753309](https://github.com/HodeTech/LearnStack/actions/runs/38424753309). +Downloaded exact-head artifacts corroborate 1,862 unit, 311 architecture, +4 contract and 1,550 integration tests (3,727 backend; zero failed/skipped), +1,556 web plus 60 SDK tests, and 27 admitted browser/Lighthouse report pairs. +Maximum normalized gzip JS was 106,551 bytes, maximum CLS 0, all automated +accessibility scores 1; the proof finished in 621,330 ms with successful cleanup. +These are evidence for the reviewed head, not this correction's final-head CI. +Correction validation: Release solution build has zero warnings/errors; +solution-wide format and diff checks pass. All 1,862 unit, 311 architecture, +4 contract and 176 Docker-free integration tests pass, with zero skips. Focused +real PostgreSQL validation passes 73 worker/store/terminal cases plus the actual +candidate-index case. Seven ADR parser cases and the document link/fragment, +prose-width and historical-record checks pass. At this initial receipt the +catalogue counted 218 methods and 200 Implemented rules (121 architecture, +79 elsewhere); the round-2 correction below records the accurate current count. + +The first full unit run exposed a cross-test metric listener race (one observed +failure counted another test's same-name meter). The corrected test filters its +owned Meter by reference, disposes its provider and verifies an unrelated meter +really emits while contributing zero to its count; the actual store must still +count exactly one. The focused case and corrected full unit suite pass. +Fresh review rounds and correction-head CI remain pending at this initial receipt. + +#### External follow-up review round 1 + +Two fresh independent agents reviewed `683ea537..586ed75`. GPT-6-astra/xhigh +reviewed runtime, security, isolation, lifecycle and performance, independently +passing 72 focused PostgreSQL integration cases and three architecture cases. +GPT-6.1-sol/xhigh reviewed guards, tests, governance and all changed documents, +independently passing eight architecture cases, 18 recorder unit cases and the +real PostgreSQL candidate-index case. All runs have zero failures/skips. + +The runtime review found no actionable issue. The proof/corpus review found two +Minor wording errors: the new machinery-write prohibition inadvertently required +all business handlers to send commands, although the Accepted classified direct +one-root path remains valid; and Security retained an obsolete one-setter count. +Root verified both against ADR-0044 Amendment 8/ADR-0057 and current transport +calls. The fixes remove the command-only restriction and describe the actual +announcement seam without a misleading count. The reviewer rechecked both and +approved with no remaining finding. Document checks pass; this fix changes no +runtime or test source. Round 2 and correction-head CI remain pending here. + +#### External follow-up review round 2 and closeout + +Two new independent agents reviewed `683ea537..d8c766f7`. GPT-6-astra/xhigh +reviewed technical correctness and proofs, independently passing 72 PostgreSQL, +eight architecture and 18 recorder unit cases. GPT-6-sol/high reviewed the corpus, +governance and test claims, independently passing seven focused architecture cases. +All runs have zero failures/skips. Runtime, isolation and lifecycle were approved. + +The corpus reviewer found a pre-existing counting omission in the touched parser +scope: two real integration rules used a bold `Implemented, twice.` status and +were excluded from the declared-state count. Root verified both exact-name +methods in `TenancySchemaTests` and `TenantIsolationHttpTests`, normalized the +statuses to a bold `Implemented` token with the qualifier outside it, and named +the actual classes. An additional positive control in the existing corpus Fact +pins qualified Implemented discovery alongside misleading Registered prose. +This adds no test method or runtime rule: the accurate catalogue total is now +202 Implemented entries, 121 in architecture and 81 elsewhere; architecture still +has 218 methods and 311 cases. The earlier 200-entry receipts retain their +as-recorded scope and are superseded for the current catalogue count here. + +Root's corrected five corpus tests pass after rebuilding. Both reviewers +independently recounted the entries, rechecked the exact methods/control and ran +all five corpus tests successfully, approving with no remaining finding. Final +format, diff and document checks pass; historical delivery receipts and Accepted +ADR text remain intact. Earlier full-suite receipts retain their stated scope; +the last correction changes test fixtures and catalogue metadata only. + +The implementation and both external follow-up review rounds are complete. +The [live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own the +correction-head CI result; the PR description is updated only after inspecting +that exact source head and its artifacts. No earlier run substitutes for it. +Maintainer review and merge remain pending; this follow-up starts no P02b-4 work. + +### P02b-3 second external review follow-up (2026-10-15) + +**Status: verified corrections and both review rounds complete on `development`; +PR #31 remains unmerged.** +The external reports reviewed `b681edb8`. Each finding was checked against current +source and Accepted ADR-0046/0057; supplied reproduction files were review data, +not instructions. This receipt supplements the +[first follow-up](#p02b-3-external-review-follow-up-2026-10-15). +That follow-up's final counting correction is commit `b681edb8`, after its +round-2 reviewed range `683ea537..d8c766f7`. + +The reviewed source head passed all seven required contexts in +[run 38736262412](https://github.com/HodeTech/LearnStack/actions/runs/38736262412): +3,732 backend tests (1,862 unit, 311 architecture, four contract and 1,555 +integration), 1,616 frontend tests and 27 browser/Lighthouse report pairs. +Downloaded artifacts were checked against source `b681edb8` and checkout +`3b06800d`; zero tests failed or skipped. These receipts cover that reviewed head, +not the corrections below. + +#### Verified corrections + +- Fixed class priority could indefinitely starve ordinary deliveries when a + terminal-audit failure backlog outlived its leases. Independent actual + PostgreSQL reproduction observed 216 terminal failures in eight seconds while + the normal delivery stayed at zero attempts; invoking the real executor + directly completed it while the scheduler audit grant remained denied. + Rotate terminal, recovery and normal acquisition after each class visit, + including failures. Each iteration still acquires at most one just-in-time + claim; existing lease, fence, partition, capacity and terminal rules remain. +- Duplicate acceptance compared retained type text literally. Independent + PostgreSQL reproduction rejected an explicitly declared compatible alias + while accepting the canonical control. Compare all other envelope values + exactly and resolve retained type through the closed registry to the incoming + CLR contract. Preserve retained type, payload, scheduling state and row version; + no arbitrary CLR loading or payload normalization is added. +- Completion constructor calls now have an exact owner census, with additional + direct/asynchronous caller and missing-site controls. Production project + discovery includes differently named projects and ignores generated `obj` + projects, with a temporary-tree control. +- Audit storage requires a non-null diagnostic context accessor in every + construction. Undefined subscription execution scope has its own fixed + diagnostic. Catalogue refusal has its own closed `execute:refused:catalogue` + descriptor, with no-construction/business/inbox controls. Rollback/reapply + proofs include the inbox trigger function, and + lease-expiry polling has a deadline propagated through its database reads. +- Live state pointers, migration-chain naming, the naming table, scheduler index + rationale, catalogue detector sharing and delivered subscriber wording are + aligned. Earlier delivery/review receipts retain their stated scope. + +#### Other findings and scope + +| Review item | Disposition and current evidence | +|---|---| +| Unknown-COMMIT failure counter | Accepted process observation, not durable business accounting; Standards 10 explicitly documents that an unknown COMMIT may have succeeded | +| Startup should log exception types/details | Existing minimized dispatcher diagnostics deliberately omit provider/exception type text; current fixed failures and health remain bounded | +| Additional completion owner assertion | Already enforced by prepared-owner creation and `RequireLive`, including before fencing; no reachable missing check | +| Suppress post-acknowledgement disposal errors | Deliberately pinned by `UnitOfWorkCommitCleanupTests` and `DeliveryCommitGateTests`; delivery interprets definitive commit evidence. Changing ordinary request response policy needs a separate design | +| Acceptance round trips | Two current subscriptions; the separate equality statement intentionally gets a fresh READ COMMITTED snapshot after a conflicting INSERT | +| Duplicated SystemActor derivation | Not present: the coordinator derives it; producer envelope creation consumes captured causal context | +| Add a 200-character subscription ID limit | No such bound exists in the Accepted grammar/package; the cited 150-character cap is specific to killswitch keys. Finite registered IDs remain trusted configuration; no new numeric contract or migration is inferred | +| Initializer conflict catch | Shared concept lock plus any-history refusal handles both registration orders; unexpected ID/constraint faults must roll back | +| Taxonomy verification needs set equality | Unique stored band keys plus equal count and complete membership already establish unordered equality; real shape/history mismatch controls remain | +| Two stores must use separate pools | Existing contention proof promises two stores and uses distinct live connections/transactions; separate pools/processes are not its claim | +| Raise shortened fixture deadlines | No reproduced deadline defect; keep the intentionally shortened valid test bounds and controlled shutdown clock | +| Health should count ordinary awaited callbacks | The published count tracks retained overruns/cleanup; the ordinary serial await does not publish it. Any retained task remains unhealthy, with acquisition stopping separately at capacity four | +| Additional commit-owner abstraction/refactors | Exact declared owners remain intentional; no new helper, outcome router or diagnostics abstraction is needed for these corrections | +| Internal replay needs a production audit writer | Still unwired; Phase 03 owns operator permission/HTTP and its classified audit path. No new replay entry point is activated | +| Friendship, cross-cutting composition and N envelope copies | Existing explicit internal proof access and composition are unchanged; the accepted package already inventories per-subscription retained copies for P02b-8/Phase 11 | +| Further policy parity/concurrency/census optimization | Existing real-role policy, independent-connection contention and planted production controls remain; no missing behavior was demonstrated beyond the corrected discovery/constructor gaps | + +Correction validation: Release solution build has zero warnings/errors; full +format and diff checks pass. All 1,864 unit, 312 architecture, four contract and +176 Docker-free integration cases pass with zero skips. Focused integration +passes 31 acceptance, 23 actual-worker and 113 store/audit/migration/composition +cases. The latter includes three Docker-free composition cases already covered +by the full Docker-free receipt; these are not extra distinct tests. + +The fixed-priority and literal-type-equality mutants each fail their new +PostgreSQL regression. Original source was restored, the solution rebuilt and +both regressions rerun successfully. Seven ADR parser cases pass; document +checks validate 2,822 relative links and 631 fragments, prose width, historical +receipts and earlier Accepted ADR text. The catalogue counts 219 methods and +202 Implemented rules (121 architecture, 81 elsewhere). + +The first architecture run correctly rejected the moved claim calls because its +exact privileged-consumer list still named `ExecuteAsync`. The corrected census +requires the private `ClaimNextAsync(string[], CancellationToken)` signature +instead, with an extra-overload control. It grants no whole-type exemption; the +full corrected architecture suite passes. + +Two fresh independent review rounds and correction-head CI remain pending at +this initial receipt. Earlier CI evidence does not substitute for that head. + +#### Second follow-up review round 1 + +Three fresh agents reviewed `b681edb8..92e296ed`. GPT-6-astra/xhigh reviewed +runtime, transaction/cancellation ownership, fairness and diagnostics; it passed +23 worker, 25 diagnostic/registry unit and 40 dispatcher architecture cases. +GPT-6.1-sol/xhigh reviewed guards, proofs, governance and corpus consistency, +independently passing all 312 architecture cases. GPT-6-sol/high reviewed alias +acceptance, concurrency, RLS and audit composition; it passed 31 acceptance, +23 worker and 25 focused unit cases. All runs have zero failures/skips. + +All three approve with no verified actionable finding. The older prefix-scoped +request/handler discovery scans are separately documented scopes, not a claim +of this shared production census. No new rule or deferred decision is silently +introduced. Round 2 and correction-head CI remain pending here. + +#### Second follow-up review round 2 + +Two new agents reviewed `b681edb8..a95ae2ec`. GPT-6-astra/xhigh reviewed runtime, +acceptance, isolation and audit composition, independently passing 163 focused +integration, 43 unit and 41 architecture cases. GPT-6.1-sol/xhigh reviewed proofs, +corpus, ownership controls and governance, independently passing all 312 +architecture and 25 focused unit cases. All runs have zero failures/skips. +Both approve with no verified actionable finding against that correction scope. + +The runtime reviewer separately identified the unchanged producer worker's same +fixed class-priority pattern. This concern was not counted as a verified finding +against the reviewed diff. The adjacent correction below owns its PostgreSQL +verification and any resulting implementation/review evidence; the delivery and +alias approvals do not substitute for reviewing that change. + +#### Adjacent producer fairness correction + +**Status: correction, validation and both independent review rounds complete.** The +producer worker's strict terminal/recovery/normal priority reproduced the same +starvation in real PostgreSQL. With 100 terminal requests and only the scheduler +role's audit INSERT denied, the regression passed its lease-cycle failure check +then failed at the independent normal-publication/recovery deadline. The baseline +producer source was unchanged. The fixed worker uses the same bounded rotating +acquisition as the subscriber; its exact private credential-consumer signature +and extra-overload control replace the prior call-site requirement. + +Accepted ADR-0046 requires continued unrelated eligible work and does not require +strict claim-class priority. This is an implementation correction, with no new +ADR, grant, lease, attempt, terminal-audit or publication-ownership contract. +The regression requires actual unwrapped transport acceptance, no business +construction, unchanged recovery attempts and every failed terminal request +remaining intact without terminal audit while the grant stays denied. + +The unchanged baseline fails the new progress regression after its first +lease-cycle check. After correction the full actual producer suite passes +19 cases, zero failed/skipped; the new regression passes in 10.634 seconds. +Release solution build has zero warnings/errors. All 1,864 unit, 312 +architecture, four contract and 176 Docker-free integration cases pass again; +full format/diff and document checks pass. Two fresh independent reviews of +this additional producer correction remain pending at this initial receipt. + +Producer correction review round 1 used two fresh agents against +`a95ae2ec..bd51a974`. GPT-6-astra/xhigh passed 80 producer/store integration, +40 architecture and 20 ownership/bounds/observation unit cases. +GPT-6.1-sol/high passed all 19 producer and 40 architecture cases. Both approve +without a verified actionable finding; no fix was needed before round 2. + +Two new agents independently reviewed the same frozen correction in round 2. +GPT-6.1-sol/xhigh passed 80 producer/store integration, 40 architecture and +20 focused unit cases; GPT-6-astra/high passed all 19 producer and all 312 +architecture cases. Both approve with no verified actionable finding. All +independent runs have zero failures/skips; neither round relies on earlier +scope approvals to cover the producer change. + +The verified delivery/alias corrections and the adjacent producer correction are +complete, each with both fresh independent review rounds. Final document/diff +checks pass; the earlier receipts retain their exact as-of scope. The +[live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own +correction-head CI; its exact source and artifacts must be inspected before the +PR description records success. Maintainer review and merge remain pending; +this correction starts no P02b-4 work. + +### P02b-3 merge and closeout (2026-10-15) + +The maintainer merged [PR #31](https://github.com/HodeTech/LearnStack/pull/31) at +2026-10-15 16:45:06 UTC. GitHub records final PR source +`0fa7dc869d5b0f704a2d05313226d3d1b0f98510` and squash merge +`ed60157c14d33fad926fd201b49c08e2d24eed1f`, whose parent is previous main +`6a277770e46a7f4ea3574d9d6891d1802cb8fa90`. Source and squash merge have the +identical tree `57cab77ffb486689de18abbf741b6186dcf7de6f`. Development incorporates +the main merge without switching branches or rewriting published history. + +All seven required checks pass in the +[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38755136480) +for that source; CodeRabbit also reports success. The tested synthetic merge is +`a131ca6b59f750c69d4465b46a0bd1a5717dcd0a`. The seven required contexts and strict +up-to-date protection were re-read from GitHub after merge and remain enabled. +Verified artifacts record: + +- **3,745 backend passes**, zero failures/skips: 1,864 unit, 312 architecture, + four contract, 176 Docker-free integration and 1,389 Docker integration cases. + All ten alias/progress PostgreSQL regressions pass on this exact source. +- **1,616 guarded frontend passes**: 1,556 web and 60 SDK, zero + failures/skips/todos; lint, typecheck, builds and native-ingress proofs pass. +- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, with + matching source/checkout identities and report digests. Automated accessibility + is 1 throughout, CLS is 0 and normalized initial JS gzip is at most 106,554 + bytes. Proof finishes in 649.646 seconds within the 12-minute bound; owned + cleanup passes. Nine timing advisories remain warnings, not production p95. + +These are final PR-head results, not a new post-merge or local full-stack run. +**P02b-3 is closed.** All six steps and verified review corrections are delivered: +durable acceptance, shared inbox/ledger, independent retries and terminal MUST +audit, fenced business completion, both Active defaults and semantic Seeder +handoff, plus production-census enforcement. Compatible-alias retries preserve +retained envelopes; rotating acquisition keeps unrelated eligible producer and +subscriber work progressing during terminal-audit failures. Each step and +correction bundle retains its two independent review rounds above. Earlier dated +receipts keep their pre-merge wording; this closeout changes no Accepted ADR. +Publication remains at least once. Phase 02b remains in progress. + +**Next: P02b-4 decision pass.** G9 and reserved, undrafted ADR-0047 must settle +job storage under the four-role model, tenant-context and transaction ownership, +safe enqueue, retries/terminal audit, queue/job identity, the adapter's demand +gate, and package/licence choices before runtime implementation. The +[background-job scope](phase-02b-events-auth.md#background-jobs) owns these questions; no job definition +or dashboard route belongs to that packet. + +API authentication, realm reconciliation, BFF sessions and phase-exit enforcement +remain P02b-5–8 in the [packet table](phase-02b-events-auth.md#packets-and-decision-gates). P02b-8 owns +retained-envelope erasure inventory. Operator replay permissions/routes, audited +recovery and privileged erasure execution remain Phase 03; broker adapters, +mapped readiness, retention/purge grants and production measurements remain +Phase 11. This documentation closeout starts no later packet or new decision. + +**Documentation-only closeout validation.** Five local Release corpus controls +and seven ADR lifecycle/workflow controls pass, zero failures/skips. Relative +links/fragments, added prose wrapping and whitespace checks pass. Every earlier +P02b delivery/review receipt and every ADR file is byte-preserved against the +accepted PR source. Only 11 Markdown files change; runtime suites are not rerun +locally for this closeout. The final PR artifacts above supply their evidence. + +## P02b-4 — Background jobs + +### P02b-4 decision package (2026-10-15) + +**Accepted — 2026-10-15, @cemil.** The maintainer approves **H1: stock Hangfire +plus an authoritative LearnStack job record**, expanded P4 infrastructure, +[ADR-0047](../decisions/0047-transactional-background-job-runtime.md), its bounded +supersessions/additive seams and all nine implementation steps below. +Acceptance and dated prior-ADR disclosures commit before runtime, package, +migration or grant changes. Development stays on `development`; prior Accepted +ADR bodies/metadata and P02b-0–3 receipts remain unchanged. Runtime, dependencies, +storage/grants, enforcement and production job proofs remain unimplemented. + +#### Problem and scope + +Ship reusable durable tenant job infrastructure covering short transactional work, +long external prepare/execute/finalize, isolated dispatch slots, cross-instance +per-tenant admission, and recurrence/tenantless fan-out. Hangfire carries opaque +wakeup/tick references; LearnStack is the only business job authority. No dashboard, +production job/recurrence, ffmpeg implementation, Hub endpoint or privileged +maintenance executor is added. P02b-5–8 authentication/session work is separate. + +The [ADR workload envelope](../decisions/0047-transactional-background-job-runtime.md#workload-envelope-and-first-consumer-obligations) +owns mechanism/feature boundaries. Phase 04 keeps real media providers, process/ +resource limits, artifacts and coordinated concurrency keys; triggered 02c keeps +phone-home definitions; 08a/08b keep notification/reminder domain semantics; 11 +keeps licence operational surround and privileged audit DDL/purge. These feature +owners no longer need to invent the selected P4 long-operation/fan-out foundation. + +#### Verified premises and document review actions + +Current transaction/producer/context/audit/entitlement seams and first consumers +were traced after the P02b-3 closeout. Three read-only design inspections cover H1 +handoff (GPT-6-astra xhigh), external/capacity (GPT-6.1-sol xhigh) and recurrence/ +privilege/schema (GPT-6.1-sol xhigh). They supplement, not replace, the earlier +comparison experiments and correction reviews recorded below. No runtime proof +is claimed by these source/design inspections. + +| Verified gap | H1 contract/action | +|---|---| +| Vendor enqueue/state commits separately | Immediate authoritative INSERT + durable generation-fenced handoff/repair; callback never depends on ACK having arrived | +| Wakeup duplication can become later retry | JobId plus wake generation; only business transition advances generation; resend retains it | +| Stock retry count differs from six committed starts | Separate app-role admission/start receipt; capacity/duplicate/deferred work spends no attempt | +| Current request owner has no job participant | Closed root/stage/recipient participants, exact mode mapping and existing eight setters | +| Ambient/SystemActor is not a privilege boundary | Sticky positive request admission, root/nested/direct Platform/provisioning denial and separate bypass/admin-entry guards | +| Long ffmpeg does not fit a DB transaction | Durable plan/execute-intent/outcome checkpoints; external execution/reconciliation with no business UoW | +| Lease expiry does not stop provider work | Positive quiescence or quarantine; unresolved reservations never expire into free capacity | +| Organization-scoped capacity misses other orgs | Tenant-wide control mutex/reservations; plan/operational ceiling applies across orgs/instances | +| Framework can enumerate no tenant today | Named minimal lifecycle projection grant, bounded durable recipients and actual-row witness admission; no caller tenant selector | +| Recurrence revision can duplicate a logical slot | Unique recurrence-key/UTC-slot independent of revision, monotonic activation, stable jitter and checkpoint/recipient atomicity | +| Filters can be bypassed on vendor fallback | Migration-owned below-filter state/metadata guards and bounded log provider, pinned real-worker dirty controls | +| Whole-schema tests assume every table is app-readable/RLS tenant data | Exact table classes, expected vendor/control 42501 denial, no unclassified-table exclusions | +| No general runtime was Accepted | H1 retains audit-maintenance Hangfire choice; exact bounded identity/context/storage changes get dated Amendment navigation | + +#### Accepted decisions + +| Gate/contract | Accepted H1 contract | Vehicle | +|---|---|---| +| G9 runtime/storage | Pinned stock Hangfire wakeups, authoritative tenant/org job row, exact public vendor-control class and four roles | ADR-0047; ADR-0003 Amendment for grant/confinement extension; canonical Standards 05/20 on implementation | +| G9 ownership/submit | Typed own-module definitions, exact writable announcement, identifier-only frozen payload, immediate INSERT/ancestral receipt | ADR-0047; ADR-0057 extension and source guards | +| G9 context/owner | JobExecutor alone; sticky ordinary ceiling; exact ISender roots/framework requests; staged owner participants | ADR-0036/0032 replacements; additive ADR-0040 and closed ADR-0052 mode extension | +| G7 job part | Sixth WriteJobTerminalAsync, actual job-row witness, terminal state/MUST audit atomic | ADR-0044/0033/0046 navigation; Tenancy platform.job.dead_letter catalogue/matrix | +| G8 job/recurrence part | Conditional routing/status exemption with exact grants/censuses, bounded diagnostics, metrics/health and terminal MUST | ADR-0046 / Standards 18 Required Behaviours extension; no general background/privileged exemption | +| G9 profiles/capacity | Short transactional or staged external execution; renewable authority, positive quiescence, tenant reservations and disjoint pools | ADR-0047; real role/capacity/stale-effect proofs | +| G9 recurrence/fan-out | UTC interval/daily, CoalesceLatest, durable slot/jitter, minimal lifecycle reader and restricted recipient producer | ADR-0047; exact Standards 05 enumeration exception and ADR-0057 producer origin | +| G9 retry/readiness | Six normal starts; separate six finalize starts/recovery probe bounds; unknown/Pending defer, explicit retired tombstone | Standards 09/20, ADR-0047 mixed-version/capability queues | +| G17 labels/observation | Finite definition/profile/recurrence/group categories, no tenant/org/job/trace labels; memory snapshots | Standards 10 with first emitters | +| G18 job payload/diagnostics | Identifier-only 262,144-byte parameters, 65,536-byte plan/outcome checkpoints and 256-byte failure descriptors; durable-store erasure inventory remains P02b-8 | ADR-0047; bounds/guards with implementation, retention/purge authority remains Phase 11 | +| Dependency/licence | Core/NetCore 1.8.25, PostgreSql 1.21.1, Newtonsoft 13.0.4; stock shared assemblies, concrete graph/notices/source/relinking qualification | ADR-0047 and implementation packaging evidence; outside ADR-0035 gated set | + +G9 and the new job parts of G7/G8/G17/G18 are Accepted — 2026-10-15. +Existing G7/G8/event accepted dates and receipts are preserved. At implementation, +production business and recurrence registries independently assert zero definitions; +nonempty real runtime subjects and fixture-only definitions carry enforcement and +behavior proofs. Acceptance claims no passing runtime census or production proof. + +#### Runtime bounds and observation + +Bounds below are accepted inputs for this expanded H1 contract. Invalid values or +relationships refuse startup before workers; SQL/database time and actual task +ownership remain authoritative. + +| Bound | Accepted value | +|---|---| +| Independent stock server pools | Transactional 1, external 2, control 1 workers by default; finite dedicated feature pools, at most 8 pools/64 queues, 1–16 workers per pool, sum at most 32 per API instance | +| Operational tenant/group ceiling | Positive 1–1,024, default 1; optional Hard LimitKey intersects it; no tenant-supplied pool/group | +| Retained actual overruns/cleanup | Stop-new-start threshold 4 per pool; atomic accounting, retain every admitted task; hard bound configured workers + 4, at most 20 per pool; other pools progress | +| Outstanding synchronous bridge calls | At most 4; wait at most 10 s, retain actual operation; do not block other control lanes | +| SQL and external reconciliation probe | SQL positive, at most 5 s/default 5 s; provider probe positive, at most 30 s/default 10 s | +| Short root/prepare/finalize | Positive, at most 5 min/default 30 s; no long external operation inside | +| External run wait | Positive, at most 24 h/default 1 h; immutable per-attempt deadline | +| Lease / renewal | Lease 15 s–10 min/default 60 s; renewal 1–60 s/default 15 s; lease > twice renewal + twice SQL timeout + 5 s | +| Quiescence cancellation grace | Positive, at most 30 s/default 30 s; expiry never releases an unproved reservation | +| Control poll / snapshot | Poll 50 ms–1 s/default 200 ms; snapshot 1–60 s/default 5 s; successful work does not force scans | +| Handoff repair grace / batch | 15–300 s/default 60 s; at most 100 rows per quantum; same-generation resend | +| Recovery probe cadence / unsuccessful budget | 5–300 s/default 30 s; 6 unsuccessful probes then quarantine; Running probes bounded by attempt deadline/grace | +| Shared shutdown joins | Positive, at most 30 s/default 30 s across pools and bridge; no per-task reset | +| Progress heartbeat deadline | At least lease + 15 s, at most 15 min/default 75 s; renewal/control progress counts, not long work completion | +| Parameter / plan / outcome / failure descriptor | 262,144 / 65,536 / 65,536 / 256 UTF-8 bytes | +| Recurrence interval / fan-out page | 1 min–366 days, UTC anchor; jitter 0–min(period, 2 h); at most 100 routes/page | + +A plan cap is resolved through IFeatureFlags, capped by a positive operational +ceiling. -1 means operational ceiling, 0 means no new admission, invalid/Soft/ +undeclared keys fail safely. No Media LimitKey is invented by this packet. + +Standards 10 owns final names/label inventory. Job observation includes pending, +oldest eligible, deferred, retained/quarantined/reserved capacity, bridge repair, +finalize/failure/lease loss, fan-out progress and heartbeat signals. Confirmed +failure differs from unknown outcome. Register jobs health, unmapped; preserve +healthz liveness and Phase 11 readyz/production-alert ownership. Normal valid +long-running work is healthy; stale/faulted/retained/quarantined work is not. + +#### Approved implementation steps + +Every step commits its implementation/validation, runs two fresh independent +review-agent rounds, verifies/fixes findings and commits corrections, then advances +automatically. Critical authority/state-machine reviews use GPT-6-astra xhigh; +independent proof/composition/corpus lenses use GPT-6.1-sol high/xhigh. Each round +uses new reviewers. A new decision outside this accepted package returns to the +maintainer before dependent work. Development stays on `development` throughout. + +1. **Acceptance and typed contracts.** Commit final acceptance/dated Amendment + disclosures first, then add scheduling/profile/recurrence/identity contracts, + closed registries, request-scope admission and Jobs project boundaries. Register + canonical catalogue obligations without claiming enforcement before it ships. +2. **Storage, dependencies and guarded bootstrap.** Add exact pins/graph/notices; + Platform migrations for authoritative/control/capacity/recipient and stock + vendor schema, immutable/transition/metadata guards, RLS/grants/indexes and + canonical Standards 05. Prove fresh/Down, every-table classes, expected 42501, + exact role/source guard, schema 23, below-filter containment, bounded vendor SQL + and real index plans; keep the unguarded notification reconnect path disabled. +3. **Submission and app-role admission.** Implement trusted producer stamping, + immediate INSERT/receipts, routing leases, scoped read-only envelope validation + and separate committed start receipts. Prove rollback/absorbed refusal, + getter/stale/read-only attacks, exact org/module scope, unknown/deferred readiness + and no handler construction before admission. Capacity integration follows step 6. +4. **H1 wakeups and independent pools.** Implement bridge/reconciler, exact two + wrapper targets, generation fencing, guarded native connection factory and + disjoint server queues/pools. Prove real pinned worker create/init/ACK crashes, + duplicates/early/stale callbacks, vendor loss/fallback, malformed invocation, + bootstrap refusal, retained synchronous calls and construction-only fixture wiring. +5. **Transactional owner and terminal audit.** Add root participant/gate, scoped + ordinary ceiling, async attribution and fair retry/recovery/terminal control. + Prove business/outbox/jobs/audit/completion atomically, lock-wait expiry, + Result/exception parity, uncertain COMMIT, no seventh start, actual-row sixth + audit seam substitutions, and terminal-audit backlog progress beyond a lease. +6. **Tenant capacity reservations.** Implement group mutex/reservations and optional + Hard LimitKey resolution. Prove two instances/orgs share a tenant cap, capacity + refusal spends no attempt, unlimited/zero/downgrade/fault cases, exact app grants + and no TTL release of unresolved external occupancy; keep independent pools live. +7. **External prepare/execute/finalize.** Implement immutable stage/attempt receipts, + confirmed ExecuteIntent, no-UoW external adapter, renewal, typed reconciliation, + quiescence proof/quarantine and bounded finalization. Prove each crash/unknown + COMMIT boundary, provider accepted-before-ACK, paused-old-start/NotFound traps, + stale outcomes/revisions, simultaneous overruns/cleanup saturation, no seventh + effect and domain known-failure/terminal behavior without rerunning external work. +8. **Durable recurrence and restricted fan-out.** Implement frozen monotonic manifests, + UTC slots/CoalesceLatest/jitter, minimal lifecycle projection, atomic pages/ + recipients and witness-bound app submission. Prove mixed revisions/ticks, + suspended licence targets, cohort bounds, NULL-org dedup, forged/cross-tenant + witnesses, child acknowledgement loss, target scope/parameter binding, bounded + fairness and no general selector. +9. **Enforcement and packet closeout.** Finish full observation, exact production + censuses/planted violations, all carrier/feature/skill handoffs and the new job + skill. Run complete backend/frontend/demo regression and packaging/boot proof; + open the development → main PR with exact evidence. Real CI and maintainer merge + remain separate from local completion; zero production business definitions. + +#### Expanded H1 proposal review + +The final contract is drafted against the selected H1/expanded direction. The +historical receipts below approve only their earlier document revisions; they do +not substitute for two fresh reviews of this route-specific proposal. Current +review/validation evidence is appended here after it actually runs. + +Round 1 reviewed proposal commit `fa539176` with three fresh independent reviewers: +GPT-6-astra xhigh (state/authority), GPT-6.1-sol xhigh (external/capacity) and +GPT-6.1-sol xhigh (recurrence/corpus). All approve the Proposed documentation; +none accepts the ADR or authorizes runtime. The state reviewer found one minor +carrier omission: Standards 01/17 now explicitly distinguish the authoritative +tenant envelope from opaque vendor wakeups/ticks. No confirmed lifecycle, +unknown-COMMIT, generation, terminal-audit or ordinary-authority defect was found. + +Self-review additionally pins the disabled stock notification reconnect path and +server-side SQL deadlines, including the counter aggregator's unlimited driver +timeout. It makes future-due handoff checks and recurrence target parameter/scope +binding explicit. These are proposal clarifications, not runtime changes or proof. +Local validation passes five Release corpus tests, seven ADR workflow controls, +1,059 local links and 321 fragments, added prose wrapping and whitespace checks. +Prior ADR files and P02b-0–3 receipts remain byte-preserved against `71568e78`. +Fresh Round 2 reviewed the corrected complete proposal before final approval. + +Round 2 paired new GPT-6-astra xhigh (architecture/security/state) and GPT-6.1-sol +xhigh (corpus/recurrence/proof) reviewers on `29cc4c15` and the correction captured +by `40c9f9b8`. The latter fixes the retained-overrun bound: four is the atomic +stop-new-start threshold; already admitted workers may overrun together and must +remain owned, with a conservative workers-plus-four bound. Both reviewers verified +that correction and approve the Proposed documentation with no remaining required +findings. Simultaneous-overrun behavior is an explicit implementation proof duty. + +Final local checks again pass five Release corpus tests, seven ADR workflow tests, +1,059 links and 321 fragments with zero errors, prose/whitespace and preserved +historical records. All eleven changed files are Markdown; no runtime/dependency/ +migration/grant change or job production proof is claimed. Final maintainer +acceptance of ADR-0047 and this nine-step package remains required before runtime. + +#### Maintainer acceptance (2026-10-15) + +The maintainer explicitly approves the final ADR-0047 and this nine-step package. +G9 and the new job parts above are Accepted. Dated numbered Amendments in the +fifteen named prior ADRs disclose only the bounded replacements/additions; every +original byte, acceptance metadata and earlier amendment remains preserved. +The decisions index, glossary, current status carriers and first-consumer handoffs +now distinguish this accepted contract from pending implementation. + +The review/validation receipts above remain evidence of their Proposed revisions; +their pending-approval statements are historical. This acceptance creates no +runtime, dependency, migration, grant or enforcement evidence. The acceptance +commit precedes every implementation change; each later step owes its own +validation and two fresh independent review rounds. + +#### Earlier proposal and correction receipts (historical) + +These dated receipts precede the H1/expanded selection above. Their then-current +open-choice/scope statements describe those revisions, not this final proposal. + +#### Decision review and approval readiness + +The following receipts describe the earlier proposal reviews, not final current +readiness. The subsequent workload/corpus review reopens the gaps named above; +earlier review agreement does not select a runtime or override maintainer findings. + +Two fresh independent review rounds inspected the Proposed ADR/package against +current source and Accepted records. Each round paired GPT-6-astra xhigh for +transaction/security architecture with GPT-6.1-sol xhigh for corpus/proof coverage. +The original three scoping inspections are separate from those four reviews. + +- Round 1 corrections: explicit TenantWide/Organization declarations and exact + announcement matching; closed transient/permanent outcomes; finite option + maxima; trusted direct-consumer operation identity; named ADR-0040/0052 + framework read-only extension. Both reviewers rechecked the revised clauses + and found no remaining approval-blocking issue. +- Round 2 corrections: explicit conditional G8 job-scheduler bypass exemption, + ADR-0020's licence-job vendor/identity handoff and first-triggered 02c/08a + recurrence ownership, with architecture 24/26 included. Follow-up inspection + confirmed the blocking issues were closed. Related source checks also name + ADR-0015's exact dashboard bullet, app-side UUIDv7 identity and the unaffected + Hub/superseded-record boundaries. The package's earlier queue summary was + aligned with the same recurrence answer. + +Local validation passes: five Release corpus controls, seven ADR status/workflow +controls, relative links/fragments, added prose wrapping and whitespace checks. +All earlier P02b delivery/review receipts and every prior ADR file are byte-preserved +against `71568e78`. These are document/source checks; no job runtime exists and +no runtime acceptance proof is claimed. Maintainer approval remains pending. + +#### Hangfire comparison follow-up (2026-10-15) + +The maintainer requested this assessment rather than accepting the initial +PostgreSQL proposal. The [expanded ADR comparison](../decisions/0047-transactional-background-job-runtime.md#hangfire-alternative-assessment-2026-10-15) +owns alternatives, trade-offs, package/source pins and evidence limits. Stock +Hangfire plus an authoritative job record is viable; public transaction-aware +storage customization is also physically feasible. Neither is accepted here. + +Three research agents inspected exact upstream/package sources, current owner +contracts, dependencies, storage privileges and lifecycle boundaries. Isolated +database experiments passed eighteen focused cases on fresh PostgreSQL 18.4; +the owned container was removed and no existing service/database was touched. +The native transaction spike used SDK 10.0.302 outside the repository, not pinned +10.0.112. Separate exact-version invocation probes and .NET 10 dependency/basic +load checks are recorded in the ADR. These do not prove production audit, RLS, +worker/retry/cancellation or complete provider support. + +Two fresh reviewers, GPT-6-astra xhigh and GPT-6.1-sol high, checked the revised +comparison against sources and experiments. Both approved the evidence/framing +without required corrections; neither approved runtime implementation. Local +document/corpus/ADR controls pass. Runtime choice and final acceptance still +belong to the maintainer; a Hangfire choice revises the detailed design and steps +before any implementation. + +#### Workload and corpus correction pass (2026-10-15) + +Verified the maintainer's findings against current code and the original +authorities. Three read-only inspections covered early-consumer workloads +(GPT-6-astra xhigh), runtime correctness (GPT-6.1-sol xhigh) and corpus/governance +(GPT-6.1-sol high). These are source/document inspections, not new runtime tests. + +- Phase 04 already requires long ffmpeg work, its own capacity and a tenant limit. + The single transactional lane does not deliver that. The ADR now names the + separate external prepare/execute/finalize contract and an explicit first-use + gate, with a maintainer scope choice before route-specific acceptance. +- Phase 04's nightly media lifecycle can precede 02c/08a recurrence. Its trigger, + restricted tenant enumeration and isolated tenant submissions are distinct from + Phase 11's privileged audit DDL/purge. Phone-home's 02c ownership exists in + ADR-0020 Implementation notes; its missing phase-plan entry is restored. +- The candidate now uses unlocked preflight and a final lock/time recheck, an + ordered Result/exception retry table, deferred unknown/Pending definitions and + explicit retirement, plus a SystemActor Platform ceiling for root/nested/direct + execution. Strict org admission and role/column/index proof duties are explicit. +- Corrected exact authority locators, dated Amendment terminology, the implemented + credential-rule widening obligation, conditional consequences and the decisions + index. Proposed glossary terms precede implementation. Quartz.NET is a documented + candidate requiring its own qualification; no unsupported rejection is made. +- Skipped the alleged missing Date/Deciders violation: neither canonical template + requires those fields. The existing Draft date is honest Proposed metadata. + Kept PreparedDeliveryOwner delivery-specific; participant and commit gate are + separately named. Long URLs/tables remain exempt from prose-width limits. + +No Accepted decision, runtime, migration, grant or previously completed delivery +receipt is changed. This pass prepares the choice; it does not accept or implement +one. + +Correction review round 1 paired fresh GPT-6-astra xhigh (architecture/security) +and GPT-6.1-sol high (corpus/proof) reviewers over the corrections after `46ca923c`. +Both approved the Proposed documentation correction with no required findings; +neither approved a runtime or workload-scope selection. Local validation passes: +five Release corpus tests, seven ADR status/workflow controls, 1,035 local links +and 323 fragments, prose wrapping and `git diff --check`. All prior ADR files and +P02b-0–3 receipts remain byte-preserved against `71568e78`. These checks run on +documentation; no new runtime proof is claimed. + +Correction commit `ec1a5520` was reviewed in a fresh second round by GPT-6.1-sol +xhigh (architecture/security) and GPT-6-astra high (corpus/evidence). The corpus +review found one wrong section locator for ADR-0017's Jobs row; the linked +Defense-in-depth heading replaces it, and focused reinspection verified the fix. +Both reviewers approve the documentation correction with no remaining required +findings. Final local link/fragment checks count 1,036 / 324 with zero errors; +earlier ADRs/receipts and the docs-only scope remain verified. Runtime selection, +workload scope and final route-specific ADR approval remain pending. + +#### Validation and carrier ownership + +Use the existing provider/migration/MediatR/audit/architecture/integration workflows +and run-tests-locally. Test real PostgreSQL, guarded roles and the actual pinned +Hangfire workers; no EF in-memory substitute establishes isolation/atomicity. +Stage dependencies/feature definitions stay explicit; no mock production job. + +Acceptance/implementation reconciles ADR-0003/0010/0015/0017/0020/0023/0028/0032/ +0033/0036/0040/0044/0046/0052/0057 through dated Amendment navigation/additions, +plus ADR-0047 and the index. Standards 01/02/05/06/09/10/11/15/17/18/20/21/index receive +only implemented current rules; canonical DDL stays 05, metrics 10, proof names 21. +Standards 01/17 distinguish the tenant-bearing authoritative job envelope from +opaque vendor wakeups and tenantless ticks without weakening business isolation. +Architecture 04/09/16/24/25/26/29/30/31/33, Tenancy audit/permission specs, glossary, +root guidance/readmes, compose/launcher fixture wiring and applicable/new skills +must follow the same delivered boundary. Phase 02c/04/08a/08b/11 handoffs keep +business definitions/provider/privilege owners explicit. Hub endpoints are unchanged. + +P02b-8 inventories job/attempt/plan/outcome/reservation/recipient copies and vendor +control metadata for erasure. Phase 11 owns actual retention/purge authority and +intervals; stock vendor expiry deletes control metadata only, never authoritative +business intent. Phase 03 owns operator replay/reconciliation/permission/runbook; +no recovery route or unsafe reservation-release switch is exposed by P4. + +### P02b-4 Step 1 — contracts and authority (2026-10-16) + +**Complete — both fresh independent review rounds pass.** +The acceptance commit is `affa0aca`; this step follows it on `development`. + +SharedKernel supplies typed job/attempt/occurrence/recipient identities, the typed +scheduler port, immutable definition/profile/request/capacity/recurrence metadata +and external Execute/Reconcile/finalization contracts. Frozen registries validate +module ownership, exact roots/nested requests, profile/queue/pool bindings, finite +readiness and recurrence scope. Identifier-only parameter/plan/outcome serialization +uses closed DTO shapes, canonical round-trips and frozen options/resolver state. +No production business or recurrence definition is added. + +Application admission holds an immutable positive request ceiling independently of +later accessor changes. Exact framework pre-reads select physical ReadOnly through +the existing pipeline. Direct privileged/delivery/admin entry refuses even through +a fresh service scope or permissive platform gate. A guarded lazy bypass-source +facade checks every synchronous/asynchronous connection acquisition, including warm +pools, and owns cleanup. API/Seeder register the same empty job catalogues; neither +registration activates a scheduler, vendor, migration or worker. + +Two architecture methods pin the current admission/credential callsites with +planted violations. The nineteen complete ADR-0047 obligations remain Registered; +these slice proofs do not claim the later runtime is implemented. Existing exact +credential/context/owner censuses stay enforced. The catalogue counts 221 methods. + +Initial Release validation passes the solution build with CI warnings-as-errors, +1,979 unit, four contract, 176 Docker-free and 1,389 Docker integration tests, with +zero skips. The first full architecture run reports 312 passed and two stale +expectations: the published method count and TransactionBehavior constructor pin. +Both are corrected without widening module/DbContext permissions; an architecture +rebuild and six focused corpus/constructor reruns pass. This gives 314 unique +passing architecture cases and 3,862 unique passing backend cases across the +full runs and focused corrections; it is not a second full architecture run. +Formatting passes for all 67 changed C# files. The documentation check resolves +2,506 local links and 590 fragments, with no wrapping/whitespace errors. Every +ADR/index remains byte-identical to acceptance commit `affa0aca`; earlier delivery +and proposal-review receipts stay preserved. Both fresh independent review rounds +remain pending; later receipts record their actual results. + +#### Step 1 review round 1 + +Two fresh independent reviewers inspect `affa0aca..94b126b4`: GPT-6-astra xhigh +for authority/lifecycle/credential confinement and GPT-6.1-sol xhigh for contracts, +registries/serialization/recurrence and corpus evidence. Both request changes for +one independently reproduced Major each; neither finds a Platform escape or a +current production job caller. + +- A retained already-entered nested request can have an open top frame after its + root closes. The common request/owner admission now checks every ancestor, while + preserving awaited nesting and framework owner entry with no current request. + Real ISender regression proves refusal before handler construction; its dirty + case fails before the correction and its awaited positive control passes. +- A handwritten getter/init accessor can change the returned identifier after the + canonical reads. Closed identifier DTOs now require compiler-generated automatic + getters and init setters, preserving positional/nonpositional auto-properties + and constructor round-trip checks. Three dirty registration/read cases fail + before the correction and pass afterward. This is an immutable DTO convention, + not an arbitrary CLR-code sandbox. + +Root verifies both findings, adds six regression cases and applies the minimal +corrections. The corrected solution builds Release with CI warnings-as-errors; +1,985 unit, all 314 architecture, four contract and 176 Docker-free integration +cases pass with zero failures/skips. The 1,389-case Docker run above covers the +initial implementation; it is not rerun for these nonactivated job guards. No +vendor/schema/production definition is introduced. A fresh second review round +follows the correction commit before Step 2 starts. + +#### Step 1 review round 2 and closeout + +Fresh GPT-6-astra xhigh (authority/lifecycle/security) and GPT-6.1-sol xhigh +(contracts/registries/tests/corpus) reviewers inspect the complete corrected range +`affa0aca..bf433085`. Both approve Step 1 with no remaining required findings. +The authority reviewer independently passes 168 focused unit and 78 architecture +cases; the contracts reviewer passes 168 focused unit and 14 architecture cases. +All use existing Release binaries with zero failures/skips. These overlapping +checks are not added to the complete-suite counts above. + +Both verify the ancestry/accessor corrections, unchanged Accepted ADRs, exact +credential/owner boundaries and the honest zero-runtime-subject scope. Recurrence +precision is a named next-step constraint: before Step 2 fixes PostgreSQL storage +representation, reject sub-microsecond manifest facts before fingerprinting. +No production job or recurrence is activated to satisfy a census. + +The implementation commit is `94b126b4`; verified Round 1 corrections are +`bf433085`. Both fresh rounds and the validation recorded above are complete. +Step 2 now proceeds under the already accepted nine-step package. Remaining +runtime/dependency/storage/worker guarantees are not delivered by this closeout. + +### P02b-4 Step 2 — storage and guarded vendor bootstrap (2026-10-16) + +**Complete — both fresh review rounds and critical-fix verification passed.** +This step follows the completed Step 1 on `development` under Accepted ADR-0047. + +Two Platform migrations introduce seven authoritative job/control tables and the +pinned stock Hangfire version-23 inventory. Standards 05 owns their canonical +DDL/grants and the explicit vendor-control table class. Existing schema sweeps +enumerate all public tables, classify expected application SELECT denial, and +continue actual tenant/organization isolation checks as `learnstack_app`. + +The vendor connection factory crosses the existing guarded lazy source on every +acquisition. Reset-safe server statement/lock deadlines bound SQL execution; +Accepted ADR-0058 requires finite enabled driver I/O and adds five-second +idle-session cleanup. The post-acceptance implementation and real source/reset +proofs are recorded below. Bootstrap verifies version, guard bodies/triggers, +exact grants and +metadata before constructing the provider. No production wrapper, scheduler +or worker is activated by this step. Runtime admission, business completion, +external execution and recurrence remain Steps 3–9. + +Recurrence facts now reject sub-microsecond precision before fingerprinting so +durable PostgreSQL reconstruction cannot silently change a declared manifest. +The dependency graph, corresponding-source/notice kit and copied publish output +are part of this step's validation. Passing evidence and review dispositions are +recorded after the actual checks; source-only inspection is not a runtime proof. + +**New qualification boundary.** The exact stock counter component overrides the +driver timeout with zero. PostgreSQL statement/lock deadlines pass blocked-SQL +checks, but a response-withholding proxy leaves the actual component pending. +[ADR-0058](../decisions/0058-bounded-stock-hangfire-maintenance.md) is Accepted — +2026-10-16 for the selective maintenance configuration and ownership controls +reviewed in the [reassessment](#step-2-maintenance-reassessment). The earlier +socket-exception proposal is withdrawn. The +[acceptance receipt](#step-2-maintenance-acceptance-2026-10-16) records the approved +boundary; Step 4 runtime qualification remains pending. This step +claims no Step 4 runtime qualification. Source/reset and schema validation pass +after acceptance as recorded below; formal Step 2 review closeout remains pending. + +#### Step 2 counter-maintenance decision review + +The isolated exact-pin response-loss experiment is independently repeated by the +root agent on PostgreSQL 18.4: the actual stock counter task is still pending at +eight seconds; closing the owned proxy sockets settles it with NpgsqlException. +Both disposable containers/proxies are cleaned up. This proves the missing +driver bound, not the proposed replacement ownership behavior. + +A fresh GPT-6-astra xhigh reviewer requests two corrections to Proposed ADR-0058: +name both read/write I/O, and pace held/not-due returns because stock Core +immediately reinvokes successful components. Root verifies and incorporates both. +The shared pool minimum and real disposal/late-cleanup proofs address the same +review's availability caveat. A new GPT-6.1-sol xhigh reviewer independently +approves the corrected whole proposal with no required findings after checking +the exact Core/provider/Npgsql source and governance. Neither review claims +passing runtime tests for the unimplemented maintenance owner. + +#### Step 2 maintenance reassessment + +The maintainer returns Request changes, not acceptance, on 2026-10-16. The +initial proposal/reviews above are historical receipts; they do not close the new +findings. Two independent source/research agents, GPT-6.1-sol xhigh and +GPT-6-astra xhigh, verify the exact pinned Core/provider/Npgsql sources. Root +independently reproduces PostgreSQL 18.4 timeout behavior. + +| Review issue | Verified disposition | +|---|---| +| Supersession/additive scope conflated | Valid. Revised Proposed ADR-0058 distinguishes selective configuration replacement from additive ownership/health/test seams; its former socket exception is withdrawn. Acceptance will name both in ADR-0047's dated amendment. | +| Suppression loses all counter maintenance | False rejection premise in the earlier draft. Stock expiration deletes expired counters and compacts the two nonexpiring state totals; removal is now the proposed alternative. | +| Expiration's five-minute wait and minimum-two sizing | Valid distinction. Retry-loop/whole-pass occupancy differs from per-command I/O. Two was never a topology capacity proof; that proposed rule is withdrawn. Step 4 must enumerate and qualify the actual supported acquisition floor. | +| Aborted transaction retains former row locks | Not reproduced. A positive active lock is released on abort; a concurrent update succeeds before the timeout response is read. Idle-aborted session occupancy remains real and is tested separately. | +| Missing interval/inventory/proof specificity | Valid. Revised proposal pins exact component/filter inventories and the expiration interval, assigns enforcement to Step 4, and maps proofs to the two existing canonical rules. | +| Incorrect timeout anchor/ambiguous defaults | Corrected. The source link names Npgsql's actual timeout selection; driver defaults, statements and invocation waits are distinguished. | + +The proposed direction suppresses only stock `CountersAggregator` and optional +`StatisticsHistoryAttribute`, preserving stock expiration/heartbeat and every +finite command/socket requirement. Expiration still needs single-flight retained +ownership: cancellation does not enter its synchronous SQL or lock-acquisition +loops. Healthy pass pacing, shared shutdown and independent progress remain +pending actual-runtime obligations, not consequences assumed from suppression. +No production owner, filter removal or new source deadline is activated here. + +**Reproducible qualification commands** (Python 3, Docker and .NET 10): + +```bash +python3 third-party/hangfire/qualification/probe-maintenance.py +python3 third-party/hangfire/qualification/probe-pg-timeouts.py +``` + +The first command builds only a disposable exact-package project and starts an +owned random-loopback PostgreSQL 18.4 container. It invokes actual stock +`ExpirationManager.Execute`, the public filter-removal hook and actual stock +aggregation through an ACKing response-withholding proxy. The second uses the +PostgreSQL simple-query protocol to withhold client reads while an independent +observer inspects backend/lock state. Both use synthetic data, finite waits and +owned cleanup. They touch no development database or shared repository binaries. +Neither substitutes for `learnstack_outbox_admin`/real worker/owner proofs. + +**Measured counter footprint.** Exact stock version-23 schema, default indexes, +fresh/truncated table per case and autovacuum disabled for repeatable sizing. +The denominator is vendor transitions between cleanup passes, not business jobs. +Bytes are `pg_total_relation_size(counter)` including relation/index overhead; +they exclude WAL, replication, other vendor tables and production bloat. + +| Transitions | One-row ordinary success | Two-row transition envelope | +|---:|---:|---:| +| 1,000 | 1,000 rows / 172,032 B | 2,000 rows / 286,720 B | +| 10,000 | 10,000 rows / 1,048,576 B | 20,000 rows / 2,007,040 B | +| 100,000 | 100,000 rows / 9,650,176 B | 200,000 rows / 19,210,240 B | + +The actual stock expiration pass reduces those six cases to one/two live rows +and preserves the tested positive totals. Ordinary VACUUM does not shrink the +previously allocated footprint in these cases. Stock delete-then-insert compaction +is not atomic, can lose a subtotal and drops nonpositive raw sums; this experiment +does not prove exact statistics accounting. Removal loses new vendor timelines. +Cleanup outages and retained snapshots can grow backlog/disk, and failed vendor +wakeups have their own nonexpiring retention. No bounded-disk or recovery-rate +claim is made. + +The actual aggregator remains pending at eight seconds despite requested +cancellation and five-second server/driver defaults. Releasing its proxy sockets +settles the owned task with a driver failure; this proves the removed path's +qualification gap, not a passing replacement owner. PostgreSQL's active lock +control holds one relation lock; the aborted state holds zero and an independent +update succeeds. Two 350 ms statements pass a 500 ms per-statement limit; a +500 ms idle-in-transaction limit terminates the remaining aborted backend. +Idle cleanup is session hygiene, not a guarantee that an ACKing proxy releases +its client socket. + +Standards 20's existing `hangfire`-schema drift is independently corrected against +Accepted ADR-0047 (`public`). Proposed ADR-0058 changes remain approval-gated; +the two fresh proposal review rounds and their dispositions are recorded after +they actually run. + +**Revised proposal Round 1.** A fresh GPT-6-astra xhigh reviewer approves the +whole revised proposal, carrier edits and qualification artifacts with no +remaining findings. The initial component-name mismatch is corrected to the +actual `PostgreSqlHeartbeatProcess` type. Root reruns both committed-source +experiments successfully: all six footprint cases, expired/future controls, +public selective component/filter removal, eight-second blackhole retention and +late cleanup, and all PostgreSQL timeout/lock controls pass. Both owned containers +and temporary projects are removed. The reviewer independently checks 450 local +links/fragments, Python syntax and scoped whitespace. This is proposal review, +not either formal Step 2 runtime/schema review or maintainer acceptance. + +**Revised proposal Round 2.** A new GPT-6.1-sol xhigh reviewer independently +approves `f5dd3a44..446d0a5f` plus the qualification-source formatting and protected +timeout-probe cleanup edits, with zero required findings/nits. Both isolated +commands pass again in that review, including all six footprint measurements, +selective component/filter controls, actual expiration and the PostgreSQL +abort/session controls. Owned teardown completes. The probe's non-whitespace C# +characters are unchanged by formatting; folder-based format verification passes. +Neither reviewer modifies files or uses proposal approval as runtime acceptance. + +Seven ADR-parser controls pass and ADR-0058 parses as Proposed. The changed-doc +audit checks 37 Markdown files, 2,673 local links and 621 fragments with zero +errors; whitespace is clean. Accepted ADR bodies remain byte-identical to the +P02b-4 acceptance commit `affa0aca`. These decision experiments are not added to +backend regression counts. Both fresh proposal rounds are complete; maintainer +acceptance and Step 2/4 runtime qualification remain pending. + +#### Step 2 maintenance acceptance (2026-10-16) + +The maintainer explicitly approves the revised ADR-0058. Its status is Accepted — +2026-10-16. ADR-0047 Amendment 1 records the maintenance configuration replacement +and additive ownership seams without rewriting its body or acceptance metadata. +The dated proposal/reassessment/review receipts above retain their original +as-of state; this receipt closes only their maintainer-acceptance gate. + +The approved configuration suppresses only exact stock `CountersAggregator` and +`StatisticsHistoryAttribute`, preserving stock expiration/heartbeat, state counters +and required admission/retry filters. Finite enabled command/socket bounds remain; +there is no unlimited-command exception. The shared source gains reset-safe +`idle_in_transaction_session_timeout=5000`, with no shared `transaction_timeout`. +At this acceptance receipt the new setting is authorized, not implemented; +source/reset, successful outbox/delivery and real aborted-idle proofs remain Step 2 +work. Full Step 2 validation and both fresh runtime/schema review rounds remain +pending. + +Step 4 owns exact component/filter selection, one shared expiration owner, +one-millisecond internal interval, completion-based one-hour cadence, bounded +wait/cleanup, shared shutdown and truthful retained-maintenance health. It also +owns the final simultaneous physical-acquisition census, enforced supported +configuration/floor and independent progress under contention. No minimum-two or +nonpooled prohibition is accepted. Step 9 owns full observation/enforcement and +regression. Standards 05/20/21 and the Events and Outbox architecture carry the +accepted policy; the existing bootstrap and independent-capacity obligations +remain Registered. Acceptance claims no implemented maintenance owner, runtime +proof, packet closeout or production-capacity/disk guarantee. + +#### Step 2 implementation and validation after acceptance + +ADR-0058 is accepted in `14bf9c42` before its dependent runtime edits. The shared +guarded source now sends reset-safe five-second statement, lock and idle-session +deadlines. Explicit bootstrap refuses disabled/excessive idle deadlines. Real +`learnstack_outbox_admin` sessions prove cold settings, the same physical backend +after pool reset, idle and aborted-idle termination while the transaction remains +checked out, and healthy reacquisition. Dirty zero/5,001 ms startup controls fail +bootstrap beside a healthy production-source control. Existing outbox/delivery +store and execution proofs pass with the new shared-source setting. + +The two Platform migrations and canonical Standards 05 deliver seven raw +authoritative/control tables and stock vendor schema 23 with exact four-role +grants. Tenant/org scope, immutable envelopes/checkpoints, reservation evidence, +recurrence slots/recipients, six-stage ceilings, schema rollback/reapply and actual +ordered locking index plans have real PostgreSQL controls. Whole-schema discovery +classifies all 47 public tables, including five migration histories, rather than +omitting denied control/vendor tables. App SELECT denial requires actual `42501`. +The genericity source census now classifies embedded production SQL and decodes +its literals; Docker-trait discovery resolves partial declarations structurally. +The existing Education parent-constraint sweep includes the seven new raw job +relations with explicit guard/FK dirty controls instead of excluding them. + +**Validation before the final column-grant correction:** Release CI-style build passes +with zero warnings/errors; formatting and whitespace pass. Unit 1,995, +architecture 315, contract 4, Docker-free integration 176 and complete Docker +integration 1,552 pass: **4,042 backend cases, zero failures/skips**. The focused +197-case source/outbox/delivery run also passes and overlaps the complete run; +it is not added to that total. TRX runner checks confirm each assembly ran and +none skipped. Earlier failed intermediate runs and their corrected focused +receipts are superseded by this fresh full run. The final self-review correction +also refuses column-level `GRANT OPTION` during bootstrap. Its subsequent Release +build passes with zero warnings/errors and all 34 Hangfire storage cases pass, +including the new dirty grant and restored-role control. A fresh full run of the +correction commit is recorded with the independent reviews after it completes. + +Framework-dependent API publish passes the actual graph/source/notice verifier: +four vendor assemblies match original NuGet bytes, both exact corresponding-source +archives and eleven licence/notice files verify. Ten planted distribution defects +refuse and explicit recipient-replacement inspection succeeds. Hosting 10.0.12 +is verified in the referenced Infrastructure graph; API/publish use the shared +framework. The actual local host is .NET/ASP.NET Core 10.0.10, not an inferred +NuGet patch. The pinned provider SQL resources remain byte-identical upstream. +The complete Apache 2.0 text accompanies its original Dapper/Core notices. +Narrow stock-byte Git attributes preserve upstream line endings/notice whitespace; +forced `autocrlf=true` checkout verifies all 32 SQL/licence/notice input hashes. +First-party whitespace checks remain enabled. + +No worker, wrapper, production definition or recurrence is activated here. +Step 4 still owns selective component/filter suppression, the retained expiration +owner, enabled-path response-loss and supported-pool-boundary progress controls; +Step 9 owns complete enforcement. Those obligations remain Registered. The +full Step 2 implementation is now committed for its first fresh review round; +both round dispositions and verified fixes are recorded after they run. + +#### Step 2 review round 1 and verified corrections + +Three fresh reviewers examine `1b4ec7f4..583374f5`: GPT-6-astra/xhigh owns +schema/isolation/state/indexes; GPT-6.1-sol/xhigh separately owns the vendor/source +boundary and the proof/corpus lens. Their formal reports precede their authorized +fix work. Root verifies four required findings against the implementation: + +- **Eligibility proof:** volatile candidate clocks scan 6,000 future rows when + fewer than ten rows are due. Stable statement-time cutoffs now supply actual + index bounds. Four migrated-schema controls cover zero/five due rows and detect + the old volatile scan; live post-lock lease checks remain separately required. +- **Stored metadata:** a guard re-enabled after an invalid durable write did not + make the old partial startup scan reject every closed field. Shared read-only + predicates now serve post-redaction writes and startup, covering every vendor + metadata store. Twenty-six committed-drift/restored controls exercise them. +- **Stock shape:** names/version alone accepted a missing unique key required by + stock `ON CONFLICT`. Startup now checks 58 column facts, 17 keys/constraints, + 29 index definitions and nine sequence configurations/associations. Eleven + dirty/restored controls cover types/defaults/nullability/keys/indexes/sequences. +- **Embedded material:** stock Core merges Cronos 0.11.1. Its exact MIT notice and + corresponding source are now in the kit, independently pinned to source commit + `b2050abdf910bf5c3b7262d1a09d2c04c0f56f58`, with five new failure controls. + +The live decisions index also distinguishes delivered source/reset proofs from +pending Step 4 ownership and Step 9 enforcement. Accepted ADR bodies and earlier +proposal/delivery receipts remain unchanged. + +Correction validation passes: Release build with zero warnings/errors; **193 +focused PostgreSQL cases**, zero failures/skips, in the final focused TRX. The +actual fresh API publish verifies three source archives, twelve licence/notice +files and original stock assemblies; fifteen planted defects refuse and recipient +replacement inspection passes. Canonical guard SQL matches its embedded resource; +first-party links/fragments, history preservation and whitespace pass. + +The first full correction-head Docker rerun was interrupted when its existing +container stopped along with unrelated running containers. It is not passing +regression evidence. Full regression is rerun after this correction commit and +recorded with fresh Round 2. No worker/business activation is claimed here. + +#### Step 2 review round 2 and external-outcome corrections + +Three new reviewers independently examine `1b4ec7f4..a593cd22`: GPT-6-astra/xhigh +owns storage/state/isolation; two GPT-6.1-sol/xhigh reviewers separately own the +vendor/source and proof/corpus lenses. The latter two approve their code/proof +scope. Root verifies the corpus review's stale live CLAUDE entry and reconciles it +with the other status carriers, preserving dated historical receipts. + +The storage reviewer reproduces a prohibited second ExecuteIntent after a durable +successful external outcome using real app/dispatcher roles with guards enabled. +Root also verifies that quiescence without a known outcome was incorrectly enough +for retry/release/terminalization. The correction now: + +- refuses a new normal cycle after success or selected finalization; +- requires known outcome plus quiescence, or positive no-start, for a prior normal + attempt, excluding only the newly inserted receipt during its own admission; +- keeps unknown effects from pending/finalize/terminal transitions and reservation + release, retaining occupancy; +- preserves failed/cancelled retry and separately counted finalize stages. + +Five real-role regression cases distinguish success, failed, cancelled, selected +failure finalization and unknown effect. The original twelve-receipt positive +fixture now records retryable known failures before its last successful normal +attempt. An independent scratch PostgreSQL control observes the old Unknown path +commit a second ExecuteIntent, then verifies the corrected refusals and both +known-failure positive controls. Its owned containers are removed. + +**Validation boundary:** the preceding Release binaries pass Unit 1,995, +architecture 315, contract 4, Docker-free integration 176 and Docker integration +1,594: **4,084 cases**, zero failures/skips. The final outcome correction then +passes a fresh Release build with zero warnings/errors and **198 focused +PostgreSQL cases**, zero failures/skips. Full canonical DDL equality and first-party +link/fragment/history/whitespace checks pass. Fresh final-binary regression and an +additional independent critical-fix review follow the correction commit; neither +is claimed complete in this receipt. + +#### Step 2 final proof and closeout + +Initial implementation is `583374f5`; Round 1 verified corrections are +`a593cd22`; Round 2 outcome corrections are `5d55ee78`. A new GPT-6-astra/xhigh +reviewer independently approves `a593cd22..5d55ee78` with no confirmed findings. +It traces first/next admission, known/unknown effects, finalize, terminal and +reservation paths, SQL-null behavior and exact refusal-message controls; canonical +SQL parity and whitespace pass. This is source review, not a claimed test rerun. + +Fresh final binaries from `5d55ee78` pass **4,089 backend cases**: Unit 1,995, +architecture 315, contract 4, Docker-free integration 176 and complete Docker +integration 1,599, zero failures/skips. The final focused 198-case run overlaps +that total. TRX runner checks require all four assemblies and zero unexecuted cases. +Release CI-style build has zero warnings/errors; formatting passes. These fresh +receipts supersede the interrupted Docker rerun and earlier regression heads. + +The final API publish independently verifies three complete source archives, +twelve licence/notice files, the actual package/framework graphs and original +stock assemblies. Fifteen planted defects refuse; recipient replacement inspection +passes. A forced `autocrlf=true` checkout preserves all 36 upstream SQL/material/ +archive hashes. Canonical SQL/resource equality, first-party links/fragments, +Accepted ADR/history preservation and whitespace pass. Owned test/probe containers +and proxies are cleaned up; the two previously running Saydin services are running. + +Both required fresh Step 2 review rounds, all verified corrections and the extra +critical-fix review are complete. No unresolved finding remains in this step. +Step 3 now owns submission and app-role admission. Step 4 still owns actual worker/ +component/filter/maintenance/pool qualification; Step 9 owns full observation and +enforcement. Both extended ADR-0058 catalogue obligations remain Registered. +No production job definition, recurrence or worker is activated by Step 2. + +### P02b-4 Step 3 — submission and app-role admission (2026-10-16) + +**Step 3 complete; both fresh independent review rounds passed.** +Accepted ADR-0047 and the approved Step 3 plan govern this work; no new decision +or worker activation is implied by this record. + +Submission stamps the actual typed producer operation, live announcement and +physical transaction. The ordinary scheduling port accepts only its declared +parameter type and owning module, requires exact tenant/organization scope, +and inserts intent on that same transaction. Serialization and injected clock/ID +operations cannot borrow stale enrollment. Successful INSERT adds a sticky +produced-work receipt; the existing owner remains responsible for commit. + +Routing claims are separate from business attempts. An opaque returned-row claim +authorizes only the exact framework read/start requests. App-role envelope +validation uses a physically read-only frame before installing the verified +Ambient/SystemActor context. A separate writable start frame locks/rechecks the +row and can authorize later execution only through an acknowledged-commit +receipt. Unknown COMMIT is not activation authority; acknowledged commit remains +distinguishable from subsequent cleanup failure. + +The committed proof set covers real app-role isolation, immutable routing facts, +read-only validation, unknown/Pending/early/stale callbacks, concurrent starts, +lock-wait expiry, absorbed producer refusal and uncertain commit. No business +request/handler may be constructed by admission. Capacity-bound/external starts +remain deferred until their approved implementation steps. + +The first full run exposes three obsolete proof expectations: synthetic request +metadata is no longer allowed to select physical read-only mode; failed audit +rows remain durable after rollback; organization-scoped audit reads need the +same organization announcement. The corrected expectations retain all business/ +job rollback assertions. A planted overload also exposes a detector exception; +explicit declaration-count diagnostics now distinguish the violation from a +clean production baseline. + +Root independently reproduces DI stopping disposal after the first throwing +async disposable. The executor retains each actual unit before handler resolution +and awaits its cleanup if scope disposal faults, while keeping context/authority +installed. Physical connection-close controls pass for failed pre-read cleanup +and post-acknowledgement start cleanup. Activity observer faults also preserve +acknowledged receipts and restoration. + +Release CI-style build has zero warnings/errors. All **38 focused PostgreSQL +cases pass**, zero failures/skips, including real physical generation substitution +at constructor/clock/ID callbacks, read-only RLS and write-refusal controls, +forced concurrent starts, lock-wait expiry, dropped COMMIT acknowledgement and +cleanup faults. Typed Pending submission commits backlog but cannot route/start. +Unit 2,018, contract 4 and Docker-free integration 176 pass; the complete +architecture suite separately passes 315 cases, including dirty/clean capability +controls. Full solution formatting verifies 972 files without changes; seven ADR +parser controls and local link/fragment/history/whitespace checks pass. +The final combined Docker-free receipt and complete Docker regression remain +pending in this receipt. Neither formal review round is claimed by self-review. + +#### Step 3 review round 1 and verified corrections + +Initial implementation is `63a7f4ac`. Three fresh independent reviewers inspect +`483463fa..63a7f4ac`: GPT-6-astra/xhigh for authority/transaction boundaries, +GPT-6-astra/xhigh for PostgreSQL/admission/concurrency, and GPT-6.1-sol/xhigh +for proof/census/composition/corpus. Authority and proof reviews approve with +no findings. Storage requests one verified correction: submission inherits +the general app source's 30-second or unlimited command timeout, violating +the accepted positive SQL budget of at most five seconds. + +The storage reviewer independently reproduces the pinned-driver defaults and +real PostgreSQL blocked-INSERT behavior in a private disposable database. Root +confirms the actual production command and accepted bound. Submission now validates +the existing runtime options, applies an explicit command timeout and links its +SQL cancellation deadline. Successful INSERT alone records produced work; +statement failure still poisons the same owner. The same source review also +identifies that announcement/COMMIT surrounding framework commands needs a bound; +the executor gives each exact read/start frame its own SQL deadline, retained +through actual cleanup. Unknown COMMIT still creates no activation receipt. + +The combined Docker-free run passes all four assemblies: Unit 2,018, +architecture 315, contract 4 and integration 176 — **2,513 cases**, zero failures +or skips, with runner nonempty/zero-skip validation. The initial complete Docker +run executes 1,637 cases: 1,636 pass and one old domain-event cleanup test fails +because its reflection call still supplies three producer-enrollment arguments +after the signature gained two optional attribution arguments. Root checks every +reflection reference and adapts that test to five arguments without changing its +cleanup/rollback assertions. This failed run is not a passing regression receipt. + +The corrected Release build passes with zero warnings/errors. All 66 focused +PostgreSQL cases pass, zero failures/skips: the 40 Step 3 cases include a real +FK-lock-blocked INSERT and a live session withholding the actual start COMMIT +acknowledgement; the other 26 cover domain-event production and the adapted +reflection call. The timeout controls use an unlimited actual app command default, +prove the production deadline wins before their independent proof timeout, and +retain poisoning, no-false-receipt, physical cleanup and restoration assertions. +Unit 2,018 and contract 4 pass again. The combined full backend rerun remains +in progress; no empty-filter run is counted as evidence. Round 2 has not started. +No runtime outside the approved Step 3 boundary is added. + + +#### Step 3 review round 2 and final closeout + +Three new independent reviewers inspect the complete `483463fa..0ddcb3e7` +implementation and its `63a7f4ac..0ddcb3e7` correction: GPT-6-astra/xhigh for +application authority/owner boundaries, GPT-6-astra/xhigh for PostgreSQL/storage, +and GPT-6.1-sol/xhigh for proof/census/composition/corpus. All approve with zero +verified Blocker, Major or Minor findings. They inspect actual source and existing +receipts without shared builds or repository edits; their source reviews do not +claim independent test execution or a completed full regression. + +Root's final CI-split regression at runtime head `0ddcb3e7` passes Unit **2,018**, +architecture **315**, contract **4**, Docker-free integration **176** and Docker +integration **1,639** — **4,152 backend cases**, zero failures/skips. The correct +`Requires=Docker` run includes the forty Step 3 PostgreSQL cases; the focused +66-case receipt additionally repeats all 26 domain-event production controls. +Every counted assembly/slice passes the nonempty/zero-skip runner assertion. +Release build remains zero warnings/errors; formatting, seven ADR parser controls, +local links/fragments, prior-ADR/history preservation and whitespace pass. + +A mistaken `Category` filter mixed HTTP and Docker tests in one integration +process, exposing startup/Activity assertions; that run was canceled and is not +passing evidence. An empty filter was also rejected by the runner and is not +counted. The exact `Requires` slices above replace those commands without +weakening production code or test assertions. The earlier reflection-signature +failure remains recorded in round 1; its corrected domain-event test passes. + +Both required review rounds and every verified correction are complete. Step 4 +owns stock workers, bridge/repair, component/filter selection, expiration ownership +and supported-pool qualification. Step 5 owns business completion/retry/terminal +execution; capacity/external/recurrence and full enforcement retain their approved +Steps 6–9. No production business definition, recurrence, worker or dashboard is +activated by Step 3. Work remains on `development`; no push, PR or CI-head success +is implied by this local step closeout. + +### P02b-4 Step 4 — server-generation decision (2026-10-16) + +**Current authority:** [maintainer acceptance and the Step 4 adaptation](#maintainer-acceptance-and-step-4-adaptation-2026-10-16) +below accept ADR-0059 on 2026-10-16. The following preparation and review receipts +retain their original pre-acceptance state; implementation is in progress and full +production qualification remains pending. + +**Preparation only; ADR-0059 Proposed, approval pending.** Step 3 closes at +`def48a1a`, with runtime `0ddcb3e7` and both required fresh review rounds complete. +The complete H1/expanded implementation remains authorized, but the newly exposed +server-lifecycle choice needs explicit approval: ADR-0047/0058 select H1 and +retention, but do not select a constructor or automatic-restart policy. +No dependent worker, maintenance or restart runtime is activated here. + +Exact-pin source inspection exposes a lifecycle qualification gap: Core links +child shutdown to its restart token, catches canceled joins and disposes live +children before announcing a replacement. `ShutdownTimeout=Infinite` alone does +not fix automatic restart. A connection-floor calculation based only on one +configured generation is therefore conditional, not an accepted/proven number. +The stock missing-server and sustained-heartbeat-failure paths both matter. + +[ADR-0059](../decisions/0059-owned-hangfire-server-generations.md) proposes an +owner per pool, public stock process composition, synchronous context capture, +classified heartbeat retries and replacement only after actual stock/LearnStack +cleanup. An affected pool can remain unhealthy/stopped while its work is unresolved; +healthy pools remain independent. Host stop retains the existing one finite +external budget. Stock SQL/binaries, roles/grants, job attempts, reservations and +business authority are unchanged. A restart never supplies external quiescence. + +The decision-support probe uses actual pinned Core 1.8.25 dispatcher/server code, +provider 1.21.1 loaded identity and the repository's pinned Npgsql/Newtonsoft graph, +with fake storage to force lifecycle events. It uses no production credential, +existing service/database or shared repository build output. The launcher builds +in an owned temporary directory and takes versions from the central package file: + +```sh +python3 scripts/probe-hangfire-lifecycle.py +``` + +| Probe | Required distinction | +|---|---| +| Stock restart | Second generation while first actual work remains live; old context token handles are disposed despite infinite internal shutdown | +| Fault before synchronous capture | Actual required watchdog is held; stop occurs first; capture still executes, supplied workers stay closed, no early disposal/replacement | +| Fault after worker start | One actual generation remains owned through finite caller wait; release precedes shutdown witness and actual join | +| Managed supplied-builder fault | Guarded failure requests draining, retains earlier actual work and skips later builders | +| Raw supplied-builder fault | Dirty control reproduces early joined outer owner and disposed tokens while actual work remains live | +| Direct process-exit callback | Dirty child remains live inside Core cancellation after the finite host wait; parent terminates and joins it | +| Closed process-exit relay | Actual Core exit runs without joining the held private callback/stock process; child exits zero, without a cleanup/quiescence claim | + +These are assertion-bearing isolated feasibility controls, not LearnStack's +production worker/PostgreSQL regression or implemented catalogue enforcement. +Generic heartbeat retries, multiple pools, partial-resource construction, +source disposal, actual wrapper/business cleanup and restart-after-cleanup still +owe real production controls. Fatal memory/thread-start failures are not qualified +by the controlled managed-builder experiment. Missing context or elapsed waiting +cannot be interpreted as successful cleanup. + +#### Proposal review round 1 and verified corrections + +Two fresh independent reviewers inspect `def48a1a..f8ff691f`: GPT-6 Astra with +xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers +proofs/corpus/governance. The proof reviewer independently builds/runs all five +initial controls, checks links/history and interrupts the actual launcher to +verify owned-child cleanup. It approves without a finding. The lifecycle reviewer +confirms two Major decision gaps; root verifies both against pinned vendor source: + +- The cached provider fetched-job heartbeat cannot belong to the replaceable + control generation. The revision gives shared stock heartbeat/expiration an + API-instance owner independent of every pool; all Core servers exclude provider + component hosting. Control-pool-held-drain/healthy-pool renewal becomes an + explicit real-production proof obligation. +- Core's synchronous process-exit cancellation is a separate boundary from the + finite host wait. The revision selects zero last-chance wait and a closed, + asynchronous cancellation relay, requires child-process qualification and + forbids treating exit/forced token signals as cleanup or external quiescence. + +The lifecycle reviewer then provides isolated exit-control implementation help; +that support is not a fresh review of the revision. Root inspects/integrates it +and independently passes all seven committed controls with zero build warnings +or errors. The unsafe direct callback stays held until parent-owned termination; +the positive observer confirms actual Core exit while private work remains held. +Every child is joined before its temporary build tree is removed. These remain +narrow feasibility controls, not production qualification. ADR-0047/0058 are +byte-preserved; acceptance and all dependent Step 4 runtime remain pending. + +Root also interrupts the launcher while its unsafe exit callback is held: +launcher exit 143, the actual child is gone and the owned temporary tree is +removed. Five Release corpus controls and seven ADR parser controls pass; the +first-party sweep checks 37 Markdown files, 2,708 local links and 643 fragments +without errors and preserves all prior authorized history. These are focused +proposal checks; the full 4,152-case Step 3 result is not rerun or relabelled. + +#### Proposal review round 2 and approval-readiness closeout + +Two new independent reviewers inspect `def48a1a..878bcd49` after the verified +first-round corrections: GPT-6 Astra with xhigh effort covers lifecycle/authority; +GPT-6.1 Sol with xhigh effort covers proofs/governance. Both approve the Proposed +change with no Blocker, Major or Minor finding. Each independently builds/runs all +seven isolated controls with zero warnings/errors. The lifecycle reviewer verifies +committed source archive hashes and extracted bytes. The proof reviewer also +interrupts the actual unsafe-callback child and forces the external watchdog; +both paths join the real child and remove the owned temporary tree. A watchdog +failure is not reported as a successful experiment. + +The initial proposal/probes are `f8ff691f`; verified first-round corrections and +exit controls are `2103f059`; the primary status pointers are `878bcd49`. Root +reads both final reports and execution logs, verifies focused final results of +five Release corpus controls and seven ADR parser controls, and repeats the +37-file sweep: 2,711 local links, 646 fragments, zero errors. All 53 previously +Accepted ADRs are byte-identical across this proposal range. No full backend, +production PostgreSQL/worker or multi-pool result is inferred from these checks. + +Proposal review is complete; ADR-0059 remains Proposed pending maintainer +acceptance. This closeout changes only the review receipt, not the reviewed +policy/probes. The user's requirement to approve new ADRs before dependent +implementation remains the gate. Step 4's real qualification and Steps 5–9 are +pending; no worker, maintenance owner or replacement policy is activated here. + + +#### External proposal review and verified revision (2026-10-16) + +The maintainer's response to the approval request is a review, not acceptance. +Root verifies its findings against `b49998d9`, the Accepted records and pinned +Core/provider source, with separate lifecycle, storage-surface and options support +investigations. Those investigators are not the fresh review rounds below. +ADR-0059 remains Proposed and no dependent runtime is authorized by this revision. + +| Finding | Verified disposition | +|---|---| +| B1 outer retry/repeat owner | Valid. Core retries failed announcement before capture and repeats normal server return independently of heartbeat. Add a preallocated owner, lazy complete lifecycle boundary, one-shot announcement and terminal stop fence including removal/acquisition/disposal. | +| B2 concrete seam and surface | Valid. Name the per-pool `JobStorage` / `JobStorageConnection` decorators, lazy acquisition and in-boundary lifecycle disposal. Preserve extended capabilities, actual transactions/fetched jobs and shared inventory; pin the obsolete API/upgrade and real-provider parity gates. | +| B3 StopTimeout and running work | Valid. Fix both stop/shutdown timers to Infinite. Local drain closes fetch/admission without canceling admitted private work; host stop has a separate retained asynchronous cancellation signal. Pre-admission wakeups may requeue. | +| B4 availability and alternatives | Valid tradeoff. Document shared-outage/all-pool drain and whole-pool blocking despite a spare slot or storage recovery. Compare no replacement and bounded two-generation shared budgets honestly; current probes do not disprove qualified overlap. Retain the proposed one-generation choice for approval. | +| B5 delayed/recurring dependency | Valid. Control drain stops native timers. Require independent same-generation bridge repair in Step 4 and missing-tick durable occurrence recovery in Step 8, without inventing a universal latency SLA. | +| B6 fixed options/metadata/margin | Valid. Pin server intervals, four-minute heartbeat cutoff below five-minute expiry, one-second pacing/five-second owner backoff and exact Queues/WorkerCount dictionary values. Step 4 startup validates these constants; they are not silently new public options. | +| B7 replacement classification | Valid. Earlier ADRs selected stock pools/retention, not a convenience constructor or automatic-restart policy. Correct the Proposed ADR/live summary to an additive lifecycle decision; accepted history is untouched. | +| B8 census/catchability | Valid. Name forbidden facade/registration paths and exact production capability scans. Catchability matches the pinned Core exact-type OOM/StackOverflow exclusions; require actual managed fault premises and closed diagnostic callbacks, not arbitrary throwing/blocking observers. | +| B9 upstream issue | Suggestion, not an implementation requirement or authorization to publish. No public issue is filed; a concrete qualified upstream change remains an alternative, not assumed available evidence. | + +The second report's smaller terminology/reference notes are also verified: +distinguish per-server metadata from storage-wide fetched-job heartbeat, separate +component/filter suppression, label the finite pool observation dimension without +mapping readiness, correct cancellation-timer wording and explain the whole-pass +heartbeat wait. Add the Database/Observability/Events and Outbox references. + +Root integrates twelve additional isolated actual-Core controls into the same +owned launcher, alongside the original seven. The current builder/exit controls +use infinite stop timeout; exit cancellation now receives an explicit host signal, +not the pool-local stopping token. All nineteen pass with zero build warnings or +errors. The new controls distinguish: + +- Raw announcement failure and normal-return repetition from stop-fenced variants. +- Announcement acquisition/disposal and removal/acquisition/disposal failures, + including faults held before owner handle publication and without capture. +- An actual caught non-InvalidOperation managed builder fault, with no later start + and earlier actual work/tokens retained; the premise cannot be skipped by stop. +- Infinite versus finite StopTimeout while actual work stays live, followed by + an independent host signal with its real cancellation/relay tasks held and joined. + +The normal-return pair deliberately allows a stock heartbeat restart with no held +old work to isolate outer repetition/removal fencing. It does not qualify supported +heartbeat containment. Fake lifecycle resources and held `IBackgroundProcess` +work prove neither real PostgreSQL/Worker cancellation nor partial mandatory +thread construction, complete provider parity, common-outage/multiple-pool repair +or actual replacement. All remain named production activation gates. The earlier +seven-control review receipts retain their as-of scope; they are not retrospectively +expanded to cover this external revision. + +Root's isolated whitespace/Release verification passes after integration; +all nineteen distinct controls pass, along with five Release corpus cases and +seven ADR parser controls. The first-party history/link sweep is clean. These +checks do not rerun or relabel the earlier full 4,152-case Step 3 evidence. + +#### External revision review round 1 + +Two fresh independent reviewers inspect `b49998d9..1853b48f`: GPT-6 Astra with +xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers +proofs/governance. Both independently pass all nineteen controls with zero +warnings/errors. Lifecycle reports no finding; proofs reports no Blocker/Major +and one Minor historical evidence-count error, verified and corrected below. +The proof reviewer also removes the actual managed exception in an isolated +mutant: the builder control turns red. Missing receipts, startup failure and +silent watchdog expiry are rejected; the actual timed-out child is joined. +Root reads both final reports/logs. These reviews do not certify production gates. + +**Evidence-count correction — 2026-10-16.** The earlier proposal round-2 receipt's +“53 previously Accepted ADRs” is incorrect. Root and the new proof reviewer use +`scripts/adr-status.py`'s canonical `lifecycle()` parser, not a text occurrence +count: both `def48a1a` and `b49998d9` contain 51 currently Accepted canonical ADRs, +all byte-identical at `1853b48f`. The older receipt remains as-of text; this dated +correction replaces its denominator, not the byte-preservation result. It does +not claim the original reviewer ran this corrected count. ADR-0059 is Proposed. + +#### External revision review round 2 and availability correction + +Two new independent reviewers inspect `b49998d9..b4a6fec0`: GPT-6 Astra with +xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers +proofs/governance. Both independently pass all nineteen controls with zero +warnings/errors and reproduce the canonical 51-ADR count/byte preservation. +The proof reviewer independently rejects missing receipts, startup failure and +watchdog expiry, joins the real child and turns the managed-fault mutant red. + +Both initially report a clean proposal. Root's final cross-check then identifies +an additional governance conflict: ADR-0047's unrelated-tenant progress promises +are broader than ADR-0059's whole-pool drain below four retained overruns. The +lifecycle reviewer independently confirms it and appends one Major, explicitly +narrowing its earlier verdict before acceptance. Root verifies the actual clauses; +their exception cannot be assumed implicit merely because the older contract +already had a four-overrun threshold. + +The correction keeps constructor/restart composition additive, but names a +bounded availability supersession of ADR-0047's Tenant capacity and independent +pools / Lifecycle and observation progress clauses. Same-pool unrelated tenants +may wait during generation-control draining despite a spare slot after storage +recovery and below four overruns. Healthy other pools, hard bounds, reservations +and independent orchestration are preserved. Acceptance will disclose this precise +change in ADR-0047; ADR-0058's ownership note remains additive. Prior Accepted bytes +are untouched. This correction changes classification/explicit contractual scope, +not the already stated single-generation behavior or the nineteen probe sources. + +#### External revision focused verification and approval-readiness closeout + +Two new independent reviewers inspect `b4a6fec0..35b6985d`: GPT-6 Astra with +xhigh effort covers governance and normative scope; GPT-6.1 Sol with xhigh effort +covers corpus/history and evidence mechanics. Both confirm the earlier Major is +resolved without widening the affected-pool exception. The first reviewer flags +one Minor in `71221799`: the four-overrun threshold stops new starts, not actual +retention. Root verifies/fixes it in `35b6985d`; that reviewer preserves its first +report and appends exact-head verification. Both final focused verdicts approve +with no unresolved findings in their stated scope. + +Root reads both final reports and verifies five Release corpus controls, seven +ADR parser controls and the first-party history/link sweep: 37 Markdown files, +2,716 local links, 648 fragments, zero errors. The canonical lifecycle parser +reproduces 51 Accepted ADRs at `def48a1a`, `b49998d9`, `b4a6fec0` and `1853b48f`, +all byte-identical in the final tree. ADR-0059 remains Proposed. The final +classification/wording corrections change only Markdown; the nineteen-control +sources are unchanged since `1853b48f`, so their existing passing receipts are +preserved without claiming a new runtime run. Diff/prose-width checks pass. + +The external revision is `1853b48f`; first-round/count correction receipt is +`b4a6fec0`; bounded availability disclosure is `71221799`; retention precision +is `35b6985d`. The initial clean round-2 verdict and its later Major addendum +remain explicitly recorded above. This final receipt changes no reviewed policy +or probe. It is neither maintainer acceptance nor real production qualification. + +The revised ADR and Step 4 adaptation are ready for maintainer approval under +the user's new-ADR gate. Same-pool blocking during generation-control drain, +including below four overruns after storage recovery, is an explicit decision +for that approval. Step 4's real worker/PostgreSQL, startup/resource, wrapper +parity, multi-pool and exit controls remain mandatory before activation; Steps +5–9 remain pending. Work stays on `development`; no dependent runtime, push, +PR or current-head CI result is implied by this proposal closeout. + +#### Maintainer acceptance and Step 4 adaptation (2026-10-16) + +**Accepted — 2026-10-16, @cemil.** The maintainer explicitly approves revised +[ADR-0059](../decisions/0059-owned-hangfire-server-generations.md) and the Step 4 +adaptation reviewed at `0db27eb6` on `development`. This closes the new-ADR +approval gate and authorizes dependent implementation after the acceptance +commit. It completes no implementation step or production activation proof. +The nineteen-control experiment and earlier review/validation receipts retain +their recorded scope; acceptance neither reruns them nor expands their claims. + +The accepted change has two distinct parts: + +- **Additive lifecycle integration:** public stock process composition, one + actual generation per pool, synchronous context capture, closed storage and + lifecycle disposal fences, classified metadata-heartbeat retry, sole owner + replacement after actual stock/LearnStack cleanup, separate shared component + ownership and a qualified closed process-exit relay. +- **Bounded availability supersession:** only the two ADR-0047 progress clauses + quoted in ADR-0059 are qualified during generation-control drain. Unrelated + tenants in the same pool can remain blocked after storage recovery, with a + spare slot and below four retained overruns, until actual cleanup completes. + Healthy other pools remain independent subject to common dependencies. + Four overruns still stop new starts in an otherwise serviceable generation; + actual retention continues. Hard bounds, fair independent orchestration, + attempts, reservation ownership and positive quiescence remain unchanged. + +[ADR-0047 Amendment 2](../decisions/0047-transactional-background-job-runtime.md#amendment-2--owned-server-lifecycle-and-bounded-availability-supersession-2026-10-16) +discloses both parts. [ADR-0058 Amendment 2](../decisions/0058-bounded-stock-hangfire-maintenance.md#amendment-2--independent-shared-component-ownership-2026-10-16) +is additive component-ownership navigation only. Both preserve the prior +Accepted bodies, acceptance metadata and earlier amendments. No whole-record +supersession or ADR-0041 fact correction is selected. + +**Adapted Step 4:** the original H1 wakeup/bridge/wrapper/pool work remains in +scope, with ADR-0058's component/filter and maintenance obligations. ADR-0059 +adds the public compositor and complete concrete storage/connection surface, +one-shot announcement/removal stop fences, exact fixed options/queue metadata, +local drain without business cancellation, retained actual stock/LearnStack +joins and API-instance shared fetched-job heartbeat/expiration hosting. +The closed diagnostic observer, cancellation relay and process-exit boundary +must be qualified before worker activation; unresolved startup/resource cleanup +refuses activation and reopens the decision, rather than granting replacement. + +Real pinned worker/PostgreSQL controls remain mandatory for full provider-surface +parity and capability census; acquisition/disposal/startup and heartbeat faults; +nonoverlap and no early token/resource disposal; control-pool drain with healthy +pool renewal and due delayed-handoff repair; common outage/recovery with a held +operation and a spare slot still closed; host stop/backoff/late completion; and +direct-callback versus closed-relay process exit. The final simultaneous physical +acquisition census must enforce its qualified supported configuration/floor and +prove progress at that boundary; no guessed numeric floor is accepted. + +Step 8 retains missing-native-tick recurrence/CoalesceLatest qualification. +Steps 5–9 retain business completion/terminal audit, tenant capacity, external +effects, recurrence and final enforcement under their existing approved scope. +The nine-step sequence and two fresh independent review rounds per step remain +authorized. Phase 03 operator recovery and Phase 11 readiness/supervision remain +with those owners. + +**Carrier inventory at acceptance:** + +| Carrier | Acceptance effect / remaining implementation owner | +|---|---| +| [Standards 05](../standards/05-database.md#background-jobs) | Existing canonical schema/grants/source deadlines remain unchanged. Step 4 must qualify every concrete connection/compositor acquisition lane and the supported pool boundary; this acceptance adds no DDL or grant | +| [Standards 10](../standards/10-observability.md#health-checks) | Accepted lifecycle observation reference only. Step 4 supplies truthful drain/heartbeat/shared-component health; Step 9 owns final instruments/censuses. No new emitter or mapped readiness is claimed | +| [Standards 20](../standards/20-infrastructure-stack.md#background-jobs-and-hangfire) | Accepted lifecycle and bounded availability reference; implementation/activation remain pending | +| [Standards 21](../standards/21-architecture-tests-catalogue.md) | ADR-0059 extends the existing bootstrap, independent-capacity and credential-confinement obligations by reference; all three remain Registered. Step 4 supplies real subjects/controls; Step 9 closes enforcement. No rule, method or Implemented count changes | +| [Events and Outbox architecture](../architecture/15-event-and-outbox.md#background-job-transport-and-maintenance) | Accepted server/component ownership and availability reference; delivered Steps 1–3 and pending Steps 4–9 remain distinct | + +This documentation-only acceptance precedes dependent runtime changes. It +claims no new worker, maintenance owner, production qualification, full backend +rerun, CI result or packet closeout. Earlier pending-approval wording is dated +history; current implementation and activation remain pending. + +#### Step 4 required-startup qualification (2026-10-16) + +ADR-0059 acceptance commits at `6c52eaa1` before dependent work. Root verifies +two independent source/design inspections (GPT-6-astra xhigh and GPT-6.1-sol +xhigh) against pinned Core and official .NET 10.0.10 source. Normal lifecycle +containment is implementable, but the literal required-startup join-before-dispose +obligation remains unqualified through the current public seams. + +Core starts metadata heartbeat and prepends private watchdog/cancellation builders +before supplied capture. If required construction throws, it skips the child join +and disposes prior controls before removal reaches the storage fence. Keeping that +uncaptured generation retained prevents replacement, but cannot undo disposal. +.NET distinguishes exact native-create OOM from a later initialization wrapper; +Core's exact exception predicate does not itself exclude ThreadStartException. +The identified Unix path concerns stack/TLS/runtime resource initialization. +No genuine Linux resource-failure experiment, ordinary SQL/configuration +counterexample or frequency estimate is claimed. A hostile global logger or +invalid input is not a supported-production counterexample. + +[ADR-0060](../decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md) proposes the narrow +fatal-process alternative: after prevalidation, unowned constructor/required +startup failure closes starts/replacement and terminates the entire API without +a graceful-cleanup claim. This interrupts unrelated pools/HTTP traffic; durable +attempts, external uncertainty and reservations remain authoritative. Normal +announcement/database faults, captured builders, local drain and host stop retain +ADR-0059's policy. The proposal neither accepts itself nor authorizes termination +runtime. It applies ADR-0059's existing decision-reopening gate. + +Independent bridge, closed diagnostics, selective component/filter inventory and +storage/parity work continue under the Accepted contracts. They do not qualify +the complete server owner or activate workers. New proposal review receipts and +actual implementation/test results will be recorded after they occur; no new +passing production test, full Step 4 completion or current-head CI is implied. + +##### Required-startup proposal review round 1 + +Two fresh independent reviewers inspect `6c52eaa1..34be14e6`: GPT-6-astra xhigh +covers policy/lifecycle and GPT-6.1-sol xhigh covers proofs/governance. Both +approve the Proposed documentation for maintainer consideration with no +Blocker/Major, independently identifying one Minor: the consequence's “rare” +frequency qualifier is unsupported. Root verifies/removes it, preserving the +explicit absence of a genuine resource-failure experiment or likelihood estimate. +The source-based state trigger, entire-host consequence, bounded supersession +and pending implementation/proof gates remain unchanged. + +Root reads both final reports. Seven ADR parser controls, the six-file link/ +fragment sweep and diff/prose checks pass; all 52 baseline Accepted ADRs remain +byte-identical. These are proposal checks, excluding the uncommitted independent +bridge/wrapper/diagnostic slice. A new second review round follows this correction; +ADR-0060 remains Proposed and no fatal-process runtime is authorized. + +##### Required-startup proposal review round 2 + +Two new independent reviewers inspect `6c52eaa1..ac5a1cd3`: GPT-6-astra xhigh +covers policy/lifecycle and GPT-6.1-sol xhigh covers proofs/governance. Both +approve the Proposed documentation for maintainer consideration with zero +Blocker/Major/Minor/Suggestion findings. Root reads both complete final reports. +The proof review independently checks all 52 baseline Accepted ADRs byte-for-byte, +ADR-0059 Accepted/ADR-0060 Proposed, 706 local links and 295 fragments with no +missing targets, unchanged catalogue bytes/counts, added prose/private-reference +checks and clean diff whitespace. Neither review runs shared builds, database +experiments or production qualification; no genuine Linux resource-failure or +frequency claim is introduced. + +The proposal is ready for maintainer consideration. Its entire-API interruption, +operator restart and absence of graceful cleanup remain explicit costs; fatal +runtime and activation still require acceptance. Independent Step 4 foundation +validation proceeds under the existing Accepted decisions and is recorded +separately. Steps 4–9 remain incomplete; no push, PR or current-head CI is claimed. + +##### Independent Step 4 foundation slice (2026-10-16) + +This slice implements the already-authorized H1 transport and public storage +boundary while ADR-0060 remains Proposed. It does not implement fatal termination, +compose Core generations, host shared maintenance or activate API workers. +Full Step 4 and Steps 5–9 remain pending under their accepted ownership. + +- The bridge claims committed intent in a short privileged transaction, retains + at most four actual synchronous stock-client calls on background threads and + suppresses ambient execution context/culture. Vendor IDs remain hints; absent, + failed or succeeded vendor rows permit same-generation repair without spending + business attempts. ACK/deferral locks the actual row before rechecking current + database-time lease/token/generation fences; callback admission may precede ACK. + Host stop closes acquisition and retains actual calls through late completion. +- Exact opaque wrappers and a five-token resolver reject arbitrary CLR lookup. + The closed activator binds a registered pool, invocation and single-use scope; + it reaches Step 3's framework admission only. Business completion stays Step 5; + recurrence materialization stays Step 8 and cannot currently report success. +- Concrete pool storage/connection wrappers preserve the complete pinned public + surface, provider features, extended casts, transactions, fetched jobs and locks. + Only announcement, metadata heartbeat and removal enter the closed lifecycle + operation. Failed disposal remains retained; this is no proof of the pending + complete generation owner or every physical provider cleanup outcome. +- Fail-closed component/filter inventories retain exact stock instances and required + filters while suppressing the counter aggregator/history. Vendor diagnostics use + fixed memory-only counters without evaluating messages or invoking observers. + Existing capability, authority, transaction and parallelism censuses enumerate + the new exact callers and retain their planted extra/missing-site controls. + +Real delayed creation exposed a predicate mismatch: stock explicit-queue scheduling +stores `queue:id` in the `schedule` set, while the prior guard admitted only numeric +IDs. The fix preserves immutable queue binding, restricts the added form to that +key and bounded queue/ID grammar, and reconciles the canonical SQL. An additive +Platform migration supports already-installed stores; reverse/reapply, malformed +and wrong-key controls exercise the boundary. Fixture corrections preserve the +actual ACK-after-lock-expiry and below-filter redaction assertions, and replace the +old missing-wrapper assumption with a positive load of the now-present wrapper. +Earlier recorded Step 2/3 evidence is unchanged. + +**Initial slice validation:** Release warning-as-error build passes with zero +warnings/errors. Unit 2,056, Architecture 315, Contract 4, Docker-free HTTP +integration 176 and focused real-PostgreSQL bridge/parity/storage/rollback 94 +pass: 2,645 tests, zero failures/skips. TRX counters are checked directly and by +the guarded test receipt. Seven ADR parser controls and a three-file sweep of +533 local links / 193 fragments pass. C# formatting and diff whitespace pass. +This is a focused slice receipt, not a full backend/renderer/demo/CI rerun. + +The first runs found the queued-schedule guard mismatch, a completed-locker +rollback in the proof, an inadmissible RetryCount test value and the old absent +wrapper assumption. The corrected PostgreSQL set passes in full. Initial +architecture failures identify only newly sanctioned caller inventories; exact +entries and forwarding/removal mutants now pass the full architecture assembly. +No failing check is skipped or broadened to allow arbitrary callers. + +Two fresh independent slice-review rounds follow the initial implementation +commit. They do not close full Step 4's real generation, maintenance, +cancellation/exit, multi-pool progress or connection-floor gates. + +##### Independent foundation review corrections (2026-10-16) + +The initial foundation review was interrupted before final reports; it is not +counted as a completed round. A resumed independent GPT-6-astra xhigh R1 inspects +the complete committed slice and surrounding runtime/census paths. It verifies +one Major: raw filter concatenation bypasses stock precedence and lets the global +retry execute before the wrapper's zero-retry attribute. The separately identified +bridge-source forwarding gap also needs exact capability enforcement. + +Commit `9db4822d` uses the stock filter-provider collection, preserves the admitted +global instances and pins the bridge store's signatures, source captures, +acquisitions, consumers and holders. Actual StateMachine controls distinguish +failed-state retention from the raw-concatenation retry/schedule outcome. Two +fresh independent R2 reviewers (GPT-6-astra xhigh runtime and GPT-6.1-sol xhigh +proof/security) inspect the corrections. The proof reviewer finds one further +Major: a pre-creation global retry registered at order 100 wins stock precedence. +Root verifies it and refuses nonstock retry registration order before changing +history; both wrappers now have effective-filter and actual state-election controls. +Both reviewers independently verify the final fix with zero remaining findings. + +Before the last two-line registration guard, Release build, Unit 2,058, +Architecture 317 and focused real-PostgreSQL 93 pass, with zero failures/skips. +After that guard and its added controls, Release build remains warning/error-free, +all 2,061 unit cases and four targeted credential/catalogue architecture cases +pass. Direct TRX counters and the guarded runner confirm execution and zero skips. +Pre-commit formatting leaves all four reviewed C# hashes unchanged. This is not a +new full backend/renderer/demo/CI receipt; no fatal runtime or worker is activated. +Full Step 4's complete-runtime review and qualification gates remain open. + +##### ADR-0060 external-review revision (2026-10-16) + +The maintainer requests changes to the Proposed record. The earlier two clean +proposal-review receipts remain historical; they do not close these later verified +gaps or authorize fatal runtime. Root rechecks pinned Core and official .NET source, +reads two independent state/policy analyses and revises the proposal before seeking +new approval. No genuine Linux resource failure, new runtime experiment or incidence +estimate is claimed. + +The revised file is +[ADR-0060: Fatal Hangfire Startup and Unsafe Unwind](../decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md). +Renaming the Proposed file reflects its explicit before/after-capture scope; earlier +record links resolve forward to that current proposal. All Accepted ADR bodies, +metadata and prior amendments remain unchanged. + +| Verified review gap | Revision / deliberate boundary | +|---|---| +| M1: fatal rationale relied on the old cleanup promise | Quarantine remains a viable policy alternative. Fatal is a conservative integrity/visible-failure preference with the whole-API cost, not technical necessity or proof that private controls execute business work | +| M2: Phase 11 ownership was absent from its roadmap | Reliability scope, deliverables and completion now explicitly own supervision/restart/backoff/crash-loop, termination/dump policies and the triggered worker-process topology decision; no present supervisor is claimed | +| M3: constructor predicate exceeded proved live-thread cases | Entire prevalidated constructor failure is explicitly conservative, including pre-thread false positives; no private instruction boundary is inferred from exception type/text | +| M4: capture did not cover Core post-builder/notification unwind | Separate progress and conditional normal-join facts; owned disposal, removal, second-announcement and outer-completion observations cover skipped waiting/removal. Closed logger/timer/final-exit premises must be qualified before activation | + +The revision also names process-wide starts/ExecuteIntent gates and earlier-admission +uncertainty, host-stop versus final-teardown priority, retained unhealthy stalled +startup under the existing ProgressTimeout, finite pool/stage diagnostics, runtime/ +Linux resource/collector dump prerequisites and orphan process-tree consequences. +Exact ADR-0059 qualification/availability clauses and its Option 4 are disclosed; +three existing canonical test obligations receive explicit prospective assignments. +No new rule/count/status or caller enforcement is declared implemented. + +The suggested automatic exact-OOM crash outcome is not established and is not used +as a policy argument. Existing API blast-radius, manual-restart, dump-risk and durable +reservation disclosures were already present; their concrete controls/owners are +strengthened rather than presented as newly discovered guarantees. Synthetic fault +placement remains distinct from real stock and genuine resource evidence. Proposed +and Accepted policies are not silently conflated. + +The independent foundation corrections above own their source capability and +filter proof/review receipt. Neither workstream completes Step 4 or permits +fatal activation. The following records own the proposal's fresh reviews. + +**Revision review round 1:** two fresh independent reviewers (GPT-6-astra xhigh +lifecycle and GPT-6.1-sol xhigh governance/proofs) inspect the frozen eight-document +revision against `422519b0`. Both request changes for one Major and one Minor. +Root reads both full reports, verifies ADR-0047's preserved other-pool progress +clauses/Amendment 2 and adds its prospective dated bounded disclosure alongside +ADR-0059. The second-announcement fatal predicate now requires missing normal +child-join evidence, preserving nonfatal post-join cleanup. Known pre-child refusal +precedence and complete-boundary announcement confirmation are explicit. + +Both independently confirm the state-model, conservative/quarantine tradeoff, +Phase 11 owners, dump/collector prerequisites and pending proof limits. Static +checks preserve all 52 Accepted ADRs; the governance review independently checks +1,290 local targets / 394 applicable fragments with no errors. Root's parser and +whitespace checks pass. No reviewer runs shared tests or resource experiments. +The independent bridge fix adds two architecture methods (222 → 224), without any +rule/status/Implemented-count promotion; its execution receipt is separate. +A fresh second revision review follows these corrections; approval remains pending. + +**Revision review round 2:** fresh independent GPT-6-astra xhigh lifecycle and +GPT-6.1-sol xhigh governance/proof reviewers approve the corrected eight-document +proposal with zero findings. Both recheck the frozen hashes and all 52 unchanged +Accepted ADR files; the governance reviewer verifies the four exact authority +quotes, unique Registered proof names and unchanged Implemented-rule count. +Root reads both full reports and reruns seven ADR parser controls, the changed-doc +sweep (1,291 local links / 395 fragments, zero errors) and whitespace checks. +No reviewer executes a resource, fatal-child, worker or PostgreSQL experiment. +These are proposal-review receipts, not maintainer acceptance or runtime proof. +The revised ADR-0060 remains Proposed; dependent fatal implementation still waits +for approval, and real lifecycle qualification precedes activation. + + +##### ADR-0060 acceptance and Step 4 continuation (2026-10-16) + +The maintainer approves the revised ADR-0060 at `189f3bcf` and explicitly requests +implementation. Acceptance precedes dependent runtime commits on `development`. +It selects the conservative opaque-construction/unsafe-unwind fatal policy after +comparing viable quarantine, including before-thread false positives and the +whole-API/healthy-pool availability cost. Stalled startup remains retained unhealthy +ownership, not timeout-based fatal selection. No exit releases durable uncertainty +or reservations; earlier-admission effects remain authoritative. + +The acceptance carrier commit adds dated bounded supersession amendments to +ADR-0047 and ADR-0059, keeps their bodies/metadata intact, moves ADR-0060 into the +Active index and reconciles current front doors, Standards 20/21, architecture 15 +and Phase 11's explicit operations ownership. Three existing canonical proof +assertions are extended without changing Registered status or published counts. +ADR-0058's ordinary maintenance contract remains unchanged. + +Step 4 resumes the actual generation owner, shared components, host/exit gates, +closed fatal capability and real pinned worker/PostgreSQL qualification. It still +must complete its implementation commit, two fresh independent full-step review +rounds and verified fix commits before Step 5. Fatal child prerequisites must be +qualified before launch; unsupported dump/collector settings fail, never skip. +No acceptance receipt claims runtime delivery, production readiness or activation. + +Focused independent acceptance audit passes after fixing the Active-table row and +derivation-header navigation. All 52 prior Accepted ADRs preserve their bodies; +the two named amendments add only new lines. Seven ADR parser controls, five +corpus architecture cases and a 1,543-local-link / 468-fragment sweep pass, with +zero failures/skips or broken targets. Published catalogue counts/statuses remain +unchanged. The acceptance commit contains documentation only. + +##### Owned generation and maintenance foundation (2026-10-16) + +**Implementation slice; Step 4 remains in progress.** ADR-0060 acceptance at +`e0d39bf5` precedes this dependent runtime. `HangfireGeneration` retains actual +construction, stop, startup observation and uncanceled Core completion separately +from caller waiting. A synchronous context capture and Core-facing wait-entry +marker distinguish progress from the qualified normal child-join witness. +Successful removal/disposal is also required before cleanup is acknowledged; +joined but unresolved cleanup stays retained. A stop that wins before Start has +its own positive no-Core completion path. + +The shared component owner retains the two frozen stock components independently +of pool drain. Native startup, invocation, actual join and cancellation callbacks +have distinct owners. Each lane observes its five-minute wait plus one-second +cleanup bound without releasing resources or starting another pass early. +Expiration keeps its one-hour cadence; fetched-job heartbeat keeps stock pacing. + +One closed process gate arbitrates host stop, final teardown and the sole +preallocated pool/stage fatal sink. Its final-exit callback registers before Core. +The gated native connection factory permits normal stock cleanup during host drain +and refuses fatal/final-teardown issuance. Bound activators/wakeups recheck the +same generation at activation, routing and app admission. The framework scope +retains that closed memory predicate and rechecks it after actual row-lock waits, +before spending an attempt. No module-supplied context or transaction owner changes. + +Focused source feedback fixes pre-lifecycle expiration drift, stop-before-start, +missing removal/disposal evidence and owner clock/timer failures. Ordinary provider +failures remain contained through the real stop/child-join fence. Two new structural +facts pin the actual fatal capability/sink and public Core constructor, with +direct/delegate/async/overload/interface/forwarding dirty controls. The catalogue +method total becomes 226; all 19 P4 obligations remain Registered and the +Implemented-rule count remains 202. Per-detector body snapshots are rebuilt after +every mutation; no process-wide mutation cache hides added or removed subjects. + +Validation currently records a zero-warning/error solution build, 2,083 Unit cases +and 133 focused PostgreSQL/process cases, with zero failures/skips. The latter +include ten real generation controls, app-role admission closure during a real row +lock, real stock parity/bridge/admission regressions, six Linux scenarios and +one in-memory receipt-predicate control. +The full Architecture run and final per-detector optimization rerun each pass +319 cases, with zero failures/skips. + +The Linux sidecar runs the real production sink only in an isolated .NET 10.0.10 +Arm64 child. A benign twin proves cleanup sentinels; fatal exit 134 omits them. +The shell verifies soft/hard core limits zero and the nonpiped `core` collector +before managed entry. Child environment is cleared, modern/legacy dumps disabled, +root/input binaries read-only, scratch isolated and network disabled. The initial +archive-copy setup refuses the read-only root; a read-only mount of staged proof +binaries fixes setup without changing dump/collector policy. Actual native and +supervisor exits, fixed diagnostics and artifact allowlists pass. These are direct +gate/synthetic-stage controls, not genuine Core resource-failure reproduction or +generation phase-dominance proof. + +The production API does not construct or activate these owners yet. Full pool +replacement/retained LearnStack work, independent bridge/control composition, +supported physical-acquisition boundary and remaining lifecycle/fault/exit proofs +remain in Step 4. Its complete implementation commit and two fresh full-step +review rounds still precede Step 5. This slice claims no new business execution, +recurrence, readiness mapping, production recovery, CI success or packet closeout. + +##### Foundation review round 1 and verified corrections (2026-10-16) + +Two fresh independent reviewers inspect `e0d39bf5..e1e6db42`: GPT-6 Astra with +xhigh effort covers runtime authority/lifecycle; GPT-6.1 Sol with xhigh effort +covers proofs/corpus. Both use standards-check then code-review lenses. These +are focused foundation reviews, not the still-required full Step 4 rounds. + +Root verifies one Major finding against the pinned provider source: fetched-job +renewal catches acquisition/SQL failures internally and returns normally. The +shared owner could incorrectly report that returned pass healthy. The correction +binds the closed diagnostics instance, preserves swallowed faults/ownership loss +through empty passes, and requires a clean pass containing actual renewal SQL +before clearing known storage failure. Return/join and storage health are distinct. +No provider message factory is evaluated and stock code/SQL remain unchanged. + +The real disposable-PostgreSQL regression fetches a stock wakeup, revokes only its +renewal-column permission and proves unchanged fetched-at, recorded fault and an +unhealthy returned/joined pass. Restoring permission must produce actual fetched-at +progress and healthy recovery with historical faults preserved. Fixture-only +cadence acceleration is explicit; the stock one-second pass pacing is unchanged. +Ten shared-owner unit cases and eleven generation PostgreSQL cases pass with zero +failures/skips. The combined bridge/generation regression passes 33 cases. +The initial new fixture does not compile against the provider's internal Options +property; narrow test-only reflection corrects cadence access. A ten-case run of +the previous integration binary is excluded from the new regression evidence. + +The proof reviewer reports no Blocker/Major/Minor. Both verified suggestions are +applied: the constructor-shape assertion includes public and nonpublic members; +the foundation receipt distinguishes six Linux scenarios from its one in-memory +predicate control. Complete Step 4 qualification/activation remains pending. + +##### Foundation review round 2 (2026-10-16) + +Two new independent reviewers inspect `e0d39bf5..28433f29`: GPT-6 Astra with +xhigh effort covers runtime and GPT-6.1 Sol with xhigh effort covers evidence/corpus. +Both approve the scoped foundation with no Blocker/Major/Minor. They independently +verify the swallowed-renewal mechanism, sticky health, positive storage recovery, +constructor census and six-Linux/one-memory proof boundary. They do not rerun the +toolchain or substitute their source review for the recorded execution receipts. + +Root verifies/applies the one nonblocking suggestion: README now distinguishes +in-progress implementation from pending full qualification/activation and points +its current-phase link to Phase 02b. Both focused foundation review rounds are +complete; the remaining Step 4 integration and fresh full-step rounds stay open. + +##### Pool replacement and framework cleanup ownership (2026-10-16) + +**Further implementation slice; Step 4 remains in progress.** One closed +`HangfirePoolOwner` retains each actual generation and its supervision task. +Replacement requires positive generation cleanup, the fixed five-second backoff +and live owner/process gates. A startup-stalled generation stays closed even +after its late cleanup joins; stop-before-start has a positive no-issued-work path. + +Generation-local work owns private cancellation sources and the actual routing +and admission tasks. Local drain closes starts without canceling that work; +host stop requests asynchronous cancellation independently of Core tokens. +Cancellation callbacks and failed cleanup remain owned after wrapper return. +Four retained entries close further starts, with workers-plus-four as the hard +ownership bound. Real stock joins do not substitute for private-work completion. + +Routing publishes its opaque claim only after acknowledged COMMIT and actual +resource cleanup. Failed cleanup retains the concrete reader, command, +transaction and connection. Framework admission likewise carries concrete failed +scope/unit/activity/authority/source owners in its result: a completed async task +may clear its state-machine locals. This correction preserves the actual failed +DI scope and unit rather than relying on the completed task alone. + +Bridge operations bind ownership before scheduling native startup and recheck the +process/local gates at actual creation and SQL acquisition. Startup return, native +end, observer return and positive cleanup have separate witnesses. Unknown startup +or observer cleanup cannot be pruned as completed; ordinary host stop preserves +durable late-handoff repair without a new local ACK acquisition. + +Validation passes a zero-warning/error solution build, 2,109 Unit cases, 74 focused +PostgreSQL cases and the full 319-case Architecture suite, all with zero skips. +The PostgreSQL set includes six real pool-owner cases, seven routing-cleanup cases +and five added generation-work cases. Those cover actual routing/DI cleanup held +past stock joins, real native admission/cancellation, delayed callbacks and exact +failed-scope retention. Four retained entries in the threshold proof are explicitly +synthetic framework occupancy; native refusal/restored admission are real. The +throwing-disposable proof repairs only its synthetic fixture during teardown and +does not introduce a production recovery API. + +Initial architecture runs expose the moved routing transaction's stale exact +caller inventories and the wrapper's declared sequential-task ownership exception. +Updating those precise owners preserves the privileged-entry checks and planted +controls; the fresh full rerun passes. A filter selecting no tests is excluded +from evidence. Earlier failed runs are not added to passing counts. + +API facade/source-lifetime integration, supported physical capacity and full Core +phase qualification remain pending. The new Core-phase fixture's first actual run +fails during isolated PostgreSQL setup, before arming any fault; its receipt +predicate passes. This is setup feedback, not fatal-policy qualification. Neither +this slice nor its tests activate workers or close full Step 4's review gates. + +##### Pool-cleanup slice review round 1 (2026-10-16) + +Two fresh independent reviewers inspect `28433f29..d9fda174`: GPT-6 Astra with +xhigh effort covers runtime authority/lifecycle; GPT-6.1 Sol with xhigh effort +covers evidence/corpus. Both approve the exact slice with no confirmed +Blocker/Major/Minor. Their source reviews do not rerun the toolchain or close the +remaining full Step 4 gates. + +Both reviewers identify the pre-existing ACK/deferral cleanup-fault qualification +boundary as remaining full Step 4 work: a returned store exception alone does not +prove positive connection cleanup. The ongoing source-lifetime integration owns +that correction and its decisive controls. Their report artifact writes succeed; +final readback is initially blocked while an unrelated local process burst +prevents new shell processes. The subsequent continuation receives both complete +reports and verifies their artifacts. No unavailable check is counted as passing. + +The implementation commit's normal hook initially conflicts only on formatting +of two newly added tests while restoring its own WIP stash. Root compares both +versions, verifies equal nonwhitespace content, keeps the formatter output and +verifies all three tracked/five untracked pending proof files byte-for-byte. +The second normal hook succeeds; only the verified recovered hook backup is +removed, preserving the three pre-existing stashes. + +##### Pool-cleanup slice review round 2 (2026-10-16) + +Two new independent reviewers inspect the same exact committed +`28433f29..d9fda174` range: GPT-6 Astra/xhigh covers runtime and +GPT-6.1 Sol/xhigh covers tests, structural enforcement and corpus. Both approve +with no confirmed Blocker/Major/Minor or required correction. The evidence +reviewer independently reads the supplied build log and TRX records, confirming +the recorded 2,109 Unit, 74 focused PostgreSQL and 319 Architecture cases with +zero skips; this is receipt inspection, not another execution. + +Both review rounds are complete for this slice. They do not close full Step 4, +review the subsequent working tree or establish worker activation. The baseline +bridge ACK/deferral cleanup ambiguity remains assigned to source-lifetime +integration rather than relabeled as a new slice regression. + +##### Source-lifetime and facade continuation (2026-10-16) + +An unrelated local test experiment exhausts the workstation's process limit and +blocks shell/test startup. With explicit maintainer authorization, only that +experiment's matching process path is terminated. The next process inventory +contains 659 processes and no matching experiment process; commands resume. +This environment repair is not product or CI evidence. + +The working implementation adds concrete connection-cleanup seals to the three +privileged dispatch/bridge stores, a one-shot shared-source lifetime pin, +positive messaging startup/actual-loop witnesses and the API runtime facade. +The corrected source builds with zero warnings/errors; its then-current Unit +assembly passes 2,161 cases with zero skips. Synthetic driver-state and cleanup +controls prove retained ownership, not production failure incidence. + +The isolated Core-phase fixture progresses through PostgreSQL preparation and +container qualification but still refuses its sanitized-output prerequisite. +Those failed runs arm no accepted fatal-policy proof and are not counted as +passing qualification. Full Core phase/mutation/native-exit evidence, composed +source lifetime, supported capacity and full Step 4 reviews remain in progress. + +##### Core-phase and direct-facade qualification (2026-10-16) + +The corrected isolated fixture passes 23 cases: seventeen unchanged-vendor Core +phase/native-exit scenarios, five actual child-only IL mutations and one separately +labelled receipt-predicate control. The mutations remove the production sink or +one exact constructor/capture-disposal/second-announcement/outer-completion +observer. The same normal predicate rejects each modified child's actual result; +a later fallback fatal call cannot conceal an observer that already returned. +These are synthetic fault placements in real pinned Core, not genuine native +thread/resource-exhaustion reproductions. + +The fixture retains strict empty-stderr, native/supervisor exit, artifact, dump, +runtime and original-vendor-binary checks. Its earlier output refusal is optional +GSS library discovery in the minimal Linux image; the password-only fixture now +explicitly disables GSS encryption. Production connection settings are unchanged. +PostgreSQL preparation has one ephemeral loopback binding, preserved and checked +after bridge detachment; the fatal child has only the inspected internal network. +No claim that the PostgreSQL setup port is unpublished is made. + +Six real-PostgreSQL facade cases pass. Actual default and maximum manifests use +the same guarded pooled settings and live stock worker/queue metadata: 45 and +151 connections respectively. A native framework invocation's held DI cleanup +keeps source disposal pending beyond the caller's stop deadline; releasing actual +cleanup permits Core removal, positive runtime completion and source closure. +Another case holds stock expiration's actual checkout with a competing database +lock while independent transactional admission succeeds at the supported default +floor. These cases do not assert simultaneous saturation of all reserved lanes. +Their two completed messaging tasks are explicit no-issued-work facts; the real +three-owner API composition requires its separate qualification. + +The current Release solution build passes with zero warnings/errors and all +2,165 Unit cases pass, zero failures/skips. Full Architecture validation and the +composed messaging-source proof remain in progress. These receipts overlap earlier +focused runs and are not summed into a packet total. Full Step 4 implementation, +fresh full-step review rounds and later Steps 5–9 remain open. + +Two additional composed PostgreSQL cases now pass with the actual API-hosted +jobs, outbox and delivery singletons and their exact bound completion tasks. +Each real terminal transaction and one matching MUST SecurityEvent audit commit +before a test-owned async disposable holds that terminal audit scope's cleanup. +The actual connection remains checked out and actual worker completion remains +pending through finite stop waiting and container disposal. Guarded acquisition +still succeeds; releasing the synthetic cleanup hold lets all three actual owners +join and the same source observer close the pool. Independent app-role reads +confirm unchanged terminal/audit durability, then no vendor server or tagged +backend remains. The synthetic disposable is not a driver-cleanup-fault claim. + +The first composed fixture run fails genuine DI validation because its custom host +omits tenancy edge registration. The corrected fixture uses the real edge and +literal development configuration; validation stays enabled. A discarded network +hold design is replaced before acceptance because bounded driver cancellation +would make its pending checkpoints depend on a narrow scheduling window. + +The full Architecture run exposes a detached Cecil target in a planted +missing-subject control; local guards now record the missing declaration/scope +instead of throwing. The already-failed unoptimized rerun is canceled and excluded +from qualification. A per-detector scan reuses type/call-site indexes only within +one synchronous evaluation; mutation and undo occur between disposed scans. +The existing companion verifies fresh async-subject addition/removal and cache +release. Its performance and the corrected full suite still await execution. + +##### Complete Step 4 implementation validation (2026-10-16) + +The current implementation passes a fresh CI-mode Release solution build with +zero warnings/errors and all **4,403 backend cases**: 2,165 Unit, 321 Architecture, +4 Contract and 1,913 Integration (176 HTTP and 1,737 Docker/PostgreSQL cases). +The runner guard confirms every assembly executes and no case is skipped. The +Docker run takes 9 minutes 55 seconds; Architecture takes 13 minutes 23 seconds. +The latter confirms the corrected detectors and mutation-scope cache pass, not +a measured speedup against the canceled failed run. + +The complete Integration run includes the Core-phase/mutation, direct-facade and +three-owner lifetime cases described above. Their focused receipts overlap this +run and are not added to the total. Seven ADR parser controls, 1,603 local links, +466 fragments, added prose wrapping and whitespace checks pass. No frontend/demo +rerun or current-head CI is claimed; full packet regression remains Step 9. + +This implementation is ready for the two fresh full Step 4 review rounds over +the changes after Step 3 closeout `def48a1a`. The earlier slice reviews remain +scoped receipts. Step 4 is not closed until both full rounds and their verified +corrections complete; Steps 5–9 remain pending. + +##### Full Step 4 review round 1 (2026-10-16) + +Three fresh reviewers inspect `def48a1a..a1832c6e`: GPT-6 Astra/xhigh covers +runtime/lifecycle; GPT-6.1 Sol/xhigh covers evidence/censuses; a second +GPT-6.1 Sol/xhigh covers security/composition/corpus. They inspect the passing +receipts without rerunning the toolchain. Four unique Major findings are verified +against current source; the security review independently confirms the same +metadata-heartbeat finding rather than adding another issue. + +- A held routing/framework cleanup has no finite wrapper-wait transition to + retained/unhealthy ownership. The correction reuses the existing short-work + wait bound and preserves actual work/callback/source ownership after return. +- The facade drops the running generation's metadata-heartbeat fault during its + retry window. Aggregate health must preserve that fault before drain and reset + only after actual stored recovery. +- Shared expiration/fetched-job component state/outcome and ownership facts do + not reach the registered health result. Fixed memory-only dimensions restore + those distinct observations without mapping readiness. +- The production final-exit child holds actual Core control work but no actual + private cancellation callback. The isolated prototype remains decision support; + a combined shipped-relay positive and direct-Core-callback dirty control are + required in the qualified production child. + +Corrections and their regression qualification are in progress. The optional +scan-cost suggestion scopes repeated type/call/body inventories to one detector +evaluation, preserving fresh mutations/restoration and measuring the full suite +before any performance claim. No Accepted decision changes. Step 9 retains the +existing Standards 10/11 carrier sweep for legacy vendor-payload wording and the +retired `Hangfire_Job_Payloads_Include_TenantId` spelling. No later step or full +Step 4 review gate is closed by this record. + +The first correction run passes 33 of 35 focused PostgreSQL/Core-phase cases, +including both real native framework expiry cases and all 24 Core-phase controls. +Its two health failures are investigated rather than relabeled as qualification. +One fixture fetches through a second provider whose renewal inventory is separate; +the corrected control uses the facade's actual provider and a fixed fixture-only +orphan queue with no native consumer. The metadata control also exposes PostgreSQL +`query_canceled` (57014), which the pinned driver's generic transient list omits. +The exact code now follows the already accepted timeout-retry policy; no other +classification or retry bound changes. Both corrected health cases pass in a +fresh 14-second run. Complete correction-head regression remains pending. + +##### Full Step 4 round-1 correction validation (2026-10-16) + +Root verifies all four findings against the current implementation and completes +their corrections. The finite framework wait owns its actual operation before +scheduling; expiry closes later admission and records retained ownership before +returning the native slot. Real native controls cover held asynchronous cleanup +and held synchronous framework execution, independent healthy admission below the +retained threshold, and positive source/generation cleanup after release. + +Real PostgreSQL controls verify metadata-heartbeat timeout/recovery through the +registered health result, distinct failed fetched-job renewal/recovery, and held +expiration ownership. The production exit child now retains its actual private +callback through finite host waiting and native zero exit. Its separate unsafe +direct-Core-callback control requires supervised timeout, owned kill and actual +join; those facts are explicitly refused by the normal-exit predicate. These are +synthetic callback/fault controls over the shipped owners, not native resource +failure incidence or a claim of cleanup at process exit. + +The corrected Release solution build passes with CI warnings-as-errors and zero +warnings/errors. Fresh complete suites pass 2,166 unit, 321 architecture, four +contract, 176 Docker-free integration and 1,741 Docker/PostgreSQL integration +cases: 4,408 backend cases, zero failures/skips. The Docker suite takes 10m10s; +the architecture suite takes 12m26s. The latter is a measured run duration, not a +controlled speedup claim. Scoped inventory caching preserves mutation/undo and +exception freshness controls without adding a global cache or a new rule. + +All 22 changed C# files are formatted. Seven ADR parser controls, 1,917 local +links, 557 fragments, changed prose wrapping and whitespace checks pass. Earlier +failed focused runs are excluded from the passing complete-suite total; focused +controls overlap it and are not added again. No frontend/demo/current-head CI is +claimed here; Step 9 owns packet-wide reruns. Round 1's verified corrections are +qualified; a fresh full Step 4 round 2 follows their commit. Step 4 remains open +until that round and any verified corrections complete. Steps 5–9 remain pending. + +##### Full Step 4 review round 2 (2026-10-16) + +Round-1 corrections are committed as `53ec8a4a`; normal Leakwatch/format hooks pass +without changing the 22 validated C# source hashes. Three new independent +reviewers inspect the complete `def48a1a..53ec8a4a` range (123 files): GPT-6 +Astra/xhigh for runtime/lifecycle and two GPT-6.1 Sol/xhigh reviewers for +evidence/censuses and security/composition/corpus. They inspect the 4,408-case +passing receipts without rerunning them and affirm all four first-round fixes. + +One unique Major qualification gap remains: ADR-0059 explicitly requires sustained +metadata-heartbeat cutoff/reset and common database outage/recovery with an actual +held old operation, a spare slot and fewer than four retained entries. Current +controls prove real transient SQL recovery and separately requested drains, but +do not compose that mandatory matrix. The runtime reviewer independently confirms +the same gap; neither review alleges a demonstrated production-code failure. +Root verifies the accepted obligation and missing coverage. Isolated PostgreSQL +outage and owner-clock controls are being added before Step 4 closes; their native +Core/SQL observations and logical clock advances remain separately labeled. + +The security/corpus review also verifies one Minor status mismatch: Standards 05 +and Events/Outbox architecture still describe both full reviews as pending. Their +live summaries now delegate review dispositions to this owning record, preserving +earlier dated receipts. No new ADR, runtime policy, grant or business definition +is introduced by these corrections. New qualification and correction review remain +pending; Steps 5–9 do not start until Step 4's verified findings are closed. + +##### Full Step 4 round-2 correction validation and closeout (2026-10-16) + +The two added controls exercise the shipped lifecycle with actual PostgreSQL. +One holds the real server row, verifies transient failure without stored progress, +then observes a stored success resetting the owner cutoff. At the renewed exact +boundary, the owner refuses before provider acquisition or SQL. The other pauses +only a test-owned PostgreSQL container and lets all three actual native metadata +heartbeats fault. Owner-clock advances then drive past-cutoff drain. After real +storage recovery, the two clean pools replace their generations and serve work; +the affected pool retains its old actual scope cleanup despite a spare native +slot and one retained entry. Only positive cleanup permits its one replacement +and the pending admission. No shared fixture container is paused. + +These controls keep native Core heartbeat cadence and SQL/socket bounds real; +the four-minute policy interval uses the owner's logical clock. The held scope +is a synthetic barrier around actual native framework work. Neither test claims +four minutes of wall-clock outage, genuine resource-exhaustion incidence, +external-effect quiescence or production supervision. + +The final corrected-source focused run passes both controls. Three separately +compiled, temporary mutations of actual production source each fail at the +intended behavior: removed cutoff permits forbidden issuance; removed successful +reset refuses the next valid heartbeat; replacing actual cleanup with the stock +child join starts generation two while generation one still owns held cleanup. +Each mutant builds successfully and executes its one expected failing case with +zero skips. Original production bytes are restored and the CI-mode Release +solution rebuild passes with zero warnings/errors. These expected red controls +are not additional passing cases. + +A fresh independent runtime reviewer inspects the complete correction and all +final receipts, verifies source hashes and restored production bytes, and finds +no remaining issue. This supplements the full second round rather than replacing +it. The status corrections in Database Standards and Events/Outbox architecture +now link their current qualification to this owning record. No Accepted policy, +grant, dependency, migration or production business definition changes. + +The final complete Docker/PostgreSQL suite passes 1,743 cases, zero failures/skips, +in 12m33s. The unchanged non-Docker partitions retain the round-1 receipt: 2,166 +unit, 321 architecture, four contract and 176 HTTP integration cases. Together +these cover 4,410 distinct backend cases; this is a combined receipt, not a fresh +run of all five partitions at this correction. The two focused passes overlap +that complete Docker suite and are not added again. Six current corpus/trait +checks and seven ADR parser controls pass. The changed-document audit resolves +1,919 local links and 559 fragments with zero errors; added prose wrapping and +whitespace checks pass. None of these overlapping checks adds to the case total. + +Both full Step 4 reviews and all verified findings are closed. Step 4 is locally +complete; Step 5 proceeds automatically on development with the existing approved +transactional-owner, retry/recovery and terminal-audit scope. Steps 6–9 retain +capacity, external effects, recurrence and packet-wide enforcement/CI. No frontend, +demo, current-head CI or completed production business definition is claimed by +this closeout. + +### P02b-4 Step 5 — transactional owner and terminal audit (2026-10-16) + +**Locally complete after both fresh full review rounds, verified corrections +and independent focused fix verification.** +The existing approved package +owns this step; no new decision or approval is pending. Source implements the +closed ordinary root participant, acknowledged start publication, immutable job +attribution, final row/time fence and sticky cancellation-versus-COMMIT gate. +Business state, child jobs, outbox/domain completion and MUST audit share the +existing transaction owner. Positive COMMIT acknowledgement remains distinct +from subsequent scope/source cleanup; unknown COMMIT needs a real locked probe. + +Independent finite renewal, retry/recovery and terminal lanes retain actual SQL, +probe and cleanup owners. Six acknowledged starts preserve the five accepted +backoffs; unknown/Pending definitions defer, explicit retirement terminalizes. +The sixth audit seam binds only actual returned job-transition values and the +same live transaction. Terminal audit failure does not advance business work. +Source and application-pool ownership are qualified against the formulas in +[Database Standards](../standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity), +including timed-out auxiliary loaders and separately declared shared headroom. + +CI-mode Release builds pass with zero warnings/errors. The complete unit run +passes 2,212 cases with zero skips. Initial PostgreSQL qualification exposed +reserved SQL naming, transition cleanup and two real concurrency defects: + +- A joined admission probe could refresh the locked job header while retaining + an older attempt snapshot. It now reads the immutable attempt in a fresh + statement after locking the header, on the same connection/transaction. The + restored original JOIN fails the committed-admission regression while its + rollback control passes; restoring the correction makes both cases pass. +- Deferred count validation upgraded the parent lock to `FOR UPDATE`, blocking + renewal COMMIT behind an unrelated child's key-share lock. A forward migration + uses `FOR NO KEY UPDATE`, preserving count-writer serialization and applied + history. Real child-lock renewal and exact one-function Down/Up controls pass. + +Focused real PostgreSQL controls pass for business/outbox/child-job/MUST-audit +atomicity, stale authority, lock-wait expiry, uncertain COMMIT, terminal witness +substitution, and native terminal-audit backlog progress beyond two leases. +Actual application and privileged sources remain retained through ignored +cancellation, held callback and messaging cleanup controls. These overlapping +focused receipts are not a second complete backend run. + +The first full architecture run records 322 passing and six failing cases out +of 328, with zero skips. Failures identify the published method count, the same +JobExecutor's additional partial path, exact physical transaction-owner lists +and retained-factory scanning. Corrections preserve finite ownership and planted +controls; four focused count/writer/parallelism reruns pass. The new orchestration +detector indexes each evaluation's actual field instructions once, retaining every +mutation/restoration check. The corrected complete architecture run passes all +328 cases in 17 minutes 31 seconds. A fresh complete run also passes 2,212 unit, +four contract and 176 Docker-free HTTP cases, all with zero skips. + +The complete Docker run records 1,771 passing and 39 failing cases out of 1,810 +in 13 minutes 1 second, with zero skips. All failures belong to two old fixtures: +DeliveryExecution's observed-unit factory still resolved the removed raw source +alias, and EducationPersistence passed the driver's password-free connection +string view to its API composition. The former now passes the existing lazy +source explicitly; the latter supplies original fixture configuration while +preserving the Seeder's caller-owned source. No raw alias or second DI disposer +is restored. After a clean Release build, both complete classes pass all 43 cases +in 19 seconds, with zero skips. Their four overlapping earlier passes are not +added twice. Together these runs establish 1,810 unique passing Docker cases and +4,530 unique passing backend cases; this is not a second complete-suite rerun. + +Formatting, seven ADR parser controls, 1,755 local links and 500 fragments pass. +Both fresh full review rounds follow the validated implementation commit; no +completed review or Step 5 closeout is claimed. Steps 6–9 remain pending. + +#### Step 5 review round 1 + +Three fresh independent reviewers inspected `4826b7df..9b634405`: owner, +authority and lifetime (GPT-6-astra xhigh), control/SQL/terminal audit +(GPT-6.1-sol xhigh), and proof/composition/corpus (GPT-6.1-sol xhigh). The last +lens reviewed all 109 changed files and independently recalculated the composite +TRX totals and original-JOIN mutation/restoration evidence. Two confirmed groups +required correction; no additional Blocker or verified finding remained. + +- A cache caller could return while the original auxiliary task still cleaned + its connection. The executor froze this pending state as a permanent cleanup + failure, preventing eventual positive generation release. It now joins that + exact task without the expired caller token before deciding cleanup. Business + issuance closes first; framework's prior binding closes while its successful + admission keeps the same owner open. Genuine disposal failure stays retained. + Exact caller/signature controls reject extra, async, detached, missing and + token-taking joins. Four unit cases and native clean/dirty controls exercise + original loader cleanup, private callbacks, retained identity, healthy later + work and both requested source disposals. +- Business COMMIT-acknowledgement loss and final lock-wait expiry previously had + real PostgreSQL direct-executor controls only. New pinned native-worker cases + stage organization, child-job, outbox and MUST-audit effects. Lost ACK retains + the actual identity while a fresh database probe is causally locked, then + resolves without a duplicate effect or vendor retry. Expired/live final-lock + controls prove atomic rollback/commit and the actual retry disposition. + +CI-mode Release builds pass with zero warnings/errors. The complete unit run +passes 2,216 cases; the complete architecture run passes all 328 in 18 minutes +3 seconds; 36 focused PostgreSQL cases pass, including the five new native rows. +All report zero skips. The initial focused run passed 34 of 36; both failures +were the new auxiliary fixture attempting a second rollback after its lock had +already been released. Explicit lock ownership fixes teardown, and the same +36-case rerun passes without weakening a production assertion. + +The actual-source control restores the old pending-cleanup snapshot temporarily. +It builds, and both native auxiliary variants fail specifically because the +business task completed before its original cleanup. Restoring the exact source +bytes, rebuilding and rerunning makes both pass. Raw exception logging observed +in two existing helpers was not established as a new Step 5 disclosure or violated decision; it was not promoted to a finding +or bundled into this correction. + +The focused run overlaps 31 prior Docker cases and adds five. Combining current +complete unit/architecture, prior contract/HTTP, and the existing corrected Docker +receipts gives 1,815 distinct passing Docker and 4,539 distinct passing backend +cases, using `(testId, testName)` identity. This is explicitly composite evidence, +not another complete-suite rerun or current-head CI claim. Formatting, the +nonempty/zero-skip runner, seven ADR parser controls and local links/fragments pass. + +The second full fresh review round follows the correction commit. Step 5 and +Steps 6–9 are not declared complete by this first-round receipt. + +#### Step 5 review round 2 + +Three new independent reviewers inspected the complete `4826b7df..9dbea7bf` +range: owner/authority/lifetime (GPT-6-astra xhigh), control/SQL/terminal audit +(GPT-6.1-sol xhigh), and proof/composition/corpus (GPT-6.1-sol xhigh). Three +verified groups required correction; timer and control findings were independently +corroborated. No additional Blocker or verified finding remained. + +- Reconciliation silently stopped at a pending/faulted job auxiliary, then cleared + the rolled-back MUST intents. Removing that precheck lets the actual standalone + writer refuse another acquisition inside its existing reporting boundary. + Every intent now receives the required bounded Critical, operation-only failure + counter and unhealthy audit signal; the original business refusal stands. + Native clean/dirty controls assert the absent rolled-back audit row, actual DI + logger/meter/health signals and unchanged held resources. A two-intent unit + companion proves independent reporting without resolving another source. +- Timer disposal preceded renewal closure. A late acknowledged renewal could + rearm a disposed timer and cancel unrelated batch members through the shared + error path. Renewal now closes permanently under the publication lock before + disposal. A deterministic real-timer disposal-gap control keeps a second + execution live and forbids early identity release. +- A positively cleaned pre-COMMIT control fault discarded its original permanent + business decision. The request now retains that exact decision and retries on + the bounded existing cadence; uncertain COMMIT and failed cleanup keep their + separate paths. A native worker returns one permanent refusal, hits a real SQL + lock timeout, retains its exact identity/request, then terminalizes with one + MUST audit and no second business start, including after lease expiry and a + duplicate native wakeup. + +CI-mode Release builds pass with zero warnings/errors. The complete unit run +passes 2,218 cases; complete architecture passes 328 in 17 minutes 23 seconds; +37 focused PostgreSQL cases pass. The control-failure proof now captures progress +while its actual SQL is blocked, rechecks that wait, then observes a completed +failed iteration before separately asserting the retained request/identity. After +this test-only strengthening, a fresh clean build and the same 37-case run pass. +All passing runs report zero skips. + +Three actual-source mutations compile and fail their intended assertions: +silent audit refusal fails one unit and both native health controls; late renewal +closure fails at the disposed real timer; discarded control decisions fail the +retained-request assertion with zero pending outcomes. Each exact source is +restored in a finally, rebuilt and its same regression cases pass. No mutation +remains in the tree. Formatting, seven ADR parser controls, local links/fragments +and the nonempty/zero-skip runner pass. + + +The focused run adds one Docker case to prior corrected receipts. Current +complete unit/architecture, prior contract/HTTP and corrected Docker receipts +establish 1,816 distinct passing Docker and 4,542 distinct passing backend cases +using `(testId, testName)` identity. These are composite receipts, not another +complete-suite rerun or current-head CI. All nineteen job obligations remain +Registered; Step 9 owns final enforcement and packet regression. + +The corrections are committed at `6a2ded99`. Normal hooks pass eight-file +Leakwatch and seven-file C# formatting, with no C# byte changes after validation. +Two new independent reviewers verify that correction and its immediate +lifetime/authority and proof/corpus dependencies: GPT-6-astra xhigh and +GPT-6.1-sol xhigh. Both approve without verified findings. The proof reviewer +independently recalculates the composite counts, checks each intended mutant +failure, and compares exact restored source bytes. They inspect recorded local +receipts, without rerunning the toolchain or claiming current-head CI. This is +focused correction verification, not a third full review round. + +Step 5 is locally complete. Step 6 proceeds under the existing approved package; +Steps 7–9 and packet-wide regression/PR/CI remain pending. + +### P02b-4 Step 6 — tenant capacity reservations (2026-10-16) + +**Locally complete after both full review rounds and verified corrections.** +Step 5 closes at correction `6a2ded99` after both full rounds and independent fix +verification. Accepted ADR-0047 and the approved nine-step package own this step; +no new capacity-policy decision or approval is pending. + +- App-role admission locks the tenant/group mutex, resolves an optional registered + Hard LimitKey and counts every unreleased reservation across organizations and + instances. Deferral spends no normal attempt. Existing entitlement provider/key + contracts and empty production definitions remain unchanged. +- Successful business completion releases its exact reservation on the existing + business transaction. Failed or skipped work needs a distinct local actual + cleanup witness and acknowledged nonexecuting recovery authority before a + sequential app-role checkpoint can release occupancy. No executable receipt is + reconstructed after lost admission acknowledgement. +- A forward storage change records truthful transactional cleanup separately from + never-started or external-quiescence evidence. The original source owner stays + open across sequential phases while every old binding closes permanently. + Missing cross-instance cleanup evidence retains occupancy in recoverable parked + state, permitting a live origin's eventual positive cleanup; TTL never releases. +- Control handles each checkpoint as a bounded owned operation, preserving fair + service and actual stop/cleanup ownership. The existing transaction owner, + tenant-setter inventory and bypass reservation-write prohibition remain intact. + +Qualification covers two-instance/two-org caps, no-attempt refusal, unlimited/ +zero/downgrade/fault limits, atomic success/cleanup release, admission and checkpoint +COMMIT uncertainty, held callbacks/resources, missing-witness parking, exact grants +and source bounds. Each implementation/correction commit and both fresh review +rounds are recorded here after they occur. Live external execution remains Step 7; +final observation/enforcement and full packet regression remain Step 9. + +#### Step 6 implementation and qualification (2026-10-17) + +The app-role start owner locks the job, then the tenant/group mutex. A separate +post-wait statement counts every unreleased reservation across organizations and +instances. The registered Hard projection intersects the operational ceiling; +missing/unlimited, zero, positive, oversized and invalid/faulted answers retain +the accepted bounded semantics. Capacity refusal spends no attempt. No production +job definition, entitlement key or provider is introduced. + +Business success releases its exact reservation on the existing business/MUST/ +outbox/child-job completion transaction. Other grouped transactional outcomes +must join the actual admission/business, auxiliary resources, observers and +original private cancellation callbacks before minting a local cleanup witness. +Genuine no-start requires an atomic unused-entry seal, including receipt-less +admission uncertainty. This witness grants neither execution nor database truth. + +The confined recovery owner publishes a separate nonexecuting capability only +from acknowledged acquisition or an exact locked proof. The same original +application-source owner then enters one fresh sequential checkpoint. Its old +bindings remain permanently closed. Evidence and release commit together; +unknown checkpoint COMMIT probes read the descriptor's historical attempt after +the header lock, separately from current routing authority. Missing local cleanup +parks occupied work with a paced probe; neither TTL nor a replacement owner +manufactures cleanup. Stop retains and joins every issued checkpoint/callback. +Host stop admits no fresh cleanup checkpoint; a clean local stop cannot substitute +for cleanup evidence that never committed, so restart still retains that occupancy. + +Forward migration `20261016210528_add_transactional_job_capacity_cleanup` adds +write-once transactional cleanup evidence, its exact release reason and three +existing guard replacements. The predecessor's non-key count lock remains. +Only the app UPDATE and dispatcher status-SELECT column budgets expand; bypass +reservation writes remain refused. Down refuses recorded new history rather +than erasing or relabeling it. Canonical fresh DDL comparison remains exact; +Down/reapply accounts only for PostgreSQL's advanced physical position of that +single dropped/readded column, preserving every other inventory fact. + +Exact owner, framework-request, minting, command, task/callback, source and final +SQL-fence censuses gain closed enrolled paths and planted dirty/clean controls. +The existing transaction owner and ADR-0040's eight logical GUC setters remain; +the new executor partial belongs to the same ADR-0036 context writer. Its exact +accessor-writing file is enrolled explicitly; no new logical writer is added. +Sequential cleanup adds no simultaneous main/auxiliary checkout to the current +acquisition inventory. + +Initial qualification exposed two missing SQL separators in the new checkpoint +builder; actual native tests now fail directly through a sanitized observer fault +signal instead of hiding the handler failure behind a timeout. Both separators +are fixed and the same four real native cleanup/acknowledgement-loss cases pass. +It also corrected the no-plan fixture's empty-provider assertion and the precise +physical-column comparison above. Initial failing receipts are retained. + +#### Step 6 validation receipts (2026-10-17) + +Local CI Release build completes with zero warnings/errors. The full Unit suite +passes 2,229 cases, Contract passes four, and integration without Docker passes +176, with zero failures/skips. These are separate local suites, not current-head +PR CI or full packet closeout evidence. + +Focused PostgreSQL qualification passes all 192 cases after the SQL separator and +fixture corrections above. Eight additional native facade cases pass together, +including admission and capacity-checkpoint acknowledgement loss, private callback +retention and receipt-less genuine no-start. A first tight-budget no-start run +reached a disposal-barrier timeout once; that cause was not reproduced. The same +two cases and two repeated mixed eight-case runs then passed. The new no-start +fixture now uses the accepted five-second SQL budget and a ten-second transaction +budget, retaining every barrier and bounded failure diagnostic. This removes an +unnecessary cold-source/role-initializer/read constraint; it does not establish the +cause of that initial timeout. + +Three actual production-source mutations compile and fail their intended +behavioral controls: counting before the real tenant/group mutex wait (two cases), +leaving sealed unused execution permission open (one), and omitting the actual +private cancellation-callback join (three). The initial callback observation let +one mutant pass; the held-callback observation was strengthened, and all three now +fail against that mutant. Every source file is restored byte for byte, freshly +rebuilt, and the same respective controls pass. No mutation remains in production. + +The first full architecture run reports 330 cases, 327 passed and three failed. +Two failures identify stale exact admission/privileged-owner caller inventories; +the other exposes a detached-Cecil-method null dereference after the detector +already records the forbidden target. The corrected guard enumerates the actual +new owners and reuses the existing exact local-revalidation proof. The capacity +detector returns its known detached-target offenders before unsafe identity +inspection. No target filter, namespace exemption or weakened production boundary +is added. Both corrected clean guards and their complete planted-control tests +pass together: four cases, zero failures/skips. + +The corrected full architecture baseline passes all 330 cases in 1,695.7 seconds. +The first full Docker run reports 1,848 cases: 1,847 passed and one native framework +lifetime row timed out before reaching its real cleanup barrier. Both original +rows subsequently pass with bounded diagnostic observations; that does not +establish the cause of the earlier timeout. The corrected lifetime fixture keeps +actual pinned native workers, physical SQL deadlines, held cleanup and source/ +slot/stop assertions. It parks the three polling loops, issues exact native wakeups, +and advances only the owner observation clock after the actual barrier. This +intentionally removes incidental bridge ACK/cold-start timing from that lifetime +proof; separate real bridge/repair controls remain and pass with the common +PostgreSQL-outage proof: 21 cases. Both corrected lifetime rows also pass. + +Two invocation-local/name-first detector filters preserve complete subjects, +identity/signature/opcode checks, caller multiplicity and every clean/dirty/restored +mutation. The same four complete guards pass in 311.2 seconds versus 515.3 before +these filters. Capacity dirty control falls from 251.6 to 113.2 seconds; authority +from 261.9 to 196.3. A source/equivalence preflight finds no actionable issue; it +supplies no full Step 6 review credit. + +The final full architecture run passes **330/330** in 1331.9 seconds, and the +fresh full Docker integration run passes **1,848/1,848** in 889.3 seconds, +with zero failures/skips and identical case-name multisets to their baselines. +Together with Unit, Contract and Docker-free integration, these distinct local +suites pass **4,587** cases. Focused/negative/restoration receipts are overlapping +proof and are not added to that total. The local timing comparisons do not prove +the complete real CI backend job fits its 20-minute ceiling; Step 9 retains full +packet regression and real PR CI qualification. + +At this qualification head, both full fresh review rounds and their verified +corrections remained pending. All nineteen job obligations remain Registered; +Step 9 owns complete packet enforcement/regression. External execution and +recurrence remain Steps 7–8. +ADR-0061 is separately Accepted in `82956666`; its dependent Step 7 implementation +starts only after Step 6 closes its two full review rounds. + +#### Step 6 full review round 1 (2026-10-17) + +Implementation commit `caf51297` passed normal hooks with a clean tree. +Three fresh independent reviewers inspect its complete 64-file scope and connected +paths: two GPT-6-astra reviewers at xhigh for ownership/lifecycle and storage/ +isolation, and GPT-6-sol at xhigh for tests/corpus/performance. They inspect source +and actual receipts; they do not rerun the toolchain or claim CI qualification. + +Both runtime reviewers independently confirm one Major local lifetime race. After +an exact historical cleanup probe releases its row lock, another instance can route +the released job to a new generation before local recovery reacquisition. A clean +null acquisition then repeats the permanently obsolete generation, retaining the +original invocation despite settled history. The corrected null branch reinstalls +its exact historical cleanup descriptor when a checkpoint is already committed. +Settlement still needs the locked original evidence plus changed routing; a live +peer lease remains pending. The production correction is five lines and changes +neither schema nor grants. A separate permanent-decision durability concern is not +confirmed as a new regression against existing crash/recovery handling of decisions +not yet recorded. + +Three native takeover cases cover the probe-unlock interleaving, live-other-owner +retention and a lost recovery-acquisition COMMIT acknowledgement. The test proxy +holds the actual historical ROLLBACK response only after PostgreSQL unlocks; an +independent store performs real fenced routing. The live-lease control uses an +explicit privileged fixture lease and waits for another actual locked probe before +asserting retention. All preserve one original attempt/checkpoint and immutable +release history, then join the original source and native slot without host stop. +Before the final fixture strengthening, the first two cases failed the original +implementation's final-join assertion after their positive database premises. +Removing the re-probe correction from the final source compiles and fails all +three current takeover controls at their missing-probe or final-join assertion. +Exact source restoration and a fresh build pass the same three cases. This includes +the recovery-acquisition ACK-loss entrance and preserves live-peer retention. + +The proof review also identifies two missing native stop windows. New controls +stop after a real recovery ACK before checkpoint issuance, and after issuance +while its actual private cancellation callback is held. The first observes the +actual control loop past the issuance window while a separate stop callback keeps +final request release held. The second observes the real app task's known rollback +separately from the checkpoint's still-pending callback join. Neither source nor +invocation is falsely released. Removing both issuance guards or the checkpoint's +actual private callback join compiles and fails the respective intended assertion. +Both production files are restored byte for byte, rebuilt, and pass those controls. + +Initial takeover-harness runs do not supply runtime proof: a thirty-second proxy +lifetime obscured the primary failure, and a diagnostic run exposed a row-description +flag reset at each ReadyForQuery before the intended ROLLBACK hold. The corrected +proxy has a separate finite test lifetime, transaction-scoped observation and primary +failure preservation. A read-only fixture preflight strengthens the actual second +probe, exact peer lease fence and host-stop cancellation premises; it supplies no +full second-round credit. + +The new release reason joins the existing real app-role forged-release refusal / +removed-trigger dirty control. Standards 05's stale pending-qualification wording +is corrected. Two further invocation-local/name-first Cecil filters preserve every +production subject, exact signature/opcode, caller multiplicity and planted control; +no global cache or owner exemption is added. + +Fresh format and CI Release build pass with zero compiler warnings/errors. The +focused native/release set passes nine cases. Full Unit passes 2,229, Contract four, +Docker-free integration 176, Architecture **330/330**, and Docker integration +**1,854/1,854**, all with zero failures/skips: **4,593 distinct full-suite cases**. +The architecture case multiset is unchanged; all 1,848 previous Docker cases remain +and six new cases account for the difference. Focused and mutation receipts overlap +these suites and are not added to that total. Full architecture takes +1318.4 seconds versus 1331.9 at implementation qualification; +full Docker takes 933.2 seconds. These are local measurements, +not a real CI budget pass. Current-head CI remains unrun. + +The first-round corrections are locally qualified. The second full fresh review +starts only after their normal local commit. All nineteen job obligations remain +Registered; the published architecture-method count remains 237. Step 6's second +full review gate is pending. Steps 7–9 and full packet/PR/CI closeout remain pending. + +#### Step 6 full review round 2 and local closeout (2026-10-17) + +First-round correction `d387f71f` passed normal hooks with a clean development +branch. Three new independent reviewers inspect the complete **68-file** Step 6 +scope: GPT-6-astra at xhigh independently covers ownership/lifecycle and storage/ +isolation, and GPT-6-sol at xhigh covers proof/corpus/performance. They inspect +source and parse actual receipts, without claiming personally executed tests or CI. + +Both runtime reviewers independently identify one further Major admission-lifetime +race. A physical admission COMMIT can fail before reaching PostgreSQL, leaving no +original attempt or reservation while its local outcome correctly remains uncertain. +If a peer clears the expired routing token before original scope cleanup finishes, +the old probe sees changed authority. Discarding that admission descriptor then +retries recovery acquisition for history that cannot exist, retaining clean work. + +The correction makes a fresh exact admission-token history read after acquiring +the actual job-row lock. Locked absence proves rollback independently of current +routing. Existing original history remains distinct from a peer's later attempt; +positive original release requires its exact reservation and corresponding immutable +evidence. Changed authority alone never settles the request, and its unresolved +historical descriptor remains retained. The read probe changes no peer state and +constructs neither executable nor recovery authority. No schema, grant or source +capacity changes are needed. + +The new native control drops the actual second app COMMIT request before the server +receives it, holds real original scope disposal, and uses an independent real +recovery store to clear expired routing. It verifies absent original attempts/ +reservations, uncertain admission with no executable receipt, no business constructor, +and original control/source/native join without host stop. The unchanged production +source fails at that final-join assertion; the correction passes. Four guarded +app-role history cases distinguish absent original with/without peer admission, +committed occupied original, and positively released original before a real second +peer admission. The positive history setup is explicitly a storage fixture rather +than a minted runtime cleanup witness. Peer header and occupancy remain unchanged. + +Two additional fresh reviewers, GPT-6-astra and GPT-6-sol at xhigh, inspect the +complete correction and its connected owner/history/proxy controls without further +verified findings. The targeted set passes ten cases, including actual lock wait, +lock timeout and both existing native admission-ACK outcomes. Removing historical +probe dispatch compiles and fails the native join plus three history assertions; +the occupied-original control still passes. Making existing history falsely mean +rollback separately fails that occupied-original control. Both source mutants are +restored byte for byte with their modes, rebuilt, and the same five cases pass. +Focused receipts and negative mutations overlap the full suite; they are not extra +passing cases. Formatter normalization changes only test whitespace. + +The first full Docker receipt reports 1,858 passed and one failed among 1,859 +cases, with no skips. The common-outage fixture times out after the owned database +pause while waiting for all three original metadata-heartbeat fault observations. +It supplies no evidence of a failed pre-outage healthy job or a cause linked to the +admission-history correction. A separate read-only source diagnosis establishes no +deterministic production fault. Bounded elapsed-phase and failure-time memory-only +pool diagnostics are added before teardown; no wait, option or assertion changes. +The same focused scenario then passes in 38.2 seconds, with pause completed at +0.55 seconds and all native faults observed at 35.3 seconds. This later pass does +not establish the earlier failure's cause. Both independent correction reviewers +inspect the diagnostics and this evidence limit. The original failed receipt is +retained. The second complete Docker run passes that outage scenario, but the +new native rollback case fails before the intended COMMIT drop: zero drops, one +bridge ACK and no retained control execution. No history assertion is reached. +Source inspection confirms a permitted setup race: bridge ACK takes the job-row +lock, native routing can skip that lock, and the default 60-second repair grace +exceeds this fixture's 30-second wait. The receipt does not establish that race +as its cause. The fixture now mirrors the existing lifetime controls: park empty +owner polling, issue an explicit stock/native wakeup, then pulse only owner polling +for the actual original join. It asserts zero initial bridge ACKs and retains the +real second-COMMIT drop, peer takeover, zero attempts/reservations and source refusal. +The outage fixture similarly parks polling around its existing explicit wakeups; +its real heartbeat cadence, 90-second bound and all lifecycle assertions remain. +Both independent reviewers verify the actual eight-file candidate against its +manifest without a further confirmed finding. The repeated production removal +mutant reaches the real COMMIT drop and fails specifically at original final join; +exact restoration passes. Both complete failed receipts remain recorded; the +fresh complete Docker receipt below is a separate passing result. + +Final full format verification and CI Release build pass with zero compiler +warnings/errors. The critical native/history/stop/release and lifecycle set passes +**24/24**. +The last changes affect only the two integration fixtures; the exact production +bytes and earlier full Unit/Contract/Docker-free/architecture subjects are unchanged. +Full Unit passes **2,229**, Contract **4**, Docker-free integration **176**, +Architecture **330/330**, and Docker integration **1,859/1,859**, with zero failures +or skips: **4,598 distinct full-suite cases**. Architecture names are unchanged; +all 1,854 preceding Docker cases remain and exactly five new cases account for +the increase. Full architecture takes 1315.5 seconds; +full Docker takes 960.2 seconds. These local measurements +provide no real GitHub Actions budget pass; current-head CI remains unrun. + +Step 6 is locally complete after both full fresh reviews, verified corrections +and their independent verification. All nineteen background-job obligations stay +Registered and the published architecture-method count stays 237; Step 9 owns +complete packet enforcement/regression and real PR CI. Accepted ADR-0061 in +`82956666` authorizes the next external-stage implementation. Steps 7–9 and full +packet/PR/CI closeout remain pending; no production business definition is added. + +### P02b-4 external completed-failure proposal (2026-10-16) + +**Initial proposal status, before the 2026-10-17 acceptance: Proposed; the +maintainer's first review required changes and explicit reapproval.** Current +acceptance is recorded [below](#adr-0061-acceptance-and-step-7-contract-2026-10-17). +Step 7 preparation identified an unanswered report-policy input: direct completed +Failed/Cancelled reports carry outcome/quiescence, without classifying the failure +or granting retry of the same stable logical operation. Existing guards permit +both retry and finalization; they do not select between them. + +The initial [ADR-0061](../decisions/0061-known-external-job-failure-policy.md) draft +at `8e0f982b` proposed separate failure class and same-operation permission, +write-once status and a terminal code when transient work cannot be repeated. +Its initial source/contract audit was against `6a2ded99`. No dependent Step 7 runtime or migration is implemented or +authorized by this proposal. Step 6 capacity work continues under Accepted +ADR-0047; the existing nine-step review/commit loop remains unchanged. + +**Initial-draft reviews at `8e0f982b`:** two fresh independent proposal reviewers +(GPT-6-astra xhigh and GPT-6.1-sol xhigh) approve that initial draft for maintainer +consideration without verified findings. They +check the actual contract/guard/grant and reason carriers, the exact bounded +supersession, restart equivalence and discriminating pending proof obligations. +The corpus reviewer independently verifies the ADR's links/anchors, Proposed +status and prose width. No runtime test is claimed. Maintainer acceptance still +precedes dependent Step 7 implementation. + +#### ADR-0061 revision after maintainer review (2026-10-17) + +**Historical revision record, before acceptance below.** +The maintainer requested changes to the initial proposal; that review was not +approval. Source checks confirm the missing finalization/terminal policy guards, +the app/control ownership distinction and the absence of durable cancellation +origin. The [revised ADR](../decisions/0061-known-external-job-failure-policy.md) +remains Proposed and supplies the complete decision and proof inventory. + +The new choices for reapproval are one nonzero three-state policy and Permanent +only for Failed. Cancelled explicitly states repeatability of the same operation; +malformed Permanent cancellation is rejected without rewriting it. Adapter truth +must survive reconciliation, while the runtime claims no certification of external +causality. App-owned selection, deterministic storage and actual-row-bound audit +cover retry, finalization and terminal reasons. The ADR separately maps module +reasons, capacity release and all seven affected Registered rules. + +Two new independent reviewers, GPT-6-astra xhigh and GPT-6.1-sol xhigh, approve the +full revised proposal for maintainer consideration without Blocker/Major findings. +Their verified Minor corrections name stored outcome kind rather than an +identifier DTO, and publish a clearly Proposed glossary pointer now. Both reviewers +verify those corrections without further findings. These are source/design reviews; +no new runtime, migration or passing execution proof is claimed. + +Error Handling's inherited five-attempt/jitter summary is independently reconciled +with already Accepted ADR-0047. This does not accept ADR-0061 or change its budgets. +No Accepted ADR body is edited. Explicit maintainer acceptance and its own decision +commit still precede dependent Step 7 implementation; Step 6 continues independently. + +### ADR-0061 acceptance and Step 7 contract (2026-10-17) + +**ADR-0061 is Accepted — 2026-10-17.** The maintainer's latest review considers +the previous seven gaps closed and finds no acceptance blocker, conditional on +correcting the catalogue Status step lists before the acceptance commit. This +decision includes Storage Steps 1–2, 6–9 and Retries Steps 4–5, 7 and 9; all seven +affected rules remain Registered, with counts unchanged. Their extended Asserts +record pending Step 7 qualification and Step 9 enforcement, not completed proofs. + +[ADR-0061](../decisions/0061-known-external-job-failure-policy.md) selects the +three-state policy, Permanent only for Failed and deterministic database retry, +finalization and reason guards. The app owns the immutable attempt outcome/policy +and finalization selection; actual returned row facts bind terminal audit. +[ADR-0047 Amendment 4](../decisions/0047-transactional-background-job-runtime.md#amendment-4--known-completed-external-failure-policy-2026-10-17) +discloses the exact completed-report input replacement and additive seams without +rewriting the Accepted body. The decision index, glossary, Error Handling status +and all seven catalogue assertions are synchronized in this acceptance decision. + +Winning owned stop closes new outcome-checkpoint and COMMIT admission even with +a live database lease; an already admitted COMMIT retains its actual result. +Durable confirmed outcomes win over later reports. Honored cancellation remains +Cancelled across restart. A nonrepeatable cancellation may finally fail the same +job during deploy through the prepared domain finalizer and atomic MUST audit; +the Transient taxonomy supplies no promise of resumability. + +Step 7 now implements and qualifies this contract before external activation, +including the forward migration and normative implementation carriers. Step 9 +closes full enforcement/regression. The nine-step sequence and two fresh +independent implementation review rounds per step continue; the historical draft +reviews above do not satisfy them. Step 6 capacity work remains independently +authorized under ADR-0047. Acceptance supplies no new runtime or passing proof. + +### P02b-4 Step 7 — external stages and recovery (2026-10-17) + +**Implementation, both full review rounds and verified corrections complete.** +The round-2 closeout below owns the final local receipts. Step 6 +closes at `0ea50b15` after both full reviews, verified corrections and 4,598 passing +full-suite cases. Accepted ADR-0047 and ADR-0061 authorize this next step on +`development`; no further decision or permission is pending. + +**Remaining closure units — 2026-10-17.** The original Step 7 scope remains +unchanged. Its long-running implementation is now tracked by these explicit +closure units; focused receipts below do not close the step or its full reviews: + +- [x] Finish no-plan terminal cleanup, exact owner handoff and atomic terminal + audit, including persistent reason and complete positive history guards. +- [x] Finish finalizer rollback/retry/refusal/exhaustion and prepared uninvokable + terminal behavior, preserving the separate six-start finalization budget. +- [x] Close external/transactional contention, retained cleanup, exact owner/ + source/caller censuses and their planted violations; qualify the complete step. +- [x] Commit Step 7 and complete both fresh independent full review rounds, + verified corrections and correction commits before advancing to Step 8. + +The foundation separates sticky process/run stop from eight finite stage COMMIT +boundaries. Admission is prebound before SQL; physical acknowledgements survive +stop without reopening later stages. Transactional capacity cleanup retains its +own fresh boundary on the same process cell and original clean source. The actual +successful result reaches the existing sole completion participant. Closed report +factories require the explicit three-state policy; Completed is removed. + +An early targeted source review identifies one P1 with two stop-refusal paths that +faulted owned tasks before their finite cleanup/publication handling. Both paths +are corrected. Two actual source mutants independently fail the corresponding +admission or grouped-business regression while its sibling passes. Exact source +and modes are restored, the CI Release builds have zero compiler warnings/errors, +and that correction's focused foundation suite passes 61 cases with zero failures/skips. +The reviewer independently verifies the correction, actual receipts and restoration. +These checks and that early review supply no full Step 7 review-round credit. +Two earlier failing fixture receipts remain recorded; the diagnostic identifies +an incorrect NeverStarted expectation, corrected to the existing positive owned +transactional-rollback result while separately asserting unused root entry. + +The forward failure-policy migration and canonical guards now pass 189 actual +PostgreSQL storage cases. Two early source-review findings are reproduced and +corrected: terminal requests cannot set the incomplete-finalization flag before +the actual terminal transition, and incompatible retained predecessor selection +or outcome/release history refuses upgrade without inventing missing facts. +Independent correction inspection verifies those fixes. External denial also +covers pre-existing UoW frames before their state changes and the four concrete +owner-null auxiliary loaders; their original failing controls and corrected +receipts are retained. + +The original-execution checkpoint foundation adds exact app-role read, Arm and +Outcome requests on the existing transaction coordinator. Prepare captures its +actual successful typed result, writes the immutable canonical plan and stamps +the original normal attempt in the same transaction. Its clean source remains +available for the next sequential checkpoint. These paths do not activate the +external routing engine. + +An early checkpoint review identifies a canonical-byte defect: JSONB parameters +rewrote text-column payloads. Both plan and outcome now use text parameters. +Actual PostgreSQL execution separately exposes four missing SQL-concatenation +spaces; the initial six failures and diagnostic `42601` receipt remain recorded. +After correction, six state/policy cases and two typed byte-boundary cases pass. +The production Prepare and Outcome writers preserve 65,536-byte canonical JSON; +a 65,537-byte outcome refuses before mutation and leaves occupancy retained. +Reintroducing only the plan JSONB binding fails all eight cases, including the +actual plan byte CHECK. Reintroducing only the outcome binding fails seven while +the oversized-input refusal still passes. Exact source/mode restoration passes +all eight again. Independent correction review verifies source, receipts and +both restoration hashes; this supplies no full Step 7 review-round credit. + +At the earlier checkpoint snapshot, the full Unit assembly passes 2,305 cases and the +focused PostgreSQL selection passes 349, with zero failures or skips. The latter +includes all 189 storage cases, the eight checkpoint cases and existing physical +owner/business/audit/helper/source controls. Its receipt validator initially +expected 342: the expanded class filter also selects seven unchanged source-owner +siblings. A separate exact-subject and 95-file source/hash audit confirms all +original subjects plus those seven passing cases; no failed test is reclassified. +Fixture-supplied admission and Audit Off business roots isolate checkpoint SQL; +these are not provider execution or domain-MUST-audit proofs. + +The original Execute bridge now requires the exact command owner's physical Arm +acknowledgement, the current Arm boundary, the original clean source and a frozen +canonical plan. The external denial scope precedes adapter construction; the +actual task, immutable observation and failed cleanup owners remain retained. +An early review catches a command borrowing another command's gate acknowledgement; +the correction and its discriminating regression are verified independently. + +Fresh recovery has a distinct eighteen-column status projection and never mints +a counted start receipt. Its new lease can outlive the original attempt deadline. +Acquisition/probe publication follows actual COMMIT acknowledgement or explicit +probe rollback acknowledgement and successful resource cleanup. A specialized +owner retains the originating operation, exact descriptor and process stop cell; +all confirmations share one receipt and one source/run binding. Early review +identifies original-cleanup substitution, duplicate receipt publication and a +cross-process-cell edge; all three are corrected and independently verified. + +The corrected snapshot passes 2,331 full Unit cases and 75 focused PostgreSQL +cases with zero failures/skips. Four actual source mutants each fail exactly their +intended regression; baseline and every restored source pass all eight selected +cases. Exact source hashes/modes and the receipts are independently audited. +Two further PostgreSQL cases prove actual acquisition COMMIT-response loss with +repeat confirmation of the same receipt, and refusal after a real token takeover. +The complete seventeen-case external checkpoint selection passes after those +additions. These storage/ownership checks do not claim provider execution, +domain-MUST atomicity or full Step 7 review-round credit. + +The three closed app requests now distinguish original admission from fresh +recovery authority. Original ledger identity remains separate from the current +recovery token; an expired original deadline does not invalidate a live recovery +lease. The read represents an absent plan explicitly and obtains causal metadata +from the actual app-role envelope. Its provisional recovery context invents no +trace, parent, incoming event or actor. Stored-fact parsing requires the exact +reservation and complete canonical plan/outcome, policy, quiescence and release +facts. Existing completed outcomes take precedence over conflicting later reports. + +An early app-owner review identifies a reused-plan exhaustion defect: a sixth +normal admission stopping before Arm lacks the plan stamp required by failure +selection. Two actual PostgreSQL regressions reproduce the exact `23514`, both +for first no-start and for independently retained unstamped no-start history. +The correction copies the validated immutable plan identity in the same locked +no-start transaction, preserving any existing timestamp and release. Its first +rerun exposes a second guard ordering issue: validated recovery finalization is +checked before eligibility-cycle normalization clears its token. The forward +migration and canonical guard now admit that exact app transition; normalizing +the new cycle still clears all recovery ownership and advances generation. +The predecessor Down body remains unchanged. Both failures remain in the receipts. +Independent inspection approves both corrections without full-round credit. + +The corrected snapshot passes all 2,331 Unit cases and 275 PostgreSQL cases: +189 storage, 26 external checkpoint, 20 capacity-admission and 40 control cases, +with zero failures/skips and a CI Release build with zero warnings/errors. +The checkpoint selection includes sixth-admission first/retained no-start, +recovery success and final-failure selection, token revocation and generation +advancement, no-plan recovery, armed no-start refusal and durable-outcome +precedence. These remain app/storage proofs with explicit fixture admission and +Audit Off roots; provider/native execution and domain-MUST atomicity are pending. + +The subsequent short-checkpoint boundary captures a conservative monotonic +lease window from fresh SQL after the actual job lock and before writes. +Original work also observes its immutable deadline; recovery uses only its fresh +lease. After pending audit, the exact owner's COMMIT admission checks the elapsed +window inside the same run lock as the stage CAS. Expiry closes the run and rolls +back; it cannot borrow an earlier successful handler check. This adds no generic +participant, callback or transaction entry. + +That boundary snapshot passes 2,333 Unit and all 32 PostgreSQL checkpoint cases. +Six cases park the actual handler before COMMIT admission without token +cancellation: Arm, original Outcome and recovery Outcome each have live and +expired-lease controls. PostgreSQL time establishes expiry; assertions inspect +actual rollback or committed intent/outcome/selection and capacity release. +Removing only the elapsed predicate fails exactly the three expiry cases while +all three live controls pass. Restoring exact source bytes and modes passes all +six again; both CI Release builds have zero warnings/errors. This remains a +targeted ownership proof, not external engine activation or full review credit. + +Read completion now also binds the exact canonical candidate recorded by its +actual read-only owner. An unrelated successful result or an unchanged clone +cannot obtain that owner's acknowledgement. Three actual PostgreSQL controls +verify the physical read-only transaction and application role, reject missing +or substituted candidates and accept the real recorded object. This later +snapshot passes 2,333 Unit and all 35 checkpoint cases, with zero failures/skips +and a CI Release build with zero warnings/errors. Executor read-handle publication +and cleanup ownership are qualified in the subsequent snapshot below. + +The named executor read driver now publishes an immutable handle only from the +exact acknowledged app-read candidate and positively completed cleanup. Recovery +uses provisional null causal metadata during Read; its handle retains only the +actual app-read envelope for later checkpoints. Actual held and throwing DI scope +controls cover both original and recovery origins. A physical read acknowledgement +survives cleanup failure, while the failed scope/unit owner stays retained and no +handle is published. + +An early review reproduces a cancellation gap after registration disposal but +before Activity cleanup, together with the pre-cancelled-entry edge. Registration +now remains owned through all actual cleanup; a final token check closes the run +before publication. Both original red cases fail on the intended open-run state. +The corrected snapshot passes 2,333 Unit and all 44 PostgreSQL checkpoint cases, +with zero failures/skips and a CI Release build with zero warnings/errors. +Subsequent test-only Task.Run hardening first exposes a test-ordering race in +the pre-cancelled case. Awaiting that actual task before its assertion corrects +the test; the held-cleanup case still asserts closure before release. Both final +cases pass after recompilation. Independent review verifies the unchanged +production hashes, exact subjects and separate receipts, closing the focused +finding without full Step 7 review-round credit. + +The named Arm, original/recovery Outcome and recovery-only NoStart drivers now +consume that exact read handle, retain their actual sealed request and await +scope, Activity, binding and cancellation cleanup. Original admission identity +stays separate from fresh recovery ownership. Only the actual app-read envelope +supplies later causal attribution; no provider report or bypass projection does. + +An early writer review corrects lost Activity ownership when Start throws and +duplicate issuance borrowing an earlier gate's COMMIT history. Real observer and +repeated-Arm cases discriminate both fixes: each source mutation fails exactly +its intended controls, and exact source/mode restoration passes again. All four +CI Release builds have zero warnings/errors. The first causal fixture run retains +two pre-driver `23514` failures from a nonexistent parent; a real parent row fixes +that fixture. Independent review audits 119 restored source hashes/modes, 2,333 +passing Unit cases and all 54 passing checkpoint cases, including ten named-writer +cases. This is a bounded slice receipt, not external activation. + +Six additional cases pass in the complete sixty-case checkpoint rerun. Actual +TCP COMMIT-response loss leaves Arm/Outcome uncertain while an outside app read +observes the landed transaction. Stop after the real handler but before COMMIT +records actual rollback; pre-cancelled entry and cancellation during held Activity +cleanup close continuation without erasing historical ACK. One further passing +case distinguishes an unissued duplicate from an earlier command's known rollback +and then commits through a fresh gate without another counted attempt. Production +source is unchanged from the 2,333-case Unit snapshot; the sixty-plus-one receipts +cover 61 distinct checkpoint cases. Seven ADR-parser and five corpus checks pass. +Provider/native integration and full Step 7 reviews remain pending. + +The original Execute bridge now accepts only the trusted read handle and exact +local Arm result. Fresh Reconcile accepts only its once-bound recovery and read +handle. Both retain the actual provider/cleanup task and external denial; stored +outcomes or absent intent skip provider construction without fabricating a report. +The last typed method-entry CAS remains separate from any earlier validation. +These helpers remain unwired to native execution and current-lease control. + +The next snapshot passes 2,333 Unit and eleven actual PostgreSQL bridge cases. +An early test review corrects masked ACK-isolation coverage using a real read +and an explicitly synthetic negative result around a distinct unacknowledged +command. It also distinguishes the first scope-only receipt from constructor +proof: that host lacked the fixture's adapter registration. The revised test-only +binding invokes the exact frozen, unchanged throwing constructor and records its +actual fixed exception under external denial. All eleven revised cases pass. +Removing both command-derived ACK checks fails only the borrowed-ACK case while +six siblings pass; exact source/mode restoration passes all seven again. Both +CI Release builds have zero warnings/errors. A throwing constructor proves entry +or refusal, never successful Execute/Reconcile or native lifetime semantics. + +The same start-observer ownership defect is then reproduced in the admission and +Prepare entry paths: both actual cases fail because the started Activity was lost +before assignment. Assigning the actual object before Start corrects both paths. +The subsequent CI Release build has zero warnings/errors; 2,333 Unit and 137 +PostgreSQL cases pass with zero failures/skips. That selection comprises all 74 +external-checkpoint cases, 23 admission, 20 business and 20 capacity-admission +cases. It includes both original red observer cases, the revised bridge controls +and the existing stop/cleanup/commit regressions. Full Step 7 review and native +activation obligations remain open. + +The history foundation now retains an exact issued Prepare/Arm/Outcome/NoStart/ +Finalize operation, with immutable business-result receipt and gate identity. +A separate job lock precedes its fresh, status-only 48-column original-attempt +query. Confirmation publishes only after explicit probe ROLLBACK acknowledgement +and actual cleanup; it never sets physical COMMIT ACK or rollback. Real lost-ACK +controls cover Prepare, Arm, Outcome and NoStart with open and stopped runs, plus +a closed duplicate Prepare that cannot borrow its predecessor's history. + +Early review corrects two unqualified Finalize classifier branches and separates +historical Arm truth from current Execute permission. Both the outer bridge and +last run CAS now require the exact command, current original owner and a +conservative monotonic lease/deadline observation. Live, takeover with an open +old run, elapsed-lease and borrowed-command controls use actual app checkpoints; +their positive remains constructor-canary evidence, not a successful provider +method. This snapshot passes 2,333 Unit and 127 PostgreSQL cases: 87 checkpoint, +20 business and 20 capacity-admission, with zero failures/skips and a CI Release +build with zero warnings/errors. An earlier Unit run retained one obsolete +unissued-root rollback assertion; its correction preserves the independent +positive unused-entry and capacity-cleanup controls. No full review credit or +Finalize/native qualification follows from these bounded receipts. + +Additional history controls distinguish COMMIT-request loss from response loss: +all four original checkpoint families remain Absent when COMMIT never reaches +PostgreSQL, without inventing a physical rollback acknowledgement or reopening +the old root. Two probe cases hold or lose the actual ROLLBACK response; a peer +acquires the released job lock before client acknowledgement, and confirmation +publishes only after acknowledgement and cleanup. Two later-admission cases keep +history bound to the original stamped attempt after current identity changes. +Replacing that query join with the current attempt fails exactly those two +controls; all sixteen same-current controls pass. Exact source/mode restoration +passes all eighteen. Both CI Release builds have zero warnings/errors. + +The wider history snapshot passes 2,333 Unit and 179 PostgreSQL cases: 99 +checkpoint, 40 control, 20 business and 20 capacity-admission. An independent +receipt audit verifies all 130 recorded source hashes/modes, exact subjects and +artifact hashes. These app/storage proofs do not exercise successful provider +methods or Finalize; socket-loss cases do not independently inject every disposal +failure. + +The ordinary business completion owner now also carries one conservative +COMMIT budget from its fresh locked SQL observation. Prepare's final plan-stamp +cleanup and transactional reservation-release cleanup consume that interval. +The existing coordinator reaches a synchronous, exact-root wrapper; elapsed +time is checked inside the same run lock as COMMIT admission. One-way publication +states prevent concurrent or duplicate recording from replacing the first +timestamp or interval. No new participant, callback or transaction owner is added. + +Four actual PostgreSQL controls pause the final Npgsql command after successful +SQL/reader cleanup, with no cancellation token or runtime timer closing the run. +Both expired-lease cases fail against the earlier implementation because it +acknowledges COMMIT; both live controls pass. The correction passes all four. +The final publication-state snapshot passes 2,333 Unit and 183 PostgreSQL cases: +103 checkpoint, 40 control, 20 business and 20 capacity-admission, with zero +failures/skips and a CI Release build with zero warnings/errors. Transactional +admission is the production path; Prepare still uses the explicit fixture +admission. These focused checks supply no full Step 7 review-round credit. + +The existing owner-boundary detector now enumerates the exact budget methods, +callers, private publication fields, fresh SQL observations and protected COMMIT +ordering. Its actual-subject and planted-control cases both pass. Controls include +extra callers, deleted capabilities, changed projections, late capture, mutable +budget reset, missing live identity and a plain-CAS bypass. This finite structural +check supplements the actual PostgreSQL expiry controls; it does not prove every +possible value, branch or asynchronous control flow. Full census qualification +and both full Step 7 review rounds remain pending. + +The shared app reader also validates the selected normal attempt, finalization +status and module reason. Its eleven focused cases cover completed policy rows, +sixth-attempt repeatable failures, positive no-start history and all partial-null +selection shapes. Projection-only dirty inputs reject mismatched identity, stamp, +status or reason without altering guarded durable data. An earlier run retained +one fixture failure from waiting for the original deadline instead of the lease; +the corrected helper and expanded matrix pass. The current snapshot passes all +2,333 Unit and 192 PostgreSQL cases: 112 checkpoint, 40 control, 20 business and +20 capacity-admission, with zero failures/skips and a CI Release build with zero +warnings/errors. These are reader/storage proofs, not actual Finalize execution, +successful provider methods or the domain/terminal two-MUST atomicity proof. + +The actual app Finalize path now reads and cleans its selected-input owner before +ordinary root entry, admits a separate counted finalization attempt and constructs +the exact registered typed request. Finalize bypasses capacity admission and +creates no reservation. Its existing business owner rechecks the actual selected +normal facts after the job lock and retains the same monotonic COMMIT budget. +Successful domain failure writes terminal state and its MUST row on that pair; +the private app mint binds the actual returned row, old acquisition token, live +unit/source/announcement and selected policy. The existing bypass mint remains +separate. A duplicate consumed root has no new read or COMMIT history. + +Four actual PostgreSQL cases cover success and permanent/nonrepeatable completed +failure. The first run passes success but refuses the three failure cases with +`42501`: the authored UPDATE unnecessarily names a control-only incomplete flag. +Removing that assignment and requiring the existing false value preserves the +column grants; all four pass. Final assertions bind audit identity, generation, +timestamp, policy and counters to actual stored facts. The corrected snapshot +passes 2,333 Unit and 196 PostgreSQL cases: 116 checkpoint, 40 control, 20 business +and 20 capacity-admission, with zero failures/skips and a CI Release build with +zero warnings/errors. Normal admission, observations and the routing claim remain +explicit fixture setup; app Finalize admission, receipt, read, root, fence and +terminal MUST write are production paths. These cases use an Audit Off root and +do not claim a domain mutation with two MUST rows, native provider execution, +independent witness-substitution coverage or full Step 7 review-round credit. + +The physical-ACK Arm path also retains its original conservative SQL interval. +An actual PostgreSQL control demonstrates that ACK alone previously allowed +provider scope construction after that lease expired, without cancellation or +a native timer; the live control passes. The corrected gate publishes its one +immutable interval only for an issued open boundary. Both the pre-scope check and +the final Execute CAS check elapsed time; the latter runs inside the original run +lock. Premature or late rejected COMMIT calls cannot seed a window for a later +unbudgeted acknowledgement. Known entry expiry reports EntryRefused, preserving +the physical ACK and inventing no provider failure or outcome. + +The corrected snapshot passes 2,335 Unit and 198 PostgreSQL cases: 118 checkpoint, +40 control, 20 business and 20 capacity-admission, with zero failures/skips and +a CI Release build with zero warnings/errors. The unchanged throwing adapter +canary verifies pre-scope refusal; a real held-constructor/provider-method timing +proof remains part of the positive SDK work. Lease renewal does not extend this +retained interval, and repeated history probes do not replace the gate's first +confirmation. These conservative refusals are distinct from permission to execute. + +The separate positive SDK fixture now supplies genuine Contracts, Application and +Infrastructure assemblies, with actual nested Tenancy commands and their MUST +audits. Its adapter calls an independent provider database using a separate, +unprivileged credential. Normal External routing and app admission use the actual +opaque claim, tenant capacity mutex and counted ledger; Finalize uses its separate +real admission. The first routing run exposed an ungranted outcome-body read; +the corrected predicate uses the already granted outcome-kind status instead. +No dispatcher grant is widened. Production definitions remain empty and the +construction-only test host runs no native background worker. + +Eight focused PostgreSQL cases pass: four actual provider outcomes, two exact +audit-INSERT faults and live/expired adapter-constructor barriers. A test-owned +SQL observer records the actual top-level transaction ID, preserving savepoint +semantics; domain state, successful business MUST, terminal state and terminal +MUST share the Finalize transaction. Each injected MUST failure rolls that work +back while prior Prepare/provider facts remain. The existing audit coordinator +may separately record the failed business attempt; this is never a success row. +The initial tuple-`xmin` assertion was invalid across EF savepoints and was +replaced by this observer, without changing production transaction handling. + +The held constructor retains its actual task and scope through release and join. +With the final run-locked Arm-window check removed, the expired case fails and +the real provider journal records an unexpected Execute and effect; its live +control passes. Exact source bytes and mode are restored, then all eight cases +pass again. These cases establish actual provider-method timing and real-store +atomicity, not native handoff, duplicate-provider acceptance or recovery. The +2,335-case Unit run and expanded 247-case PostgreSQL regression pass on the +corrected snapshot, with zero failures/skips and a CI Release build with zero +warnings/errors. The old External-unavailable admission assertion is replaced by +an exact profile/definition mismatch refusal; the genuine SDK flow supplies the +positive External coverage. The broader run retains the existing checkpoint, +control, business, capacity, admission and submission cases. + +The next native-control foundation binds the real External receipt's profile, +normal/finalize stage, counters and selected outcome to its existing execution +owner. Prepare acknowledgement no longer ends lease renewal. Its status-only +renewal probe checks the exact locked job and fresh immutable ledger, before +generic completion shortcuts. Two actual publication/control cases and seven +passive metadata substitutions per case cover both preparing and finalizing. + +The Prepare case starts the real renewal lane and independently observes SQL +lease advancement and a successful rearm of the actual System timer. Restoring +the two old Prepare-ACK guards leaves SQL renewal working but fails that timer +assertion. Exact source/mode restoration passes all ten SDK cases. The frozen +150-source snapshot passes 2,335 Unit and fifty focused PostgreSQL cases (forty +control, ten SDK), with zero failures/skips. An independent receipt audit verifies +all source hashes/modes, artifact hashes and actual TRX subjects. A retained +zero-match run after an initial compile failure supplies no test credit. This +foundation does not yet prove complete native provider handoff or recovery. + +The existing native execution owner now retains the optional Prepare, app read, +Arm, provider and Outcome tasks, with separate exact-family historical probes. +It skips Prepare when admission supplies the existing-plan stage. A normal return +closes that original run; unresolved effects retain reservations for fresh recovery. +An acknowledged Outcome stops renewal even during held cleanup, while actual +cleanup still gates identity release. Finalize remains a separate admission/root. + +Four genuine SDK cases now pass through the real facade, stock bridge and native +worker pools, independent provider journal and fresh Finalize admission. Success, +permanent failure and both nonrepeatable failure/cancellation preserve one normal +and one finalize receipt, one provider Execute, and actual business/terminal MUST +atomicity. The earlier two-case red run reached Prepare but stayed `prepared`, +discriminating the missing native continuation from the explicit-driver proofs. + +A held real adapter constructor exposes the former global short-wrapper timeout. +The existing invocation now owns one monotonic stage timer, armed before each +possible synchronous prefix, and retains every task after wrapper return. Its +finite mapping uses short-root, SQL, external-run and history-probe bounds. Lease +loss, deadline and host stop close/retain before signalling wrapper return; normal +capacity-cleanup cancellation remains separate. Actual timer disposal and private +cancellation callbacks precede source release. Deterministic controls distinguish +an old queued callback from the current stage and forbid refreshing elapsed work. + +The qualified 158-source snapshot passes 2,339 Unit and one hundred PostgreSQL +cases: forty control, twenty-three admission, twenty business and seventeen SDK. +The SDK selection includes all four native results, the long-constructor wait and +host-stop/lease-loss cases that return the wrapper while actual cleanup stays held. +The initial Unit run retained one obsolete host-stop `Running` expectation; its +correction independently counts running plus retained ownership. Removing only +the actual cancellation join fails the held-callback test while its three siblings +pass. Exact source/mode restoration passes all 2,339 again. Builds have zero +warnings/errors; no full Step 7 review or fresh native recovery is claimed. + +The receipt addendum includes the changed host-stop Unit fixture omitted from the +initial 157-path inventory. It preserves the original manifest and distinguishes +the two subsequent Unit-only corrections from unchanged production/PostgreSQL +sources; an independent audit verifies the complete 158-path inventory. + +Four further genuine native cases hold actual COMMIT responses at Prepare, Arm, +Outcome and Finalize. Their clean, exact-family historical confirmation permits +continuation without inventing physical acknowledgement or duplicating provider +work. The Outcome case also handles a real early wakeup while the original +invocation remains retained: a pre-routing identity check avoids acquiring a +routing lease that the same owner must immediately refuse. The initial red run +fails only that Outcome control; the corrected four-case run passes. + +A separate actual Outcome-ACK control holds Activity cleanup after the database +scope has closed. Its gate is acknowledged while the concrete task and invocation +remain retained. The live control lane neither rearms the settled lease timer nor +reports a renewal refusal; actual cleanup still precedes identity release. An +already issued renewal batch may finish. This does not claim zero SQL after ACK +or immediate next-stage service: a consumed early vendor hint can wait for repair. + +The final 160-source snapshot passes all 2,339 Unit and 261 PostgreSQL cases: +118 checkpoint, forty control, twenty business, twenty capacity, twenty-three +admission, eighteen submission and twenty-two genuine SDK cases. There are no +failures/skips; CI Release builds have zero warnings/errors. The snapshot keeps +red/green epochs and the test-only repair-grace reduction separate. Fresh native +recovery, full architecture qualification and both full Step 7 reviews remain +pending. + +Fresh recovery now carries a source-local Stopwatch observation taken before its +actual locked SQL projection. Binding and the final typed Reconcile entry check +the same remaining lease under the Run lock; expiry closes that Run permanently. +Neither binding, cleanup, a held constructor nor a later probe rebases its window. +The original attempt deadline may already have expired; it is not the new lease. + +A genuine SDK live/expired pair first executes against the independent provider, +omits Outcome and then acquires fresh recovery for that exact old attempt. A held +real adapter constructor exposes the missing final check: the red expired case +incorrectly calls Reconcile; the correction prevents that actual method call, +while the live control reconciles the retained effect. No extra Execute, normal +attempt or effect is created. This is an explicitly arranged recovery route, +not native bridge/control recovery qualification. + +Three additional real-socket controls hold the exact recovery probe's completed +ROLLBACK response. A peer can acquire the released row lock before the client ACK, +but no receipt publishes yet. Live ACK/cleanup permits the first binding; a clean +response delayed past the observed lease publishes history but refuses binding. +A lost response publishes nothing; a later clean first probe cannot rewrite its +failure or physical acquisition ACK. Repeated probes retain the same receipt. + +All 2,342 Unit and 145 focused PostgreSQL cases pass with zero failures/skips and +zero-warning/error Release builds. The PostgreSQL selection contains 121 checkpoint +and twenty-four SDK cases. An Integration-only test cleanup correction then joins +the actual probe task using its existing deadline even on failed premises; its +three affected controls pass again. Earlier source epochs are retained separately. +The subsequent recovery-renewal foundation preserves the original ledger token +and expired deadline separately from the fresh recovery token. Its actual SQL +extends only a still-live exact recovery lease; ordinary execution remains capped +by its original deadline. Private passive evidence publishes only after physical +COMMIT acknowledgement and actual cleanup. The Run accepts it under its own lock +only while both windows remain live, without changing the acquisition receipt or +resetting provider entry. Observing expiry closes the Run and current checkpoint. + +The actual expired-original case first fails against the old execution-only SQL. +Four genuine SDK controls then pass: a two-tenant mixed renewal batch, lost renewal +ACK without evidence publication, and timely/late evidence application around a +held real Reconcile constructor. Timely application permits one Reconcile after +the old window expires; late application cannot reopen it. These are delayed +applications of already acknowledged evidence, not held successful network ACKs. +Fourteen memory identity substitutions and separate binding/process/stop/order +controls exercise the acceptance boundary without claiming SQL provenance. + +The frozen 164-source foundation passes 2,361 Unit and 189 focused PostgreSQL +cases with zero failures/skips and zero-warning/error Release builds. The latter +contains 121 checkpoint, forty control and twenty-eight SDK cases, including the +four renewal controls. A lost ACK's later status probe proves the recovery row's +renewal without publishing usable evidence; the ordinary mixed row is independently +checked in the direct-ACK case. Native renewal consumption, actual cleanup-fault +injection, native recovery handoff and retry/quarantine/finalizer failure routing +remain pending, as do both full Step 7 review rounds. + +The native recovery owner now roots acquisition, exact historical confirmation, +app read, Reconcile and checkpoint tasks before issuance, without fabricating an +ordinary admission. Its fresh lease survives the expired original deadline; +actual renewal evidence feeds the existing Run boundary. Two genuine SDK controls +exercise direct/lost acquisition ACK and renewal across the first recovery window. +They arrange parking explicitly and do not qualify automatic scheduling. + +NoStart's lost app COMMIT ACK now uses its exact history family. Real timer +construction/Change controls hold the actual call while host stop closes permission; +returned handles require actual disposal, while unreturned failed initialization +retains ownership. Renewal keeps its old expiry visible during Change, and Join +awaits the actual update before disposal. A clean late return can decline renewal +without inventing failed cleanup. Held-stop controls do not prove autonomous expiry +at a shorter deadline during an arbitrarily blocked supplied Change. + +The frozen 167-source correction passes 2,362 Unit and 280 PostgreSQL cases: +121 checkpoint, forty control, twenty business, twenty capacity, twenty-three +admission, eighteen submission and thirty-eight SDK cases. There are zero +failures/skips; Release builds have zero warnings/errors. The new Change controls +first fail at the actual blocked stop/late identity boundaries, then pass after +correction. Earlier constructor/history and known-fault native epochs remain +separate. Automatic park/bridge/disposition and both full Step 7 reviews remain +pending. + +The next automatic-recovery slice adds two bounded control selections for expired +external owners and retained unarmed recovery rows. A single eligibility cycle +arms a finite probe and advances the wake generation once; stock handoff/repair +retains that generation, the original normal attempt and its reservation. A +forward migration and canonical DDL guard live-owner clearing, unarmed/reset +transitions and unsafe downgrade. Five actual SDK controls plus canonical-schema +parity pass, including an automatic facade recovery and both pending routing +stages. This does not qualify every future-due, exhausted, contention or planner +case. + +Its broader frozen 172-source run passes 493 of 494 PostgreSQL cases and exposes +one native lost-Outcome-ACK history failure: a competing row lock legitimately +returns a clean unavailable result. The correction retries only that exact clean +unavailable history read, after actual cleanup, inside the already armed single +history budget. It never treats unavailability as confirmation or resets the +original origin. A separate real transaction holds the exact job lock; the socket +observer ties the actual binary UUID/query to PostgreSQL's zero-row response. +That causal control first fails at the missing history value and then passes. +Seven focused history controls and all 2,362 Unit cases pass with zero skips and +zero-warning/error Release builds. The broader failed run remains a failed +receipt; these narrower passing controls do not imply a fresh full regression. + +The application-source inventory now includes external invocation owners alongside +transactional owners. Its job-only floor is 22 by default and 118 at the maximum +business-pool topology; unrelated arrival headroom stays separate. The shared +privileged inventory remains 50/156 because each invocation's routing, recovery +acquisition, confirmation and history operations are sequential and cleanup-owned. +The maxima need separate calculations: the qualified eight-pool/four-worker +facade fixture has privileged 156 and application 32, without claiming that +every topology reaching privileged 156 has the same application floor. + +The new count/kind and immutable 21/22 startup controls first fail against the +transactional-only calculation. After correction, 15 actual PostgreSQL cases +and all 2,365 Unit cases pass with zero skips and zero-warning/error builds. +Actual main/auxiliary connections fill 22/118 pools, with explicit zero/two +unrelated headroom controls; four native normal SDK cases and automatic recovery +use pooled application 22/privileged 50. These controls do not claim held external +versus transactional native contention or maximum-topology native execution. + +Retained completed facts now have a recovery-only app selection mode. Its actual +trusted read supplies plan/operation identity; no caller supplies a replacement +report, payload, policy or quiescence fact. The handler re-reads canonical stored +facts under the job lock and applies their policy. Missing facts and early +repeatable outcomes are refused by both driver and actual handler; selection +never rewrites outcome, quiescence, NoStart or reservation-release stamps. + +An existing marker alone no longer confirms a selection-only transaction. +Outcome history requires the exact policy-derived selected normal attempt, +status, reason and plan stamp; prepared-plan NoStart at six likewise requires its +exhaustion selection. Actual request-loss controls first expose both false +confirmations, then pass after correction. Actual response loss confirms the +selection while keeping physical ACK false, including after a distinct counted +Finalize admission advances the current header. + +The native recovery owner consumes those retained facts through the same held +app checkpoint task and commit budget. A genuine SDK control first remains +Reconciling against the old early-return branch, then reaches completion after +the correction without another provider scope, Reconcile or Execute. Its peer +with absent Outcome still performs one Reconcile. Thirteen focused PostgreSQL +cases and all 2,365 Unit cases pass with zero skips; the broader checkpoint/SDK/ +control regression is still pending at this receipt. This delivers selection, +not early-repeatable retry disposition, probe/quarantine or finalizer-fault policy. + +That subsequent run executes 217 PostgreSQL cases: 216 pass and one native +nonrepeatable case remains FinalizePending at its fixed twenty-second assertion. +Its saved receipt contains no ownership/handoff snapshot, so its exact cause is +not retrospectively established. The source permits a successor hint to finish +while the old acknowledged Outcome still owns actual cleanup; the default +sixty-second repair grace exceeds that test's former wait. + +Two causal controls, for success and nonrepeatable failure, now hold the actual +Outcome Activity cleanup. They observe the exact new-generation persisted vendor +hint as Succeeded, cleared bridge/ownership fields and a future database-time +handoff check while the old task is incomplete and routing is refused. Releasing +the real cleanup permits same-generation repair and one Finalize, with unchanged +normal count and independent provider counts. The NativeFlow fixture uses the +accepted fifteen-second repair minimum and a wait derived from repair grace plus +Finalize transaction/SQL budgets. Both causal cases and all four native flow +cases pass together. The complete forty-six-case SDK regression then passes +with zero skips and zero-warning/error builds. Only the two SDK test files +changed; production and all other frozen sources remain byte-preserved. Earlier +132 checkpoint and forty control passes, plus 2,365 Unit passes, stay tied to +their unchanged-production epoch; this is not a fresh 218-case run. The failed +217-case receipt stays distinct, and both full Step 7 reviews remain pending. + +Known-fact retry now accepts only a closed original-completed or fresh-recovery +identity. Under the actual job lock, its status-only read validates every normal +ordinal and positive NoStart/release or repeatable completed-outcome/quiescence +history. The current original admission token, deadline, scope and generation +remain distinct from a fresh recovery token. Missing or unresolved facts cannot +return work to Pending. + +For a live original owner, lease shortening, private nonexecuting recovery handoff +and fixed-backoff Pending selection share one transaction. Only the final returned +row permits COMMIT; refusal rolls back the intermediate ownership too. A fresh +recovery owner uses its live lease independently of the expired original deadline. +Scheduling advances one generation without adding an attempt, rewriting evidence +or starting provider work. The uncertainty descriptor retains the actual returned +schedule. Its locked probe distinguishes the exact old rollback shape, committed +same-cycle routing and a distinct later admission; no generic rollback fallback +or executable receipt is used. + +The native owner retains the actual disposition and optional confirmation tasks +through cleanup. It issues them only after a clean acknowledged or exactly +confirmed app checkpoint; retained known recovery facts need no new provider report. +A focused source review removed an unnecessary recovery-side control call after +final-selecting outcomes. Twenty-eight real PostgreSQL cases pass after that +correction, with zero skips and zero-warning/error Release builds. The twenty-one +store cases cover all five backoffs, real COMMIT request/response loss, subsequent +routing/admission, unresolved/nonrepeatable refusals, final-UPDATE rollback and +positive no-plan NoStart after actual original-deadline expiry. + +Seven actual SDK/native cases cover Failed/Cancelled original retry with normal +or lost Outcome ACK, plus recovery from retained facts, Reconcile and absent +ExecuteIntent. Held actual writer cleanup forbids early disposition issuance; +lost ACK requires its exact clean history confirmation. The subsequent counted +attempt preserves the plan/operation, reacquires capacity and performs its own +Execute before one fresh Finalize. Independent provider counts and domain rows +distinguish that progress from another Prepare, duplicate effect or invented +quiescence. The broader current regression then passes all 246 cases: 153 +checkpoint, fifty-three SDK and forty control cases. All 2,365 Unit cases also +pass on the same frozen source with zero skips and zero-warning/error builds. +The twenty-eight focused cases are included in that broader result. This is a +fresh passing run, not a reinterpretation of the earlier failed 217-case receipt; +neither full Step 7 review round is closed by these tests. + +The next bounded status slice validates unresolved ExecuteIntent under the same +exact normal identity and complete positive prior history. Running preserves the +unsuccessful-probe count; explicit failed probes increment once. The sixth failure +or a still-unresolved deadline/grace boundary quarantines without inventing an +outcome, releasing occupancy or admitting another normal attempt. Private lease +shortening and paced parking remain atomic behind the existing expiry-only wake +guard. Actual returned generation, counter, schedule and quarantine reason bind +the separate lost-COMMIT history probe. + +Thirty-five focused PostgreSQL cases pass with zero skips: twenty-two new store +cases and thirteen existing filter matches. They cover the six-probe boundary, +Running between failures, retained occupancy, known-fact and stale-owner refusal, +actual deadline/grace, request/response COMMIT loss, changed ownership and an +injected final-park rollback. A fault followed by a repeatable outcome preserves +the count through Pending; only the next real counted admission resets it. +The initial fixture attempted to move an unowned probe schedule and was correctly +refused by the existing guard. Its failed receipt remains separate; the corrected +tests wait for the actual due time and leave that production guard intact. +Independent source/artifact inspection closes this store slice only. Native +timeout/report/callback qualification and durable quarantine-health observation +are still in progress; neither is claimed by these store cases. + +The subsequent native regression executes 275 PostgreSQL cases: 273 pass and +two fail, with zero skips. Both failures record the only Reconcile timer callback +arriving before its owned monotonic deadline, by 1.288 ms and 1.200 ms. Discarding +that callback loses the future wake. A preliminary 1 ms tolerance therefore +does not qualify this path; its failed receipt is preserved separately. All +2,377 Unit cases passed at that same source, demonstrating the missing combined +timing coverage rather than disproving the native failures. + +The correction restores actual elapsed-time checks and gives an early wake one +supplementary timer and one task under the existing invocation. That observer +alone rearms and asynchronously disposes its timer; stage changes and closure +signal it without calling timer operations under the state lock. Actual observer, +timer and cancellation cleanup precede private-source release. Twenty-three +focused Unit cases pass, including repeated early wakes, successor changes, +held timer construction/change/disposal and refused/faulted timer operations. +An additional nanosecond-clock control rejects premature expiry caused by +TimeSpan conversion. The current source then passes all 2,385 Unit cases and +all 275 PostgreSQL cases: 175 checkpoint, sixty SDK and forty control cases, +with zero skips and zero-warning/error builds. The actual late-report tests +assert preserved state and original job/attempt/operation identity. The earlier +failed receipt remains separate. This adds no database connection, executable +authority or full Step 7 review credit; it does not qualify the later durable +health slice or remaining terminal/finalization policies. + +Durable quarantine health now uses a forward partial index and one status-only +read on the existing serial control lane. Acknowledged read rollback and actual +cleanup precede cache publication. Failed refresh retains the last good value +with an independent fault; unknown or stale samples cannot report healthy. +Snapshot cadence remains valid even when it exceeds the separate progress bound. +Health getters issue no SQL and do not become admission gates. + +All 2,391 Unit cases pass, including six new memory/freshness controls. Eleven +focused PostgreSQL cases also pass with zero skips and zero-warning/error builds: +six control observations, three schema/canonical/reversal cases and two genuine +native quarantine flows. The latter waits until quarantine is the only health +fault; a fresh host, source, gate and runtime start with no cached sample and +independently observe the retained quarantine. They preserve occupancy and the +single normal admission without another Execute. The normal planner uses the +partial index against six thousand future rows; dropping it makes the same +detector expose the backlog scan. These focused results close no full review round. + +The subsequent control/SDK/facade/storage regression executes 332 cases: 328 +pass and four fail, with zero skips. Two historical recovery-migration tests +incorrectly include a later index migration in their refused-downgrade inventory; +EF commits each successful migration separately. They are corrected to qualify +the recovery migration at its own boundary without weakening the full inventory +comparison. One retained-outcome recovery case remains FinalizePending at a +thirty-second assertion despite its sixty-second repair setting; its original +cause is not established by that receipt. A separate facade case passes actual +cleanup and zero retained-owner assertions, then times out awaiting a follow-on +job. Controlled recovery-cleanup coverage and follow-on scheduling diagnostics +are in progress; the four failures are not credited as passing qualification. + +The test-only correction run then passes nine PostgreSQL cases with zero skips +and a zero-warning/error build. It covers both historical migration modes, both +native recovery modes, both original held-Outcome cases, a new genuine stored +recovery selection with held real cleanup and same-generation repair, and both +auxiliary-cleanup modes. Production is unchanged from the preceding 332-case +epoch. The diagnostic-only facade rerun does not establish the original +follow-on timeout's cause; a source-reachable test-fixture collision between +the old job's legitimate retry and the new job is being tested separately. + +The controlled old-retry-before-new-job experiment fails with the original +call-count mapping. Exact job-id mapping alone still fails: the two fixture +UUIDv7 ids also share the timestamp-only twelve-character slug prefix. Actual +handler diagnostics show the new job's `business_rule_violation`, independently +of clean source/owner release. The corrected fixture maps resources by actual +`JobTenantContext.JobId` and uses the full UUID in each slug. Two distinct ids +are deliberately generated at the same timestamp; the old retry commits first +without consuming the independent job's resource, and the new job completes +in one admission. Both clean and dirty auxiliary-cleanup cases pass with zero +skips and a zero-warning/error build. These constructed controls explain and +remove both fixture collision classes, without retrospectively assigning the +earlier receipt a cause its saved observations did not capture. + +The no-plan terminal foundation now persists an exact finite request before +app NoStart, reservation release or terminal audit. Its fresh locked read checks +every normal admission and positive prior plan-free NoStart/release; committed +plans, effects and finalization are excluded. Its dedicated lost-COMMIT probe +binds the requested reason and immutable admission identity, preserving physical +ACK separately from history confirmation. Actual permanent Prepare refusal at +one/six, sixth recovery exhaustion, request/response loss, committed-plan and +expired-owner controls pass: seven PostgreSQL cases and all 2,391 Unit cases, +zero skips and zero-warning/error builds. This is the request/history primitive; +terminal-purpose app cleanup, stronger terminal storage guards, native routing +and final terminal audit integration remain pending and are not activated here. + +The terminal-purpose cleanup foundation adds a fresh, immutable +`TerminalNoStart` recovery receipt. It grants only app-role NoStart and exact +reservation release; it cannot enter Prepare, Execute, Reconcile, ordinary +renewal or finalization. The app reads the actual causal envelope without +constructing module parameters or requiring an Active definition, then checks +complete normal history under the row lock. NoStart and `never_started` release +commit atomically. A purpose/reason-bound history probe preserves the original +physical ACK separately. All 2,396 Unit cases and thirteen focused PostgreSQL +cases pass with zero skips and zero-warning/error builds, including first/sixth +admissions, absent current definitions, acquisition/checkpoint COMMIT request +and response loss, and a reservation CHECK refusal after the marker UPDATE. +The initial failed fixture assertions remain separate receipts; the corrected +Unit descriptor preserves the production probe's strict phase/reason check. +The broader checkpoint/recovery regression then passes all 196 PostgreSQL cases +with zero skips, including those thirteen focused cases. This foundation does +not activate the native terminal lane, terminal audit or stronger terminal +storage guards. + +The forward terminal-history migration freezes a non-NULL request reason and +requires complete positive no-plan history before the first dead-letter write. +It preserves the existing app NoStart/release guards, grants and four-role +boundary. Its initial eighteen-case run passes twelve and fails six: five +expose an ungranted payload-column read in the new guard, and one exposes a +dirty-control fixture that removed existing owner-clearing housekeeping. The +correction uses only permitted outcome metadata and restores the actual prior +function for dirty controls. The corrected build has zero warnings/errors and +all 217 PostgreSQL cases pass with zero skips, including canonical DDL parity, +exact prior-function Down/reapply, first/sixth actual NoStart, malformed prior +history, immutable reason and unadmitted retirement controls. A bounded reviewer +verifies both fixes and finds no further defect; this is no full review-round +credit and does not activate the terminal worker or its audit path. + +#### Native terminal and finalizer policy qualification (2026-10-17) + +The existing terminal lane now owns actual app NoStart cleanup independently of +ordinary terminal SQL. Its main/auxiliary application-source pair raises the +current application-pool floor to 24 and maximum supported floor to 120. Earlier +22/118 receipts above retain their historical meaning. A speculative empty +cleanup lookup does not increment pending outcomes. Stop joins the actual task, +scope and callback; an expired lease never substitutes for cleanup evidence. + +The prepared terminal path retains plan, operation and selected outcome metadata. +Its existing witness has a prepared 40-column returned projection alongside the +unchanged NoPlan 13-column and app 37-column projections. A private-constructed +24-column prepared acquisition carries the exact additional metadata. The +forward migration requires positive complete history before stamping incomplete +business finalization; its Down restores the exact prior transition function. +Audit failure rolls back both terminal completion and the incomplete flag. + +Actual native tests verify permanent Prepare refusal, sixth NoPlan recovery and +an already-recorded NoStart, including real cleanup-lease expiry and exactly one +MUST audit. Native Finalize tests roll back a nested business write, then admit a +fresh Finalize without rerunning the provider. PostgreSQL transaction identity +is captured while live: Npgsql can recycle its transaction object, so object +reference inequality was an invalid initial test premise. The corrected first +qualification passes sixteen PostgreSQL cases with zero skips. + +A later execution deadline could discard an already-classified, positively +cleaned Permanent Prepare or Finalize result. Both now retain that actual result +in the existing bounded control queue; status accounting can outlive execution +permission without reopening app/provider entry. Native timer-disposal barriers +verify this window, host-stop refusal and actual handler cancellation returning +RetainOwnership. Unknown status COMMIT permits only exact historical probes +until rollback is established. Changed ownership ends the old authority without +claiming its COMMIT succeeded. Retained terminal and finalizer history dispatch +precedes generic probe interpretation, including copied-boundary refusals. + +The expanded PostgreSQL qualification passes 214 of 216 cases; two planted-history +fixtures incorrectly ask the restored transition guard to accept damaged history +while expiring scheduling ownership. Correcting only that setup makes both pass. +The subsequent 42-case run passes 41; its remaining new foreign-owner fixture +incorrectly moves an already-expired lease forward. The corrected final focused +run passes fourteen cases with zero skips, including that refusal and a selected +external failure followed by six real Finalize admissions, all five backoffs and +one honest terminal MUST. Explicit fixture eligibility avoids waiting over an +hour; these are not six native delayed wakeups. The production source also has +2,396 passing Unit cases. All qualifying Release CI builds have zero warnings +or errors; initial migration/import build mistakes remain separate receipts. + +The first complete architecture run passes 304 of 330 cases and fails 26. Exact +caller/signature/owner guards require alignment with the new external paths; +their nonempty subjects and planted violations remain required. This is a +recorded failing self-check, not completed architecture qualification or either +full review round. + +Uninvokable cleanup and request routing are implemented without requiring an +Active definition or reconstructing module parameters. The candidate selector +proves positive cleanup history before its bounded page; unresolved earlier +rows cannot consume that page. Historical request probes retain their original +identity, compare selected timestamps independently of session time zone and +reject mixed specialized histories. A forward migration extends only the +positive NoPlan terminal reasons; prepared finalization guards stay unchanged. + +The first foundation builds with zero warnings/errors and passes twenty-eight +existing PostgreSQL terminal-history cases. The subsequent 257-source checkpoint +passes all twenty-one dedicated uninvokable/invalid-envelope cases and the real +native application-source contention case. Its 272-case PostgreSQL run passes +271 cases and fails one index-name assertion: the normal planner legitimately +chooses the newly added matching retirement index for a pending query. All four +actual control-query plan cases, canonical DDL parity and full schema +rollback/reapplication pass. The assertion correction permits only that known +pending/retirement pair, retaining the cutoff, scan-bound and removed-index +controls. Its focused correction run passes all thirty-two PostgreSQL cases, +including the twenty-one uninvokable cases, all four actual control-query plans, +the five ordinary eligibility/index-removal cases and canonical/full-rollback +parity. + +At that same source checkpoint, Unit passes 2,396 cases, Contract four and +Docker-free HTTP integration 176, all without skips. Architecture qualification +runs all 333 cases in two complementary groups: 326 pass and seven fail. The +failures expose stale exact-owner expectations, missing recovery-minter census +coverage, a Cecil mutation-restoration error, a composed table projection and +the published method count. All 1,074 external orchestration dirty/restoration +controls pass. The first correction run passes five architecture cases, including +the exact owner/minter baselines, terminal mutation controls, literal-SQL guard +and corrected count. Expanded minter mutation qualification then passes; the +owner mutation test exposes a further missing multiplicity check between the +two identical external budget projections. Requiring both exact occurrences +closes that false-pass control without removing either mutation. + +The next correction build has zero warnings/errors and Unit again passes all +2,396 cases. Both orchestration facts pass in 4m53s, including all 1,074 external +dirty/restoration controls. The authority and owner group passes three cases in +6m16s, including the corrected budget mutations. Detector-local target-name and +identity indexes preserve fresh baseline/dirty/restored scans; detached targets +remain explicit offenders. These durations are receipts, not a controlled speedup +measurement or evidence that the complete CI backend job fits twenty minutes. +Step 9 retains that complete-job qualification. The first two helper analyzer +warnings and all seven original architecture failures are closed by focused +corrections; the original failed full run remains a separate receipt. + +Commit preparation identifies whitespace/encoding-only corrections in fifty +changed files. They are applied after all running tests stop; final format/build +and representative post-format checks then pass. The complete solution verifies +format without changing any of its 1,268 files, and Release builds with zero +warnings/errors. Post-format Unit passes 2,396 cases, Contract four, architecture +seven and PostgreSQL thirty-three, including the native application-source +contention case. The normal nonempty/zero-skip TRX guard verifies all four test +assemblies. The 258-source SHA-256/mode manifest closes at +`b9187ae8e90976f7b974171cb1563c5b3a4df57e070809f845f3d040678600be`. +No complete current-head suite, PR/CI success or full review-round credit is +claimed. The changed-document audit passes 1,377 relative links and 423 fragments; +all seven ADR parser controls pass. + +The remaining Step 7 checkpoints are explicit: + +| Checkpoint | Current state | +|------------|---------------| +| External stages, durable policy, reconciliation and native terminal/finalizer paths | Implemented; earlier focused receipts above record their source-specific qualification | +| Uninvokable retirement/invalid-envelope cleanup and candidate progress | Implemented; twenty-one dedicated cases, actual retirement-index seek and corrected alternate-index assertions pass | +| Native application-source contention | Genuine contention regression passes with the provider task retained and an unrelated transactional job completing at the application-source floor | +| Complete exact census and relevant backend regression | Focused implementation qualification and correction checks pass; full packet regression/CI remain Step 9 | +| Step commit and two fresh full review rounds | Implementation committed as `6e90a52f`; both full review rounds and verified corrections complete; the round-2 correction and closeout share this commit | + +Both full Step 7 reviews and their verified corrections are complete. +All nineteen packet obligations remain Registered; no +production business definition is added. Steps 8–9 and real PR/CI closeout remain pending. + +#### Step 7 full review round 1 (2026-10-17) + +Implementation commit `6e90a52f` passes normal hooks and leaves a clean tree. +Three fresh independent reviewers inspect the complete Step 7 range from +`0ea50b15`: GPT-6-astra at xhigh for runtime/authority, and two GPT-6.1-sol +reviewers at xhigh for storage/isolation/audit and proofs/composition/corpus. +These are full source reviews, distinct from the earlier slice preflights; +reviewers run no toolchain and supply no additional runtime or CI receipts. + +The unique findings are external capacity deferral, the terminal NoStart +candidate cutoff, and required provider-causality qualification. The runtime +review independently corroborates the capacity and causality findings, with +no additional verified runtime defect. No new tenant/org isolation, privilege, +policy, release or terminal-audit atomicity defect is established. + +External normal admission correctly refuses a full capacity group without +inserting an attempt or reservation. Its shared control disposition still +accepts only the transactional profile, silently leaving the external routing +lease. A real app-admission/native-control regression fails the unchanged +implementation at that retained routing owner. The correction admits the two +ordinary profiles through the same exact pending/routing/token/generation/live +lease fences; finalizer admission remains separate. The corrected real-path +case passes, including the recorded five-second wait, genuine provider/Outcome +release, new admission before the old lease expires, and stale-token refusal. +The twenty-one related PostgreSQL cases and all 2,396 Unit cases also pass with +zero skips and a zero-warning/error Release build. The original red receipt +remains separate; these focused checks are not a complete packet rerun. +A separate source inspection finds no actionable issue in this correction; +it supplies no second-full-review or complete native handoff credit. + +The terminal NoStart candidate query used a volatile cutoff where selection +requires a stable statement timestamp. A real migrated-schema regression seeds +6,000 future terminal audit-backoff subjects with guarded NoStart/release history +and 6,000 unrelated occupied subjects. The original query fails its stable-range +assertion and records 36,000 loop-weighted plan-row visits, not distinct rows. +Stable cutoffs alone still fail the one-due-page work bound: a flattened +reservation EXISTS scans unrelated reservations. A local zero-offset fence keeps +that probe correlated to each due candidate. Full positive history remains before +LIMIT, and fresh post-lock authority checks remain unchanged. + +The exact corrected query passes both idle/one-due cardinalities, the stable +index condition and fewer than 256 loop-weighted visits. Changing only its +available-after cutoff back to the volatile clock exposes the large idle scan. +All thirty-eight selected PostgreSQL cases, including existing control-query +plans and terminal/history controls, pass with zero skips; three architecture +checks pass and Release builds have zero warnings/errors. The first stable run's +integer-only EXPLAIN JSON parser failure is retained separately and corrected to +accept PostgreSQL's numeric row counts. The actual stable-only failures and their +plan remain separate receipts; no measured timeout, forced planner option or +new index/grant is claimed. Independent correction inspection finds no actionable +issue and supplies no second-full-review credit. +The existing provider tests preselected cancellation policy; they did not prove +an actual runtime cancellation becoming a durable Cancelled report and surviving +fresh-host Reconcile. Three new native cases now pass. An actually accepted +Running operation honors the private runtime token and commits Cancelled with +positive provider fencing in its independent database. Its stopped original +owner joins without writing Outcome or releasing occupancy. A fresh host/source/ +Run with no original probe reconciles the same job/operation/attempt/deadline, +checkpoints its exact policy/evidence, releases capacity and commits domain +finalization with both MUST audits. + +The companion permanently fails and durably closes its provider fence before +stop, while holding only the response across stop; fresh recovery preserves that +independent meaning. A third, explicitly dirty adapter changes only a genuine +Cancelled Reconcile report to Failed/Permanent. It leaves the provider journal +unchanged, actually reaches the wrong persisted result, and is rejected by the +same semantic assertion used by the clean companions. This proves adapter +qualification, not generic runtime certification of external causality. + +Independent source inspection finds no actionable issue in the correction design. +The three actual native cases, all 2,396 Unit cases and four Contract cases pass +with zero skips and a zero-warning/error Release build. The initial three analyzer +warnings are corrected by explicitly awaiting provider-owned cleanup independently +of its already-cancelled input. The remaining seventy-one provider/SDK cases +also pass in 8m46s. Together the two disjoint filters execute all seventy-four +cases in that class, including genuine native, lost-reply/ACK, recovery, retry, +finalizer, cancellation/cleanup and source-contention controls. Four architecture +checks pass. The normal runner guard verifies nonempty execution and zero skips +in all four assemblies; its initial suffix-only invocation is retained as an +invocation failure, separately from the passing full-assembly-name invocation. + +Format verification changes zero files. The seven-document audit passes all +1,377 relative links and 423 fragments. The final 261-source SHA-256/mode manifest +closes at `b1404b39d54434ba1fa3233bbe9fb742cc856d828139406d61a6ed11f9df005c`; +the corrected runner invocation has its own receipt without rewriting that manifest. +Capacity and candidate-scan fixes are committed as `ef3cf7b4` and `1ef18e64`. +This correction closes the three verified first-round findings; the second fresh +full review remains pending. No complete current-head backend/CI run or packet +obligation promotion is claimed; Steps 8–9 and the full closure gate remain open. + +#### Step 7 full review round 2 (2026-10-17) + +Three fresh independent reviewers inspect the complete Step 7 range +`0ea50b15..d0eb7596`: GPT-6-astra xhigh covers runtime/authority and a second +GPT-6-astra xhigh covers storage/security/audit; GPT-6.1-sol xhigh covers +proofs/composition/corpus. Runtime and storage report no actionable findings. +The proof review identifies one required coverage gap and one minor live-standard +correction. These are full reviews, distinct from earlier narrow inspections. + +The genuine provider recovery tests did not exercise Failed/TransientNotRepeatable +or Cancelled/TransientRepeatable through Reconcile. The existing recovery theory +now retains its three cases and adds those two; no Fact/Theory method or catalogue +count is added. Original Execute returns a completed report without an exception, +but its application Outcome is deliberately absent. Fresh native recovery reads +the same independent provider attempt before any later execution. + +An actual acknowledged recovered Outcome holds its cleanup before disposition. +App-role assertions bind state, policy, operation, fingerprint, evidence and atomic +quiescent release to the original provider journal. Repeatable cancellation has +no premature failure selection and later spends a distinct normal admission on +the same operation. Nonrepeatable failure commits its ordinary failure finalizer +and exact `external_retry_forbidden` MUST audit without another Execute. Both +new cases and all seven existing retry/recovery/ACK cases pass: nine cases, zero +failures/skips, with a zero-warning/error Release build. + +A temporary Reconcile-only adapter mutation maps the two policies to different +valid policies while leaving provider storage unchanged. Exactly the two new +cases fail at the same stored-policy comparison; the three existing recovery +controls pass. This is an executed adapter-protocol negative control, not runtime +certification of provider truth. The exact fixture bytes and mode are restored +and independently verified against the clean 261-source snapshot. The restored +Release build has zero warnings/errors; its five-case native rerun passes with +zero failures/skips in 1m33s. The restored-source manifest closes at +`33ba204ead511e91fa7f0ad7c63394e07e5fa894874b5d0df14e5290f2ea46db`. + +The live Infrastructure standard now describes the actual stage-specific wait +switch and correct completed Step 6 review status. Independent narrow inspection +finds no remaining issue in the correction or the actual clean/dirty receipts. +The initial clean source manifest closes at +`3654d96f7cb27241deeb049fbe05e8476211bff20ba54828778617ff220ec6e6`; +the separate expected-failure mutant receipt closes at +`2d6ace0de47a4babd374a605e2e6fd5cc11cd7865f5f19039d63320b8159312b`. + +A fresh complete Architecture run on the frozen `d0eb7596` source passes all +333 cases with zero failures/skips in 30m41s; its 261-source manifest closes at +`bc2936a69e07c77c23afb684d7f225f9b192199f0f9e7bbd6f825bdd4200c9ad`. +This includes the earlier seven corrected controls and preserves their original +failing receipts. It precedes the test-only policy extension; it is not a complete +current-head backend/CI receipt. Step 9 still owns CI-duration qualification and +full packet regression. All nineteen obligations remain Registered. The round-2 +correction commit closes Step 7 after both full reviews and verified corrections; +Step 8 follows under the already Accepted plan. No new maintainer decision is pending. + +### P02b-4 Step 8 — durable recurrence and restricted fan-out (2026-10-18) + +**Locally complete after both full review rounds and verified corrections.** +The [round-2 closeout](#step-8-full-review-round-2-2026-10-18) owns final evidence. +Step 7 closes at `69405b16` after both full +independent review rounds and verified corrections. Accepted ADR-0047 authorizes +this step on `development`; no new decision is pending. + +The implementation is organized into three closure units within the unchanged +approved Step 8. They do not replace the implementation commit and two fresh full +review rounds required before Step 9: + +- Frozen monotonic manifests, UTC slots, coalescing and bounded lifecycle pages. +- Actual-row recipient admission, scope recheck and atomic child/recipient receipt. +- Owned runtime/tick integration, fairness, capacity and complete fault proofs. + +The first foundation adds idempotent manifest registration and one locked +materialization quantum. Two actual sources converge; obsolete or conflicting +revisions cannot overwrite the accepted manifest. Historical slots retain their +stored target/policy; a newer manifest cannot be materialized by an older binary. +CoalesceLatest atomically advances to the slot after the latest due occurrence. +Future slots enter the index only when due. Pending/unknown targets defer without +advancing and yield to healthy work. A denied occurrence INSERT rolls back both +occurrence and manifest progress; restoring the narrow grant permits a clean retry. + +The focused foundation Release build has zero warnings/errors. Thirteen existing +recurrence Unit cases pass; the extended PostgreSQL class passes eight cases and +the production authority census passes one, all with zero failures/skips. Its +266-source hash/mode receipt closes at +`09aa9ca0275c531b65d11851a3674788762a8571c499a772e5140fcb62b765d1`. +An initial missing test-helper compilation failure remains a separate receipt; +no tests are credited to that failed build. These focused checks do not qualify +the remaining fan-out/runtime surface or either full Step 8 review round. No +production recurrence or business definition is added; nineteen obligations +remain Registered. + +#### Lifecycle pages and foundation preflight + +Tenancy declares the status meanings as closed metadata. Its additive migration +grants exactly eight SELECT columns; real dispatcher connections reject names, +wider reads and tenancy writes. Raw tenant/organization pages bound examined keys +before eligibility filtering. Frozen upper keys and recipient INSERTs advance in +one transaction; denied INSERT controls leave neither bounds nor progress behind. +The actual tenant query seeks past a 6,000-row ineligible prefix in a 12,000-row +fixture without rescanning it. This is a raw-key eligibility sweep, not an MVCC +snapshot cohort. No organization query-plan result is inferred from that test. + +Two planted same-revision manifest conflicts initially fail at the semantic +materialization assertions. Both materializers now require the exact local hash +when the revisions match, while preserving supported historical targets under a +newer local manifest. Both cases pass in the restored clean run. + +Two independent foundation preflights inspect runtime/isolation and proof/corpus +surfaces. Runtime has no verified finding. Proof review identifies that executing +the canonical grant block after applying the migration cannot detect an omitted +grant. The corrected test starts from a verified empty lifecycle ACL, proves the +same exact-budget assertion rejects a missing required column, then runs the +unaltered canonical block from an empty ACL and verifies its complete budget. +These are bounded preflights, not either full Step 8 review round. + +The 275-source pre-correction receipt passes 35 PostgreSQL cases and both the +positive and planted-violation authority cases, with zero failures/skips. It closes +at `43873ad1a6b7c95bb578b4da04d2db8b7a6818e12be89236a50c949a977863e4`. +After the proof correction and formatting, the Release build has zero warnings/ +errors; 35 PostgreSQL cases, all 2,396 Unit cases and the positive authority case +pass with zero failures/skips. That 275-source receipt closes at +`04894512bcfe8c444a82a5f16b956dd2c8e217d16146f4b88f860f842aa65b6c`. +Earlier compilation failures and the two meaningful conflict failures remain +separate receipts. These checks do not claim full packet regression or CI success. +Restricted child admission and owned runtime/tick integration remain within this +same Step 8, before its implementation/review closeout. + +#### Recipient acquisition continuation + +Foundation commit `69c3998a` preserves the preceding qualification and bounded +preflight correction. Normal hooks leave all 275 validated source hashes/modes +unchanged. Restricted recipient acquisition is the next unit, not a new step. + +The actual locked recipient now yields an opaque single-use claim containing its +stored occurrence, route, manifest, target and fresh acquisition. The compatible +registered manifest supplies its declaration Type; no stored CLR name is resolved. +Publication requires positive claim COMMIT acknowledgement, actual cleanup and a +conservative remaining lease interval. Pending, unknown and same-revision +conflicting binaries defer without publishing authority. Two independent sources +cannot issue one live route twice; a competing application row lock is skipped. +Acquisition itself creates no child or business execution. + +The 278-source qualification passes a zero-warning/error Release build, 41 +PostgreSQL cases, all 2,396 Unit cases and the positive authority case, with zero +failures/skips. Its source/mode/artifact receipt closes at +`cd7961e2b5873fa94b326caedacf265decffaf81cb7552591718fbe927c3eb52`. +An earlier test assertion compilation error remains its own failed-build receipt; +no tests are credited to it. App-role child submission, its completion gate and +acknowledgement-loss behavior remain pending in this same Step 8. Full Step 8 +reviews and runtime/capacity enforcement remain pending. + +The narrow acquisition preflight finds two additional source issues: claim +ordering includes a column absent from the pending index, and declaration-kind +validation rejects metadata accepted at registration. The corrected query orders +by `(available_after, id)`, matching the canonical index. A real 3,000-recipient +zero-jitter backlog proves the actual query uses that index without sorting and +examines a bounded quantum. Restoring the obsolete order in the same query makes +the same detector fail and consumes the backlog before LIMIT. Interface, struct +and open-generic manifest declarations pass the actual registration-to-claim +flow without constructing any feature service; owning-assembly validation remains. + +After these corrections, the Release build has zero warnings/errors; 45 +PostgreSQL cases, all 2,396 Unit cases and the positive authority case pass with +zero failures/skips. The 278-source receipt closes at +`d12a0f5fdaebacf0cfb7e8d93e0df8b65cf32a7e9e107514b39e37add1e8090f`. +Independent correction verification checks the source and hashed artifacts and +closes both findings without a new verified issue. This remains bounded +preflight/correction evidence, not either full Step 8 review round. + +#### App-role recipient submission continuation + +Acquisition commit `2059a7ee` preserves the preceding evidence. The closed +recipient executor now installs the actual tenant/organization route without an +invented child or parent identity and sends one exact framework request through +the existing coordinator. Its participant binds the original source owner, +physical transaction and positive tenant announcement. The app-role owner locks +the recipient, evaluates a fresh database clock and rechecks current lifecycle +eligibility before creating one fixed occurrence-input child. + +The common scheduler INSERT preserves ordinary producer checks and records +produced work only after successful SQL; failure marks the existing owner +rollback-only and rethrows. After owner drain and MUST audit, the participant +checks the full immutable route, original token and live lease and writes the +reciprocal receipt. A conservative monotonic budget covers SQL and cleanup until +the final commit gate. Only the existing coordinator records commit ACK. The +executor retains its source, scope and cancellation ownership through actual +cleanup; it constructs neither the target request nor its handler. + +Real PostgreSQL cases cover tenant and organization success, lifecycle refusal, +single-use replay, a closed gate and independent child-INSERT/receipt-UPDATE +failures. Both writes commit together or neither remains. Construction controls +exercise the actual registered target and handler separately and prove the same +no-construction assertion rejects each. Exact production censuses enroll the new +framework/context/source/owner path and retain the original admission restrictions. + +The 287-source qualification passes a zero-warning/error Release build, 75 +PostgreSQL cases, all 2,403 Unit cases and twelve focused Architecture cases, with +zero failures/skips. Its source/mode/artifact receipt closes at +`464b9554dac3d4b0060b8ca7021a16127741abd8b8d8518948dadf2da3fe18f2`. +Narrow proof review identifies five planted field/constructor mutations that the +first detector incorrectly accepts. All five fail against that original detector; +the corrected detector checks full writer identity, opcode and exact private +constructor/flag shape, and the same controls pass in the qualification above. +Earlier build, SQL and detector failures remain separate receipts. + +Final guard additions pin the recipient executor's exact internal signature and +currently empty production caller set. The shared INSERT proof binds its actual +SQL invocation and await acknowledgement to the same rollback-only/rethrow catch; +produced work must be invoked after acknowledgement and outside failure handlers. +Ten targeted controls move, remove, delegate or detach these actual instructions. +The earlier detector's incorrect compiled-signature assumptions remain a failed +qualification, not a runtime finding. Independent correction inspection verifies +both catch binding and invocation sensitivity without claiming test execution. + +Only that Architecture test file changes after the preceding 287-source receipt. +Its final Release build has zero warnings/errors; all seventeen recipient +Architecture cases and two real auxiliary-cleanup regressions pass with zero +failures/skips. Full formatter verification reports no changes. This source/mode/ +artifact receipt closes at +`65ba343bf9da98134a09e0e6297364d38daf752d57ef0aab2a03d3c2e6b3bd7a`. +These are local, source-specific receipts, not current-head full backend or CI +qualification. + +At this continuation's commit, historical acknowledgement-loss confirmation and +confined skip/defer remain pending; the following record owns their delivery. +Additional fault controls and native runtime/fairness/capacity integration remain +pending. This is not complete Step 8 delivery or a full review round. +No production recurrence or business definition is added. All nineteen +obligations remain Registered; both fresh full Step 8 reviews precede Step 9. + +#### Recipient history and confined disposition + +App-role submission commit `a99e6a8a` leaves all validated source hashes/modes +unchanged after normal hooks. A new confined operation now requires the original +executor's positive cleanup before opening another physical source. Its original +result has immutable authority fields and a constructor restricted to that +executor. A locked-row observation checks the full stored route and reciprocal +child before the old token: the accepted child wins even after token clearing or +a later acquisition, without creating another identity or inventing the original +COMMIT acknowledgement. A skipped lock is unavailable, never proof of absence. + +Without a final receipt, only the original DB-live token permits disposition. +Current lifecycle is rechecked; a deleted/ineligible route is skipped, while a +restored or otherwise eligible route receives bounded deferral. The final UPDATE +repeats the complete route/token/time fence. No app grant or business attempt is +added; this status operation publishes only after its own ACK and cleanup. + +Nine new PostgreSQL cases use real server-COMMIT response loss and unforwarded +COMMIT requests, counted identity creation, actual row locks, actual replacement +acquisition, lifecycle restoration and a throwing scoped cleanup dependency. +They distinguish a stored child observation from the original ACK. The initial +qualification retains one fixture failure at the forbidden live-token rewrite +and the detector's compiled-string mismatch; neither is a runtime finding. +The fixture now expires the lease and reacquires through the actual store. + +The final 289-source Release build has zero warnings/errors; 44 PostgreSQL cases +and 22 focused Architecture cases pass with zero failures/skips. All 2,403 Unit +cases pass before the two test-only corrections. Formatter verification reports +no changes. The final source/mode/artifact receipt closes at +`cbcc6cff06e17f089c4923e0819703e118454e8d68eed103288e896731e979d8`. +Narrow independent source inspection finds no unresolved runtime/test-evidence +issue and claims neither test execution nor full Step 8 review credit. +Remaining admission/fault controls and native integration still precede both +full Step 8 review rounds and Step 9. Nineteen obligations remain Registered. + +#### Recipient admission fault qualification + +History commit `f08f8bf1` preserves the preceding source qualification. Eleven +additional PostgreSQL cases exercise corrupted actual claim facts, context +replacement during identity creation, lease expiry after an observed row-lock +wait, and stop after the actual receipt UPDATE but before commit admission. +The tests check actual identity creation, SQL effects and rollback together; +no production seam or business definition is added. + +Narrow independent inspection identifies that the first context-callback test +cannot distinguish refusal before INSERT from rollback afterward. The corrected +paired test observes an actual server-side INSERT notice. Removing only the +post-identity context guard makes the corrupt case fail that exact assertion +while its healthy counterpart passes. The original production bytes and mode +are restored and verified against HEAD before rebuilding. This deliberately +failing mutation remains a separate receipt, not a production failure. +Independent correction inspection verifies the same assertion's failure, exact +source restoration and passing paired cases; no further issue is identified. + +The restored 290-source Release build has zero warnings/errors; all 55 cases in +the recurrence PostgreSQL class pass with zero failures/skips. Formatter +verification reports no changes. The source/mode/artifact receipt closes at +`022523338fa6f8ee3c3384f2b5ce878bb31b099035e16d07df338e65f995b8d0`. +Only Integration test sources change after the preceding committed production +qualification; Unit and Architecture suites are not repeated or claimed here. +Native runtime, fairness and capacity integration remain pending before both +full Step 8 review rounds. This focused qualification does not close Step 8. + +#### Native recurring-write serialization + +Recipient fault qualification is committed as `35c3e0d5`; normal hooks preserve +its validated source hashes/modes. Actual stock recurring `Job` writes now lock +the exact unsuperseded revision inside the vendor transaction. The explicit +volatile trigger takes a fresh snapshot after earlier waits, and bootstrap checks +the installed volatility with its existing body/language/search-path/ACL contract. +A generated additive migration upgrades already-migrated stores and restores the +preceding exact body on Down. Canonical SQL remains in Standards 05. + +Ten focused PostgreSQL cases use the real stock manager without starting workers. +They cover old-over-new refusal, an unchanged Job omission, retained older hints, +volatility-only drift, independent migration Up and canonical replacement, and +three actual lock interleavings. The same assertions reject the KEY SHARE, +missing-active-predicate and stale nonlocking-snapshot controls. No elapsed sleep +establishes those barriers; the tests observe actual blocking backend identities. + +Narrow source review identifies that applying canonical SQL before Up would mask +an omitted upgrade body. The corrected test first upgrades the actual old body +through the migration alone, then independently tests canonical replacement. +No further concrete issue is identified. Earlier SQL-cast and test transaction +cleanup failures remain separate receipts; a subsequent build-only receipt +grants no test pass. + +The final 297-source Release build has zero warnings/errors. The ten focused +cases and the broader 143-case PostgreSQL selection pass; the broader selection +includes those ten cases. All 2,404 Unit cases pass, with zero failures/skips. +Formatter verification reports no changes. The source/mode/artifact receipt, +including current SQL and canonical carriers, closes at +`aa38ded6b0042cba7a3521bbf02ada212b6cf09ae74c4fdde3ca5deac89aaa97`. +This is local qualification of the guard/storage unit, not full Step 8 review or +packet-wide CI. Owned runtime/tick integration, fairness, physical capacity and +their real fault proofs remain within Step 8. All nineteen obligations remain +Registered; both fresh full reviews still precede Step 9. + +#### Runtime connection and stored quarantine qualification + +Guard/storage commit `c4a93deb` precedes this runtime unit. The existing facade +now owns a recurrence child, one independent native manager flight and at most +four actual recipient application owners. Durable registration, slot, page, +claim and original-receipt history quanta rotate on one SQL lane. Native ticks +only coalesce a memory signal; they construct neither recipients nor feature +work. Exact recipient IDs remain excluded while their original task, cleanup or +receipt history is retained. Failed cleanup supplies no replacement authority. + +The shared observation reads stored recurrence, occurrence and recipient +quarantine independently of the local registry, including unknown older keys. +Each table has a reversible partial presence index. Both observation values +require actual reader/command cleanup and acknowledged ROLLBACK. Failed refreshes +preserve the preceding value and make the observation unhealthy. API composition +supplies Tenancy's existing closed lifecycle declaration as metadata. + +The named capacity inventory adds two privileged connections and four application +main/auxiliary pairs; stock worker and retained-invocation bounds do not increase. +Standards 05 owns the reconciled formulas. Real default/maximum app inventories, +explicit unrelated headroom and actual default/maximum native facade composition +exercise their own boundaries; this does not claim simultaneous saturation of +every runtime lane. Existing owner/caller manifests admit only the new concrete +recipient and recurrence callers, without widening source-acquisition authority. + +The initial runtime build retains three analyzer failures as a separate receipt. +An intervening Unit run passes 2,401 cases and fails three old capacity premises; +after their correction, all 2,404 Unit cases pass. The first two native fan-out cases +reach completed children before their test-created ticks fail the transport's +ambient-culture guard. The corrected test uses the real native owner's invariant +culture boundary; that guard remains unchanged. A subsequent 311-source build has +zero warnings/errors, 2,408 passing Unit cases and 78 passing PostgreSQL cases. +Three new quarantine refresh cases fail because revoking a column grant cannot +remove the existing table-level SELECT grant. Their corrected premise first +proves actual `42501` after revoking the real grant, before awaiting health change. + +The final 322-source Release build has zero warnings/errors; all 2,408 Unit cases, +twelve focused PostgreSQL cases and four focused Architecture cases pass with +zero failures/skips. The PostgreSQL selection covers each corrected cold-runtime +quarantine path, expired-lease exclusion, invalid exclusion sets, populated +recipient query plans, three-index Down/Up, actual facade topologies and actual +native transactional progress at the new app floor. Earlier passing cases include +both tenant/organization fan-out paths, three duplicate stock ticks per path, +reciprocal receipts and each control index's decisive 3,000-row removal control. +The final selection does not rerun or relabel that earlier broad selection. +Formatter verification reports no changes. Its source/mode/artifact receipt closes +at `8722a6b2799ba23d3cc1d8271c56dc9357b649a5b684160df8a4f8beabcc08f8`. + +Two narrow source preflights identify the missing isolated quarantine/index proof +and the exact existing caller enrollments, addressed above. They execute no tests +and grant neither full Step 8 review round. Complete new-owner/tick capability +guards and retained-work, fairness and shutdown fault qualification remain before +both fresh full Step 8 reviews. Nineteen obligations remain Registered; Step 9 is +pending and no packet-wide regression or CI success is claimed here. + +#### Actual native hold and parent-source pins + +Runtime commit `c500bcba` precedes this test-only qualification. An actual Npgsql +diagnostic callback holds the stock recurring manager on its owned native thread. +Two registered keys still produce two completed durable children. This is a +bounded synthetic callback hold, not a network-fault reproduction or a minimum +connection-pool proof. The fixture has explicit unrelated connection headroom. + +The original one-key assertion could pass with the hard native-flight guard +removed because the same-key cooldown independently prevented replacement. A +narrow source review identified that masking premise. Two keys now establish a +second eligible native opportunity; the test reads the actual published owner +under its lock and verifies that its original thread remains the sole owner. +The first strengthened run fails only because a string assertion selects the +wrong overload; its corrected explicit collection assertion preserves the premise. + +Before testing source retention, all ordinary pools, shared maintenance, bridge, +parent control lanes and recurrence loop/cancellation relay positively join. +The held native invocation still prevents parent completion and both actual +source lifetimes from disposing. Releasing the callback permits actual SDK/thread +return, parent completion and positive disposal without cleanup faults. An +independent nested-finally join retains the original thread even when an +assertion or parent shutdown fails. + +Two separate temporary source controls are decisive: removing only the hard +native-flight guard admits the second key and fails the original-owner assertion; +removing only the parent's recurrence completion await makes stop finish early +and fails the finite-stop assertion. Each control builds without warnings/errors, +fails the same test and is restored byte-for-byte with its original file mode. +No deliberate violation is committed. + +The final restored 323-source Release build has zero warnings/errors. All 76 +recurrence PostgreSQL cases pass with zero failures/skips in 43 seconds, including +the actual native hold, tenant/organization fan-out, native races, recipient +receipts/history and stored quarantine paths. The runner's nonempty/zero-skip +guard passes and scoped formatting reports no changes. The source receipt closes +at `c9331866654efc91c83769cb718398416c97084897f38547a0a18f9cd2253416`. +The narrow review supplies no full Step 8 review credit. Remaining recipient +retention/fairness and exact capability guards still precede both full rounds. + +#### Actual recipient ownership, expiry and source cleanup + +Following `dd600e88`, the actual runtime exercises six due recurrence keys with +four real recipient application tasks held before their handler acquires a row +lock. Each retains its original unit, source owner and published operation. +PostgreSQL's clock establishes natural expiry of all four 15-second leases; +the fixture neither rewrites those leases nor substitutes local timestamps. +Durable registration and fan-out continue while all four application slots remain +occupied, including their timed-out actual tasks. + +The otherwise-eligible production selector independently ranks a retained original +first. Three handlers then return through their real closed-gate refusal, +rollback, cleanup and history resolution. Exact original-object eviction permits +a fresh operation for the same ID. Another recipient commits its reciprocal child +and completes while the remaining held row preserves its original token and +operation. Releasing that old attempt cannot attribute a later child's ACK to it. +All six children eventually complete through the actual runtime. + +Two separate source controls fail the same semantic assertions: enlarging the +ceiling from four to five admits six wrapper entries, and removing only the SQL +retained-ID exclusion replaces the otherwise-first held token. The rank helper +does not assert the removed SQL spelling, and full capacity does not mask the +exclusion check. Both controls build cleanly and are restored with exact hashes +and file modes before final qualification. + +Two further cases separate a physically held original cancellation callback from +an actual DI scope's successful asynchronous disposal. The callback case first +proves that the executor, scope and application-source cleanup have returned; +the cancellation relay alone remains held. The scope case instead observes a +positive child COMMIT ACK while actual scope disposal and executor return remain +pending. Every sibling, including any native registration, positively joins +before the original operation and both source pins are checked. Replacing the +all-owner cancellation join with an any-owner wait fails the callback case while +the independent scope case still passes. The original join is restored exactly. + +Narrow reviews correct the exact three-history-owner eviction observation and +the registration fixture's inline-cancellation race. Registration is itself an +owned actual task with a finite setup wait. All barriers release before shutdown; +nested finally blocks independently join registration cleanup and the original +operation. These reviews grant no full Step 8 review credit. + +The initial application-test build records two analyzer errors, corrected without +changing production policy. Earlier clean qualification passes the application +case and both source-pin cases. The final restored 325-source Release build has +zero warnings/errors; all 79 recurrence PostgreSQL cases pass with zero skips in +1m08s. The four focused Architecture cases initially expose the stale published +240-method count; five already-added Step 8 methods make the actual total 245. +After that documentation correction all four pass, including Docker-trait and +planted-trait checks, the non-skip guard and catalogue counts. The runner verifies +nonempty execution and zero skips; explicit TRX checks separately require zero +failures in both final runs. Scoped formatting reports no changes. The source, +mode and artifact receipt closes at +`c463834754105981e5babcad10d39cbf0529a6c8a4b9f3b0358ba0ae94ebec6a`. + +New-owner/native-manager/tick/exclusion capability guards and their planted +controls still precede both fresh full Step 8 review rounds. Nineteen packet +obligations remain Registered, Step 9 remains pending, and this qualification +claims neither packet-wide regression nor CI success. + +#### Recurrence core capability qualification + +After `b72ce6ce`, a new nonempty production census closes the four concrete +recurrence owners' constructors, startup/cancellation callbacks and parent +completion capability. It pins exact declaring assembly, method signature, +visibility, caller, opcode and multiplicity. The internal sealed native client's +primary constructor has public IL visibility; the census records that actual +shape without changing production accessibility. Null-conditional native stop +and thread-exit calls likewise retain their exact compiled opcodes. + +A narrow review finds that name/count checks alone could accept a foreign +cleanup target. Cleanup checks now require the exact trusted .NET 10 facade +identity, full signature, instance/static shape and opcode. Actual configured +awaiter identities preserve multiplicity, including both non-generic native +awaits. Attached foreign capability, Thread and nested awaiter controls must fail +the same detector; each restores the original operand before removing its +temporary in-memory type. No assembly file or production source is mutated. + +Earlier guard runs record incorrect constructor/opcode premises separately; +mutation cases failing their clean baseline receive no dirty-control credit. +The final 326-source Release build has zero warnings/errors. Thirteen focused +Architecture cases pass in twelve seconds with zero skips: the baseline, eleven +clean/dirty/restored controls and the catalogue count. The two added companion +methods bring the published count to 247. Scoped formatter verification reports +no changes. Its source/mode/artifact receipt closes at +`8d62c2fd3956e1bc2d182ea1dcda0f1ff61e7e00f6a5388480e971942ad4c4d2`. + +This qualifies the core capability slice, not semantic task-dataflow enforcement +or the complete recurrence census. Field/holder and publication ownership, +native SDK invocation, memory-only ticks and exclusion-list guards remain before +both full Step 8 review rounds. Nineteen packet obligations remain Registered; +Step 9 is pending. Neither narrow source review supplies full-round credit. + +#### Recurrence ownership, hint and publication guard qualification + +After `59a19e15`, the same two companion methods close the new owners' field +inventories, resource types, exact access sites and whole-production holders. +Actual async attributes identify permitted state-machine holders. Generic +resource identities are checked recursively; same-name foreign resources and +forwarding accessors are rejected. Each completion source retains its actual +concrete owner. Existing physical-source, privileged-entry and rollback caller +allowsets are unchanged. + +Native registration uses the exact stock manager seam, two manifest arguments, +control queue, UTC minute hint and Relaxed misfire policy. The census includes +the stock V2 recurrence interface. The fourteen-method tick closure admits only +its enumerated memory calls/fields and pinned framework/vendor leaves; injected +scheduling, indirect calls, changed tick identity or early readiness reads fail. +This establishes a closed work surface, not an absolute latency guarantee or +general argument/control-flow proof. + +Recipient selection retains its sole caller, bounded collection snapshot, +actual UUID-array parameter and retained-ID SQL exclusion. Source-order checks +pin publication before Start, cancellation join acknowledgement before source +disposal, and positive completion after actual cleanup/thread-exit observation. +The previously recorded actual PostgreSQL/retained-task controls supply the +separate causal lifecycle evidence; structural order alone is not its substitute. + +Narrow independent inspections identify and verify corrections to the V2 +interface census, resource/generic identities, cancellation join acknowledgement, +provider invocation identity and tick token. Earlier build/clean-premise errors +are retained separately. The initial 43-case run has one passing catalogue case +and 42 clean-baseline failures caused by an ambiguous completion-signal selector; +none receives dirty-control credit. The corrected selector distinguishes the +returned signal from positive owner completion. + +The final 330-source Release build has zero warnings/errors. All fifty focused +Architecture cases pass in one minute ten seconds, with zero skips: the baseline, +48 clean/dirty/restored cases and the unchanged 247-method catalogue count. +Scoped formatter verification reports no changes; its workspace-load warning is +not reported as a build warning. The source/mode/artifact receipt closes at +`cc7fcc480cd9234aa9d80ef189d3a602bc32c5e10b884e5393cd797bd22c7b4a`. + +This completes the new guard slice. Both fresh full Step 8 review rounds remain +before Step 9; these narrow inspections award neither round. All nineteen packet +obligations remain Registered. No packet-wide regression or CI success is claimed. + +#### Step 8 full review round 1 (2026-10-18) + +Three fresh independent reviewers inspected `69405b16..332e7a4a`: GPT-6-astra +xhigh covered runtime/lifecycle, GPT-6.1-sol xhigh covered persistence/authority, +and GPT-6.1-sol high covered tests/corpus. These are full Step 8 reviews, distinct +from the earlier narrow preflights. The reviewers ran no toolchain or database +checks; the execution receipts below belong to the root implementer. + +Two Major findings and one Minor corpus correction were verified: + +- A stop winning before the new child's native-client binding or Start caused a + setup exception. The parent/facade could then retain a false cleanup failure + indefinitely despite no issued recurrence work. Both child entry points now + return neutrally for that stopped-before-setup state. Already-bound/started + duplicate refusals and an open nonempty owner's missing-client refusal remain. +- PostgreSQL's finite timestamp range exceeds the CLR range. A schema-legal BC + activation or year-10000 anchor could repeatedly fail decoding the first due + row before its invalid-control branch, starving healthy work. Readers retain + the actual locked locator before decoding and treat unrepresentable dates as + absent facts, never fabricated valid values. After actual reader cleanup, the + exact recurrence, occurrence or recipient is quarantined without issuing work. + Only deterministic conversion exceptions are contained; IO/cancellation/server + failures retain the existing owner/cleanup path. Higher-revision registration + compares the prior activation in PostgreSQL instead of decoding it into CLR. +- The live catalogue introduction still described completed Step 7 qualification + as pending. Both current pointers now agree with its completed record; Step 9 + enforcement remains pending and all nineteen obligations stay Registered. + +The first four regressions ran against unchanged production code and failed at +all four intended assertions, not fixture setup: two bad-date rows repeatedly +failed without quarantine/healthy progress; two late child setup calls threw. +That test-only receipt is +`6613d4652759320ee077261bc6186efef597258d74d832431dc407d584d24299`. +With the five production corrections, the same four cases pass; the first +corrected receipt is +`e54a9f08143b829cac78911e3291a2a7dfafe374e0a9dbee2e7548a6cb94948f`. +Neither receipt is a current-head whole-packet regression or CI claim. + +The expanded qualification adds eight timestamp cases across recurrence +materialization, occurrence paging, recipient acquisition and higher-revision +registration, all under the real confined-role grants and unmodified guards. +Each invalid selected row confirms ACK/cleanup, no authority/progress beyond +quarantine, and healthy sibling progress. BC scheduled routes require BC manifest +activation, so their absent-manifest branch does not independently qualify the +recipient's own-date checks. A future year-10000 incumbent activation returns +Conflict without inserting a revision; a BC incumbent permits the later valid +revision and exact supersession/hash. + +Four lifecycle cases use actual owners and sources. The late setup assertions +inspect the actual null client/native fields, unstarted flag, empty recipients +and positively completed null-loop witness. A synchronous hold on the actual +child monitor orders real parent Start past its admission guard before facade +stop, then joins the original start task, parent/facade completion and both +sources. The open/duplicate controls preserve programmer-error refusals. No +synthetic owner/task/source replaces the real cleanup chain; the parent barrier +is qualified on corrected code, not described as an original-code execution. + +The expanded Release build has zero warnings/errors. All 2,408 Unit, 91 +recurrence PostgreSQL and 57 focused Architecture cases pass with zero +failures/skips. The Architecture run includes all 49 recurrence capability cases, +four existing owner/recipient guards and four catalogue/skip/Docker-trait checks. +The seven changed C# files pass formatter verification with no changes; its +workspace-load warning is distinct from the warning-free build. The 332-source +hash/mode receipt closes at +`afdda5089283dd6eee49f527576466778817bf78f3a041c857d4385bccb00239`. +The local link audit passes 1,740 links and 519 fragments. These focused checks +do not replace Step 9's complete regression or real CI. Round 1 and its verified +corrections are complete; a fresh full Step 8 round 2 is still required. + +Step 9 explicitly owns durable unknown/deployment-mismatch observation, including +an empty-registry restart. Local registration mismatch flags alone do not qualify +that cold durable-health surface. These corrections add no new ADR decision, +role/grant, production business definition or general lifecycle selector. + +#### Step 8 full review round 2 (2026-10-18) + +Three new independent reviewers inspected the complete `69405b16..f687924b` +range: GPT-6-astra xhigh (runtime/lifecycle), GPT-6.1-sol xhigh +(persistence/authority/security), and GPT-6.1-sol high (proofs/corpus). The +persistence lens verified no finding. Runtime and proofs independently found +the same Major acceptance-proof gap, counted once: ADR-0059 explicitly requires +recurrence progress while the actual control generation stays drained/held. +The earlier native-manager-thread hold and empty-registry delayed-job repair +proofs did not establish this composed scenario. No new Step 8 runtime defect +was verified. These full reviews ran no toolchain/database checks. + +The new real-facade test preregisters a due 61-day-old, 30-day-interval manifest, +then locks that actual row before starting the runtime. It holds the actual +control generation's owned Invocation, requests drain, positively joins its +normal children and verifies zero occurrences/native jobs before unlocking. +The retention barrier is explicitly synthetic; no network/business fault is +claimed. A coalesced occurrence skips two slots and completes one reciprocal +recipient/child with one normal attempt while the same generation remains held. +Three real SDK ticks remain Enqueued during drain; three actual duplicate store +quanta add no slot. Releasing and positively joining the original generation +permits a replacement to execute those ticks without another occurrence, child, +normal attempt or feature execution. Actual runtime and both source lifetimes +must confirm cleanup/disposal. + +A separate inherited Major parent-start race was verified against the Step 8 +base as well as current code. Facade startup could pass its final admission, +then encounter an already stopped parent's throwing Start guard and retain a +false cleanup failure indefinitely. This is not attributed to the new child +race or Step 8 diff. It is corrected now within the packet: an already-started +parent still rejects duplicates, but stop before its first start returns +neutrally using RequestStop's actual empty-loop witness. No cleanup flag or +completion promise is reset. + +The new stopped-parent leaf fails at the original guard on unchanged `f687924b` +production, then passes with the correction. Its executed negative receipt is +`6a01365667134f9e6ff9c03d74da65f5fa4e9eac756b7367333d54f2571a9970`. +An initial test-only blocking-Result analyzer error is recorded separately and +receives no execution credit. The corrected actual-facade test holds the real +parent monitor, observes the original facade task's Starting state after its +last admission, then calls stop before parent admission and releases the +monitor. It joins that same startup task, facade and actual sources without +awaiting under a monitor. A distinct already-admitted-parent case preserves +duplicate refusal. The full facade barrier is qualified on corrected code; +no old-code full-facade cleanup claim is made. + +Both focused correction reviewers approve the inspected source and causal test +premises; these are verification of round-2 corrections, not a third full review. +The first corrected 333-source receipt records a zero-warning/error Release +build and four focused PostgreSQL cases passing with no skips: +`88e67c6e998d603c87874635eee1deeac615b124732359ab8860abd82186aa12`. + +A deliberate, uncommitted source control couples control-generation drain to +the shared process start gate. The same held-generation test then fails at +post-drain durable child progress, after its actual join/row-lock premises, +and performs its ordinary barrier/owner cleanup. That dirty receipt is +`ba68cf1a3dd7a77c9490dc82fe1d3208c585569c88ae714cdda10c291ae968fe`. +The generation source is restored byte-for-byte and the corrected source/mode +inventory matches again. No mutant enters the change. The test demonstrates +its ability to reject the forbidden dependency; it is not a production fault +or unconditional delivery-latency guarantee. + +Final clean-source qualification freezes 333 changed/new C# sources and records +a zero-warning/error Release build, 2,408 Unit cases, 94 recurrence PostgreSQL +cases and 57 focused Architecture cases passing with zero skips. The focused +Architecture run takes 4m12s. The final receipt is +`268a030f9ee059860732668f78061973caf5cd6da342d5a43191a526915d9431`. +Scoped formatter verification returns no changes. Both full Step 8 review rounds +and verified corrections are complete; this closes Step 8 locally. + +Step 9 follows under the already Accepted plan. Its scope includes durable +unknown/deployment-mismatch observation, full job metrics and health, complete +nineteen-rule enforcement, the skill/carrier handoffs and full packet regression. +The historical complete Architecture run exceeds the existing backend CI budget; +Step 9 must measure and reduce repeated detector scans while preserving every +subject and clean/dirty/restored control. No nineteen-rule promotion, complete +backend/frontend/demo, packaging, CI-duration compliance or real PR-head CI +success is claimed by Step 8 receipts. No maintainer decision is pending. + + +### P02b-4 Step 9 — enforcement and packet closeout (2026-10-18) + +**Current status:** the [local closeout](#p02b-4-local-closeout-2026-10-18) owns +completed implementation/reviews, exact qualification and remaining PR/CI/merge +work. Earlier slices below retain their as-of evidence. + +**Initial status — implementation in progress.** Step 8 closes locally at +`390515b8` after both full review rounds and verified corrections. This follows the already Accepted +ninth step; no new maintainer decision is pending. + +The step's three internal closure units are: + +1. Complete full job observation, including bounded dimensions, memory-only + immutable gauges, cold durable unknown/deployment-mismatch health and distinct + confirmed-failure versus uncertain outcomes. Reduce repeated Architecture + detector scans without dropping cases, production subjects or any mutation/ + restoration pass; the unchanged whole backend CI budget still requires proof. +2. Match all nineteen packet obligations to actual nonempty production censuses, + behavioural proofs and planted controls; complete carrier/feature handoffs and + the shared repository background-job skill. Catalogue promotion waits for + complete enforcement and qualification. +3. Run complete backend/frontend/demo regression and packaging/boot proofs, + commit, then run two fresh full multidimensional review rounds with verified + corrections and commits. Prepare the development-to-main PR with exact local + evidence; real PR-head CI and maintainer merge remain separate. + +The initial performance preflight is read-only planning, not a benchmark or full +review. It finds repeated whole-production instruction traversals inside one +read-only detector evaluation. A current-source four-case baseline runs before +editing that mechanism. Any index must be fresh for every clean, dirty and +restored evaluation, include every actual operand/owner/opcode and retain exact +identity and multiplicity checks. No shorter filter or increased CI timeout is +proposed. Full observation/enforcement and packet qualification remain pending. + +#### Initial scan and existing-boundary qualification + +The first slice adds complete method/field operand indexes inside one disposable +detector evaluation. Name buckets only prefilter the existing full identity, +opcode, order and multiplicity checks. Every clean, dirty and restored evaluation +gets fresh indexes. Owner strings are computed after candidate selection, and +ordinary call-site ownership is formatted only when its body contains a method +operand. The attribute-based async-owner mapping remains unchanged. + +The four-case current-source baseline passes in 288.801 seconds of summed case +time. Initial indexing passes the same four cases in 160.233 seconds; the later +owner-string refinement records 60.062, 38.801 and 47.214 seconds for the three +existing runtime/bridge cases, plus 3.651 seconds for the expanded cache companion. +These are focused measurements with additional cache controls, not a complete +workflow speedup or proof that the CI budget is met. A deliberate persistent-index +mutant fails the actual membership comparison. A separate stale-owner-string +mutant fails at the same method's `RenamedRun` versus cached `Run` identity. Both +test-only mutations are restored byte-for-byte before clean qualification. + +The complete intermediate Architecture run executes 403 cases: 401 pass, two +fail, and none skip, in 1,837.15 seconds of wall time. Its two failures expose +older source guards that still reject Accepted recurrence readers/task owners. +They do not justify broader runtime permissions. A brief native sample cannot +attribute managed hotspots; no profiling-based attribution is claimed. + +The organization guard now enumerates five exact SQL subjects across four actual +files: three composite point reads and the bounded composite inventory/bounds +queries. It pins direct command arguments, minimal projections, tuple seeks, +page limits and actual tenant/organization parameter bindings. The original +validator's READ ONLY/announcement ordering and the EF primary-key ban remain. +The parallelism guard permits only nine exact invocation spans in three retained +recurrence owners, with method/signature/count and suppressed-flow publication +checks; the rest of each file is still scanned. Neither change adds whole-file +exemptions or substitutes for the separate database grants and resource proofs. + +Focused independent inspections identify and close reader-discovery and binding +false passes: JOIN/interpolated/constant-concatenated readers, transformed SQL +literals, nonexecuted bindings, protected-key overwrites and captured parameter +rebinding. The actual-source dirty/clean companions exercise the same detectors. +Two new companions bring the published Architecture method count to 249; all +nineteen P02b-4 obligations remain Registered. These inspections are not either +full Step 9 review round. + +The final 338-source snapshot passes a CI Release build with zero warnings/errors +and all 39 selected Architecture cases, with zero failures/skips. The selection +includes both corrected source guards and their companions, cache sensitivity, +catalogue consistency and both complete orchestration mutation companions. Its +source/artifact receipt is +`832548288722970b30482e75a1f814e07675476210784f93d6913a7eb07f9b81`. +The final two orchestration cases take 54.310 and 239.371 seconds, supplying the +fresh baseline for the next bounded optimization. The unchanged twenty-minute +whole-backend CI budget remains unqualified. Full job observation, complete +packet regression and both full Step 9 review rounds remain pending. + +The next two-file slice removes eager orchestration identity formatting while +retaining the complete declaration and field-access inventories. Actual delegate +resolution uses a name bucket followed by the unchanged exact identity and unique +match policy. Field owners remain actual attributed method references until the +original name/type filters select them; string deduplication and opcode/write/ +address counts stay in their original positions. An independent companion +compares the old/new declaration policy with foreign namesakes and overloads, +then checks every field group and ordered occurrence before the full mutations. + +Both complete orchestration companions pass with zero failures/skips after a CI +Release build with zero warnings/errors. Their summed case time changes from the +fresh 293.681-second baseline to 191.688 seconds (33.271 and 158.417 seconds). +This approximately 35% reduction applies only to those two companions, including +the additional equivalence checks. The final 338-source/artifact receipt is +`3a8555f7481c4fb74a8123676a9ab61c5141f6e71d8cdccd393db8e2962a43f6`. +A focused independent inspection finds no correction; it supplies no full Step 9 +review credit or whole-workflow duration proof. The twenty-minute CI budget and +the remaining observation/enforcement/packet work stay open. + +#### Bounded mutation-collection qualification + +Eight existing heavy companion Facts move into three public nested sealed +partial classes. Each Fact still owns its independent Cecil graph and complete +clean/dirty/restored sequence. Canonical rule Facts remain in the outer class. +An explicit per-class collection attribute caps the Architecture assembly at two +runner threads; neither the CI filter nor its timeout changes. + +All 249 source method token sequences and compiled signatures/attributes match +before/after. Complete runner discovery preserves all 405 cases with exactly +eight declaring-class substitutions and no missing, extra or duplicated cases. +The first comparison omitted the custom-display NetArchTest meta case from its +404-row namespace subset; the corrected comparison includes that unchanged case. +A scratch actual-detector control proves distinct module/type/method/instruction +objects, an offender in graph A with graph B clean, and both restored clean. +The pinned xUnit factory selected by the actual assembly attribute assigns four +distinct collection identities to the outer class and three nested classes. + +The 341-source snapshot passes a zero-warning/error Release build, all eight +moved companions and six corpus/cache cases, with zero failures/skips. Scoped +formatter verification reports no changes; a focused independent source review +finds no correction. The source/artifact receipt is +`21c209eaefce9e70e5bc55117b02629cfa6be7fa45a9f9bddf0c7dac0dfd1482`. +The eight-case run takes 869.24 seconds of wall time; summed case durations are +1,433.773 seconds. Completion-time/duration reconstruction is consistent with +two overlapping collections. The adapter's TRX StartTime usually equals result +receipt time, so it is not independent execution-start telemetry. These figures +are workstation qualification, not a same-source speedup benchmark or CI proof. + +Repeated/full Architecture and complete backend-budget qualification remain +pending, together with full job observation, nineteen-rule enforcement and both +full Step 9 review rounds. No catalogue promotion or packet completion follows +from this focused slice. + +#### Durable observation foundation qualification + +The existing serialized status-read owner now publishes one complete immutable +aggregate after acknowledged rollback and actual resource cleanup. Frozen local +metadata classifies unresolved jobs, relevant historical recurrence manifests, +unfinished occurrences/recipients and unreleased reservations. The dispatcher +reads no payload or causal envelope and receives no new grants, source, task or +physical acquisition slot. Four independent indexed quarantine aggregates remain +in the same statement. A failed or stale refresh retains the prior sample and +cannot report healthy empty work. + +Cold native-runtime controls use genuinely empty definition and recurrence +registries. Four isolated fixtures retain future jobs/manifests or future retry +availability on unfinished children, without deployment-error markers. Completed +or fully superseded parents cannot mask a missing child aggregate. Each real +runtime reaches an otherwise healthy snapshot; only the copied deferred bit +changes its health result. Observation leaves the durable records untouched and +constructs no feature handler. + +The actual SQL hash CTE agrees with the independent .NET registry fingerprint +for thirty-six schedule/policy/date combinations, including microsecond limits, +unequal activation/anchor atoms, pre-epoch instants and maximum positive revision. +Two additional revisions prove discovery of frozen history needed only by an +actual pending occurrence. Diagnostic projections retain all production CTEs and +bindings and run under two session timezone/display formats. Epoch-offset, +repeated-anchor, omitted-history and removed-date-bound mutants fail their same +assertions. The unmodified full reader also accepts the valid population. + +An intermediate fourteen-case cohort passes eleven cases and fails three new +test assertions that incorrectly require a nonempty business queue in control-only +fixtures. Explicit empty-queue versus single-job assertions correct that test +error. The final 348-source snapshot passes a CI Release build with zero +warnings/errors and all twenty-three selected PostgreSQL cases, with no failures +or skips. This includes real rollback-response hold/loss, refresh grant refusal, +last-sample preservation and actual-query partial-index removal controls. Its +source/artifact receipt is +`606e8b2a5945cec409c20f23d7c1c25f0ae8d0cb74d0a920848bfc336d1f951a`. +Paired assertions in existing real admission, recovery, capacity and external +checkpoint tests qualify status eligibility against actual stored transitions. +They distinguish future original due time, retry availability, live/expired +routing, execution ownership, actual retained identities, unknown/Pending/retired +definitions and profile mismatch. Unreleased reservations remain counted after +expiry under their declared group or fixed unknown label. Repeatable/no-start +history admits real Normal routing after the proved backoff; selected outcomes +admit real Finalize routing independently of the six-normal-attempt ceiling. +These guarded state pairs do not claim independent removal tests for every +redundant storage defense. + +The final eligibility cohort passes fifty-two PostgreSQL and sixteen model/health +cases with zero failures/skips after a zero-warning/error CI Release build. Its +348-source/artifact receipt is +`af8b73b5899ffa0136cc0cdcd942d6cb5a003c904456be321043b760dcca7e80`. +The six production files remain byte-identical to the focused source inspection +and earlier three passing Architecture owner baselines. Focused inspections close +three hash-fixture proof gaps; none supplies a full Step 9 review round. + +Complete metric emission, nineteen-rule enforcement, full regression/CI duration +and both full Step 9 reviews remain in progress. No catalogue promotion or packet +closeout is claimed by this slice. + +#### Native observation projection qualification + +The immutable runtime snapshot now projects actual running/retained work, +generation counts and capture/join/cleanup facts from their existing owners. +Confirmed metadata timestamps remain nullable: an actual successful announcement +can confirm monotonic zero, while no confirmation remains absent. Returned pool +and maintenance collections reject replacement through their collection interfaces. +These additions introduce no scheduling, SQL, source or release authority. + +The first two-case PostgreSQL run passes the existing facade health case and +rejects a new fixture that supplies a separately reconstructed topology. Using +the host's actual frozen registry corrects the fixture without weakening the +production identity check. A focused inspection also closes its failure-path +cleanup gap: generation stop starts before either heartbeat or stop is awaited. +The final 350-source cohort passes both cases with zero failures/skips after a +zero-warning/error CI Release build. Its source/artifact receipt is +`733c1d57536c2c870810d27bb826b2cbf614cb153609ac6db01218e3f6dcb598`. +Three Architecture owner cases pass against the same production projection. +The manual real metadata callback does not claim Core's scheduling-cadence proof. +The focused inspection has no open findings and supplies no full Step 9 review +credit. Metric emitters and complete packet qualification remain pending. + +#### Memory-only job metric collector qualification + +One required concrete observation singleton binds the actual API runtime after +its snapshot owners initialize and before either source pin. The shared +API/Seeder composition creates no runtime or worker. Five observable families +project counts, exact SQL eligibility age, confirmed heartbeat age, component +state and fixed monotonic control observations. Each callback captures one +immutable memory snapshot and materializes its finite sparse measurements. +The [metric inventory](../standards/10-observability.md#required-metrics) owns +names and dimensions. Queue age remains the stored SQL sample; the earlier +acquisition/freshness timestamp cannot extrapolate it. Retained aggregate and +per-pool series remain distinct even for a legal pool named `none`. + +Actual MeterListener controls cover required DI, missing registration, +bind-once/disposal authority, conservative freshness, missing versus confirmed +heartbeats and complete empty-sample zeroes. Real PostgreSQL/native controls +observe cold unknown work under empty registries, preserve prior quarantine +samples through actual grant refusal and check complete metric identities for +the legal `none` pool. Fifty-eight unit and ten PostgreSQL cases pass with zero +failures/skips; their production and fixture sources remain unchanged through +the subsequent Architecture corrections. + +Three new Architecture companions inspect actual singleton descriptors, consumed +instrument/callback arguments, binding receiver/order/dominance and the transitive +memory method graph, including reached static initializers. Balanced clean/dirty/ +restored controls reject indirect SQL, arbitrary delegates, hidden or extra Meter +registrations, name/callback bait and skipped binding. An initial seven-case run +passes six cases and fails a new fixture's ambiguous instance/static constructor +selection. After that correction, a four-case run passes three and reveals an +unreachable skipped-binding mutation: existing branch targets bypass its prefix. +Moving the mutation onto the actual landing instruction corrects the control; +the final three metric companions pass with zero failures/skips. The complete +existing runtime/source-owner companion passes against the same shared walk. + +The final 356-source snapshot builds in CI Release with zero warnings/errors; +its source/artifact receipt is +`0327dabd84b0f91c0db248312f7747e0f6439756491160756bd6bfae43740100`. +Focused collector and guard inspections close their verified findings; neither +supplies a full Step 9 review round. Stage/event instrumentation, complete +control-path accounting, nineteen-rule enforcement, whole regression/CI-budget +qualification and both full Step 9 reviews remain pending. + +#### Actual executor stage measurement qualification + +Three synchronous families add execution duration, confirmed stage failure and +uncertain write/effect observations to the five memory collectors. Seven actual +executor owners record after their existing scope/Activity/context/authority/ +source/auxiliary/registration cleanup. Duration excludes subsequent metric +notification and the outer native owner's later private-token cleanup; a blocked +listener still belongs to the actual task. Each instrument contains catchable +listener faults independently, reports observation unhealthy and preserves the +original result. A physical acknowledgement remains successful through cleanup +or notification faults. + +The private provider-issued bit records the existing typed bridge's successful +entry CAS immediately before the actual call. It grants no execution, checkpoint, +retry or release permission. Construction/entry faults before that point do not +become uncertain external effects. Valid Running reports remain pending; +explicit Unknown and issued-call faults remain distinct from provider Failed. +Capacity cleanup without acknowledgement or uncertain COMMIT uses neutral +`NotCommitted`, since its existing result does not distinguish refusal from +failure. Business cancellation registration disposal now completes before its +final classification and measurement. + +All 364 Jobs unit cases and 25 selected real PostgreSQL cases pass with zero +failures/skips. The latter retain actual dropped-COMMIT-response, post-ACK scope +and Activity faults, held cleanup, throwing metric listeners, unissued provider +constructors, genuine provider/finalization, Running/Unknown and issued reconcile +fault/timeout premises. Measurement assertions accompany those durable facts; +they do not substitute for them. These cases do not independently qualify every +capacity, recipient or stored-selection metric branch. + +The first seven-case Architecture cohort passes six and fails a new stage-call +scan on a deliberately detached method reference. Narrowing to an attached exact +observer target before formatting identity fixes that detector regression. +Focused review also closes call-reference versus call-opcode, synchronous unit/ +numeric metadata and actual stage-root selection gaps. Balanced method-group, +seconds-to-milliseconds and direct SQL mutations exercise those same checks. +The hidden-Meter boundary permits only the exact instance constructor; a dirty +actual observer static initializer proves that distinction. The final seven +Architecture cases pass with zero failures/skips, including the complete prior +runtime/source and orchestration companions. + +The final 357-source snapshot builds in CI Release with zero warnings/errors; +its source/artifact receipt is +`847271cf34791d5cb0d930202de07500776afac2adc5463249e0bfe7d524e616`. +Production and unit/PostgreSQL fixture sources remain byte-identical through the +final guard corrections. Focused implementation and guard inspections have no +open findings in this slice and supply no full Step 9 review credit. Named-source +tracing/Start ownership, remaining branch/lease/control instrumentation, +nineteen-rule enforcement, whole regression/CI-budget qualification and both full +Step 9 reviews still precede packet closeout. + +#### Named-source tracing and cleanup ownership qualification + +The required observation singleton owns `learnstack.jobs`; its finite factory +returns an unstarted W3C Activity. All eight actual owners capture it before +`Start`. Recipient and pre-envelope recovery reads start independent roots; +terminalization keeps the real suppressed control lane. Trusted envelopes supply +the other parents. Recipient startup clears the caller's context before central +enrichment; it invents no tenant tags before the actual route context exists. +All seven executor owners independently attempt Activity and tenant restoration, +including a restoration callback fault after an actual COMMIT acknowledgement. + +Absent, refusing, propagation-only, sampled and throwing samplers preserve the +factory contract. The first unit run detects an all-zero fallback parent; +omitting `SetParentId` for a default parent produces a genuine root. The corrected +373 Jobs unit and 70 real PostgreSQL cases pass with zero failures/skips. Actual +recipient, capacity, stored-selection/no-start, recovery, held/faulted cleanup and +lost-ACK premises accompany source/parent/measurement assertions. The first PG +selection accidentally includes a helper-name filter and is canceled; it earns +no full passing receipt. The replacement uses 35 exact test-method identities. + +The source census binds the consumed source name, readonly owner, factory and +disposal receivers, actual retained Activity slot and Start/Dispose instructions. +Its memory walk follows the actual factory through helpers and static +initializers. Name bait, early Start, spare slots, hidden sources, helper SQL and +helper Start controls pass in the corrected ten-case Architecture cohort. Final +disposal method-group controls additionally distinguish an actual call from a +captured reference; all ten final Architecture cases pass with zero failures or +skips. The final 362-source receipt is +`ca0549e92bcb4bad50ea5fc7d82218bc3831a2bc9bcad49c21c6c6000095c9f9`. +Only the tracing guard differs from the preceding 373-unit/70-PostgreSQL source +snapshot; all production and behavioral fixtures remain byte-identical. Caller +operation/parent policy is behavioral qualification, not a general IL dataflow +claim. Focused reviews supply no full Step 9 review-round credit. + +Complete control/lease/late-settlement accounting, nineteen-rule enforcement, +whole regression and unchanged CI-budget qualification, and both full Step 9 +reviews still precede packet closeout. + +#### Control transition counter qualification + +Actual control owners retain physical renewal, retry and terminal observations +even when subsequent cleanup refuses release. The original completion request +counts its retry once; a clean locked probe can confirm that exact transition. +Same-generation routing repair and changed ownership do not imply a retry. +The external execution owner likewise distinguishes its actual retry ACK from +its original locked confirmation. Renewal history has a separate fixed +`renewal_history_confirmed` cell and never reopens the closed execution lease. +No counter recorder creates a source, task, listener invocation or authority. + +The new actual-owner PostgreSQL theory covers ACK, lost ACK with a real blocked +confirmation query, and a later real admission that changes the original owner. +All three corrected cases pass. The existing nine native known-outcome/recovery +cases additionally assert direct retry ACK totals. The initial new theory uses +an invalid 25 ms polling bound and leaves its probe pacing at the 30 s default; +those setup defects are corrected to the accepted 50 ms and 5 s bounds. Its +initial three failures do not constitute counter-runtime failures. The first +build also rejects a nonexistent test-row property, replaced by an independent +database generation read. + +The final source census roots each of the three recorders and the finite retry +predicate in the existing memory walk. Reached/unreached SQL helpers and clean +restoration distinguish these paths; exact references and typed bookkeeping +owners remain bounded. Real-listener projection uses distinct acknowledged and +history-confirmed renewal values. Focused reviews grant no full Step 9 round. + +The final CI-mode Release build has zero warnings/errors. All 373 Jobs unit and +six final Architecture cases pass with zero failures/skips. The three corrected +owner cases and nine native PostgreSQL cases cover byte-identical production and +PG fixture inputs; the final changes affect only four guard/unit files. The +final 363-source receipt is +`067bf593428c041bcbb0b0e1857c0c2e1c8a635f55b0bed3608eb6c6fd7362e8`. + +#### Control branch qualification + +Fourteen actual-owner PostgreSQL cases pass together with zero failures/skips. +They cover external retry ACK, lost ACK with blocked original-history confirmation +and changed ownership; both native Finalize retry paths; ordinary retry plus +actual grouped-capacity rollback/release; physical versus history-confirmed +renewal; and terminal MUST audit followed by held or refused scope cleanup. +The existing prebound late-renewal case also passes with the selective proxy. +History-confirmed renewal never reopens execution permission. Terminal counting +preserves an acknowledged audit even when actual cleanup refuses release. + +The proxy holds the actual renewal COMMIT by its returned column inventory; +other control transactions cannot consume that fault. Actual owner results, +durable state and row-lock waiters constrain the observations independently. +The grouped retry case qualifies a physical ACK, not grouped lost-ACK history. +The deliberate terminal cleanup failure disposes its inner scope before throwing; +the finite observation task joins actual lanes while public cleanup remains +unconfirmed. Isolated external retry ownership does not establish native +Hangfire handoff. The focused source review reports no verified findings and +grants no full Step 9 review-round credit. + +The final CI-mode Release build has zero warnings/errors; scoped formatting +reports no changes. Production source remains unchanged from `c581f798`. +The final 364-source receipt is +`fb03a92a9e6e96b22aae6953c233fe5b4106d02567421b6e355d1741627b06b1`. +Connection-cleanup fault combinations and grouped retry history are not claimed +by this bounded cohort. Recurrence/bridge/lease/late accounting, nineteen-rule +enforcement, whole regression and unchanged CI-budget qualification, and both +full Step 9 reviews remain open. No catalogue obligation is promoted here. + +#### Recurrence progress qualification + +The actual recurrence owner records six fixed process totals from original +acknowledged occurrence/page results before cleanup qualification. These cover +inserted occurrences, skipped slots, pages, raw routes examined, inserted +recipients and completed fanout cursors. Registration, native ticks, null results, +unacknowledged values and later history add no original ACK. The existing +eight-family metric inventory projects them through fixed control-total +operations without identity labels, new SQL, sources, tasks or authority. + +Both-scope actual-runtime PostgreSQL cases examine three raw lifecycle routes, +including a suspended tenant, and create two recipients in two pages. Independent +stored state, child/context checks and actual listener samples establish one +occurrence, two skipped slots and one completed cursor. Repeated collection and +duplicate native ticks preserve the totals. Two isolated actual-store/owner-hook +cases lose the physical COMMIT response after proving the server write: their +nonnull results and later no-op queries never become acknowledged progress. +They qualify occurrence and empty-page uncertainty, not native-runtime handoff +or nonempty-page lost-ACK inserts. + +Eleven unit cases feed the actual generic owner observation hook with synthetic +ACK facts and real resource-model cleanup. ACK plus failed cleanup preserves +the totals and retained ownership; no ACK remains zero. This is not genuine +PostgreSQL transaction/connection disposal-fault injection. Distinct scalar +listener projection is supplementary to actual-runtime producer qualification. +The transitive memory census includes the private recorder and rejects reached +SQL and an extra caller; exact typed field access and emitted compiler cache +owners remain pinned. The two source-review findings, a missing namespace import +and assertion-failure teardown path, are corrected before the first build. +The focused review has no remaining findings and supplies no full Step 9 credit. + +The CI-mode Release build has zero warnings/errors. All 384 Jobs unit, 52 focused +Architecture and four PostgreSQL cases pass with zero failures/skips. The final +366-source receipt is +`10600bb7dd16c847e74001e3e1af3b375dc1e1057cbdf6c0ea1caeaab073a6b5`. +Bridge/lease/late accounting, nineteen-rule enforcement, full regression, +unchanged CI-budget qualification and both full Step 9 reviews remain open. +No catalogue obligation is promoted by this slice. + +#### Bridge repair qualification + +The locked bridge candidate classifies prior acknowledged hint, expired prior +token without a hint, or unmarked state before replacing its token. Hint takes +precedence. Two fixed process totals count the disjoint marked-repair subsets +only after actual startup/native exit and a true fenced ACK return. Unmarked is +not first-ever work: a prior creation-failure deferral can clear its markers. +Deployment-mismatch deferral now counts only a true fenced status change. +The existing eight metric families and authority/source/grant boundaries stay +unchanged. + +Thirty-two PostgreSQL cases pass, including actual stock repairs for missing, +failed and succeeded vendor hints; old-marker precedence; an actual stale ACK; +and false mismatch deferral after real claim cleanup expires its fence. Two +runtime/stock-client cases project both repair cells through the live listener. +Their prior-hint setup uses a synthetic numeric hint, not a claimed earlier +stock creation; the separate stock repair cases cover that provider boundary. +Actual native startup/stop/join controls preserve zero repair counts while +ownership is retained. + +The real status-connection cleanup is held after its matching COMMIT. A separate +database read proves the vendor ACK while counters remain zero until the actual +bool call returns. A throwing Closed-event cleanup control instead leaves zero +visible ACKs and one retained logical owner; the actual native thread, observer +and test callback have ended. The bool API cannot expose the ACK hidden behind +cleanup failure, so no current-row inference backfills it. Exact locker/role +barriers and nested finally cleanup constrain these tests. + +The corrected CI-mode Release build has zero warnings/errors. All 384 Jobs unit, +six focused Architecture and 32 PostgreSQL cases pass with zero failures/skips. +The first build rejects a test-local variable-name collision, corrected without +runtime changes. Focused review also corrects the exact classification-getter +caller census before testing; no findings remain and no full Step 9 credit is +claimed. Exact typed fields, immutable classification and reached memory-only +observation remain guarded. The final 369-source receipt is +`ae0bb0721b6bce47230b38c07098cfa245a56fe51f16263d79a3e4254e62b799`. +Lease/late accounting, nineteen-rule enforcement, full regression, unchanged +CI-budget qualification and both full Step 9 reviews remain open. No catalogue +obligation is promoted here. + +#### First lease-loss observation qualification + +Two fixed process totals retain the first observed renewal refusal or elapsed +local lease per validated start publication or clean recovery receipt. The +execution's cause CAS precedes its Interlocked-only persistent parent recorder; +recording adds no task, source, grant, listener or execution authority. Existing +identity publication stays in place. Already-visible stop, settlement, join, +cleanup fault or permanent renewal closure suppress a new count. Gate observation +does not establish universal atomic ordering with concurrent host stop. + +The seven-case unit matrix covers refusal, actual timer callback after controlled +clock advance, stop, join, settled work, missing publication and repeated recording +while Run remains open. The latter distinguishes a real first-cause CAS from +duplicate suppression supplied by a separately closed gate. Existing held timer +Change/disposal controls preserve zero counts. Real renewal-owner PostgreSQL cases +distinguish a physical ACK from lost ACK plus original locked history. Actual +Outcome ACK with held cleanup, including stored recovery selection, remains zero. + +Eight recovery-timer cases use real acknowledged PostgreSQL acquisition and +actual held timer factory/Change handles. Six stop/fault cases preserve zero; +two advance only the local monotonic observation clock during a held lease timer +prefix, then observe one elapsed loss before identity publication and no provider +entry. These are controlled-clock proofs, not wall-clock lease-duration benchmarks. +Cleanup still owns the actual returned handle; a hidden failed handle remains +retained. They do not independently qualify expiry before recovery Bind or every +normal publication/renewal elapsed branch. + +All 519 selected Jobs unit and five focused Architecture cases pass with zero +failures/skips. The first PostgreSQL run passes eleven cases and finds two fixture +shutdown omissions: elapsed-only cases had not closed generation starts before +awaiting completion. After that test-only correction, all thirteen pass in +94 seconds. Production and Architecture/unit source hashes are unchanged between +receipts. The corrected CI-mode Release build has zero warnings/errors; scoped +fourteen-file format verification reports no changes. The initial build's helper +return-type analyzer warning is corrected. Focused source review closes an async +metadata/discarded-task enforcement gap with transitive scheduling rejection and +balanced dirty/restored controls. This is not either full Step 9 review round. + +The final 370-source receipt is +`8ef7ac676619345655f818c371ee63cbf995564009703bd9243408724862795e`. +Late settlement, nineteen-rule enforcement, full regression, unchanged CI-budget +qualification and both full Step 9 reviews remain open. All nineteen obligations +remain Registered. + +#### Actual late-settlement qualification + +Seventeen fixed `late_<stage>_settled` process totals distinguish an elapsed +stage from eventual positive cleanup of its actual invocation. Only the stage +clock records the effective elapsed-stage marker; host stop, lease loss, timer +fault and a returned wrapper wait cannot invent it. Consumption happens once, +after actual framework/execution, timer, cancellation-callback and private-resource +cleanup. The existing bound invocation forwards only a fixed Interlocked update. +No task, data source, grant, execution admission or new metric family is added. + +Each stage requires its actual typed task and positive cleanup. Recovery +confirmation follows the current NoPlan/retry/acquisition branch and never +substitutes an older clean probe. Whole-framework completion covers history and +NoPlan loops beyond their final SQL slot. These are settlement observations, +not durable ACKs, successful business outcomes, rollback or provider-quiescence +certificates. Permanently retained cleanup contributes no settled count. + +Five new classifier cases cover absent tasks, observer join, exact business +stage, current confirmation branch and positive disposition. A live Meter unit +case checks all seventeen fixed projections, zeros and repeated scrapes. Wait +controls preserve predecessor/prospective-stage semantics and zero markers for +host stop or timer fault. All 525 selected Jobs unit cases pass with zero skips. +Four real stock-worker/PostgreSQL cases pass: two held framework-scope paths and +two provider-recovery paths distinguish actual clock expiry from host stop. +The latter holds private cancellation cleanup after provider return and confirms +zero until release, then one elapsed settlement or zero for host stop. This is +not positive native coverage of all seventeen stage kinds. + +The initial five-case Architecture run passes both orchestration censuses and +singleton registration; two metric companions expose exact emitted `call` +opcodes where the new guard expected `callvirt`. After guard-only corrections, +all three metric cases pass. Additional framework-task/cleanup-field ownership +and a planted extra-cleanup-writer control also pass those three cases. No +production, unit or PostgreSQL source changes between these receipts. The +CI-mode Release build has zero warnings/errors; scoped eighteen-file formatting +reports no changes. Initial missing namespace imports are corrected before that +qualified build. Focused independent source inspections leave no open finding +and provide neither full Step 9 review round. + +The final 375-source receipt is +`7cd762f4870900a03420ed4e14b416d89d15eeddae890a98fb6b2d391f62c1cf`. +Nineteen-rule enforcement, shared workflow guidance, full regression, unchanged +CI-budget qualification and both full Step 9 reviews remain open. All nineteen +obligations remain Registered. + +#### Shared background-job workflow guidance + +The shared `add-background-job` skill now describes the actual typed scheduler, +explicit registry/catalog composition, ordinary transaction owner, external +prepare/execute/finalize and three-state failure policy, capacity declaration and +recurrence path. The common skill catalogue links it for every agent runtime. +A focused source review corrects release wording for known failed/cancelled but +quiescent effects, distinguishes capacity declarations from optional entitlement +keys, and preserves all seven framework requests when replacing empty defaults. +It provides no full Step 9 review-round credit or feature business definition. + +The preceding late-settlement commit's hook changes only six property-pattern +indents and one trailing blank line. Reconstructing the exact pre-hook bytes +matches its recorded hash; no semantic tokens change. Its test receipts remain +pre-hook source receipts, rather than a newly claimed post-hook test run. + +#### Production manifest and route qualification + +A single fresh structural census compares every disk-discovered production +project and each module's four assemblies with the loaded population. It pins +both empty-registry factory paths and catalogue implementations, rejects +business/recurrence constructors in scaffold modules (including delegate/async +forms), and checks frozen registry state. The actual Program provider separately +resolves both registries, catalogue aliases, seven framework requests, exact +pool/queue/worker topology and nonempty runtime/health/hosted registrations before +asserting empty business/tombstone/recurrence manifests and unopened sources. +Missing/duplicate registrations and valid nonempty fixture registries exercise +the same predicates; recurrence rejection remains independent of definitions. + +The actual fourteen-route/method/handler multiset includes eight public actions, +liveness, OpenAPI, Scalar UI and its three static assets. Real extra dashboard, +recovery, neutral-path and probe-controller endpoints fail that predicate. +Whole-production IL additionally pins all four endpoint-registration call sites +and concrete/inherited public controller actions, covering paths not executed by +the Development host. Pinned dashboard method/type and generic middleware +capabilities have dirty controls without adding a dashboard runtime dependency. +A focused source review closes conditional-route, default-dashboard-options and +inherited-action false passes; it is not either full Step 9 review round. + +Seven focused Architecture/corpus/discovery cases and the actual API composition +case pass with zero failures/skips. Sixteen actual PostgreSQL policy-selection +cases pass, including the added accepted nonrepeatable Failed outcome at admission +six and rejected false-exhaustion projection; SQL source is unchanged by later +guard corrections. The initial host assertion omitted Scalar's static assets; +its approved exact inventory now includes them. The corpus counter exposed four +previous observation companion methods absent from the prose tally; the +mechanically verified total is 254, including the new manifest method. The final +CI-mode Release build has zero warnings/errors. Three-file format qualification +reports no changes. + +The final 377-source receipt is +`532c29d65f6362a9ea6d25a3c3d2e30827baa19213211847429821748f457105`. +Constructor-time context proof, combined privileged capacity qualification, +complete nineteen-rule reconciliation, full regression/packaging/CI-budget proof +and both full Step 9 reviews remain open. All nineteen obligations remain +Registered. + +#### Constructor-time context and trace qualification + +A four-case real executor theory covers tenant-wide/organization work, each with +success or cancellation while its actual business task remains held. After real +routing/admission cleanup, observation-only fixture hooks capture parameter, +root-request and handler constructors plus Body entry/continuations. Every +mandatory capture sees the exact stored tenant/org, SystemActor, causal actor, +job/incoming identity, module and correlation. Both sampled ActivitySources retain +the stored causal trace: parameter/root observe `job.execution`, while handler +and Body keep their genuine MediatR child and execution ancestry. The unrelated +caller context and Activity retain their exact references throughout and after +actual cleanup. + +The same assertion rejects a real parameter construction before job ownership. +A separate trace-only capture at the genuine constructor preserves correct job +context but selects the caller Activity; context facts pass and the independent +trace predicate rejects it. These are oracle controls, not a claimed production +source-reorder mutation. Static hooks restore their exact prior values only after +the actual task becomes terminal. A failed bounded join supplies no cleanup +claim. Caller AsyncLocal isolation alone does not prove each explicit finally +setter; existing cleanup/Activity fault cases remain complementary. + +All 24 selected business PostgreSQL cases pass, including the four new cases, +with zero failures/skips in 17 seconds. The final CI-mode Release build has zero +warnings/errors and scoped two-file formatting reports no changes. Initial +generic-assertion/cancellation-forwarding analyzer warnings are corrected with +explicit intentional noncancellation of the held Body waits. Focused independent +source inspection finds no defect; it is not either full Step 9 review round. +No production context writer or execution authority changes. + +The final 378-source receipt is +`e77b70cd875f2b208d46deaac82f248b21e508dbcbd9bb5598a9b0030cf14a7c`. +Combined privileged capacity, complete nineteen-rule reconciliation, distribution +and full regression/CI-budget qualification, and both full Step 9 reviews remain +open. All nineteen obligations remain Registered. + +#### Published distribution gate qualification + +The existing backend CI job now publishes the actual Release API into a fresh +owned temporary directory, then runs both existing offline distribution +verifiers against that publish and its exact API/Infrastructure build graphs. +Failure remains gating; only JSON receipts join its test-result artifact. The +required job name, filters and twenty-minute ceiling stay unchanged. The kit +README documents the prerequisite Release restore/build/publish commands. + +A fresh local framework-dependent publish completes in 1.176 seconds. All four +stock shared DLLs, corresponding-source archives and licence/notice inventories +verify. Fifteen dirty distribution controls reject, and the recipient-modified +Core inspection succeeds without a runtime restriction. The original 178-file +publish remains byte-identical after controls. These checks take 0.801 seconds; +replacement inspection does not prove a modified assembly executes compatibly. +The exact new workflow shell block also passes locally, emits both JSON receipts +and removes its owned temporary publish. `actionlint` and diff checks pass. + +This is artifact/graph and workflow-step qualification, not API boot, full CI +success or proof that the entire job fits its unchanged ceiling. Combined +privileged capacity, complete nineteen-rule reconciliation, full regression and +both full Step 9 reviews remain open. All nineteen obligations remain Registered. + +#### Canonical obligation ownership alignment + +Fourteen existing test methods now carry their catalogue identifiers in place. +Their complete source bytes reverse to the prior files after replacing only that +one identifier: bodies, attributes, Theory data, traits and dirty companions are +unchanged. The two existing canonical owners and the three substantive manifest/ +constructor owners provide the other five names. Compiled Architecture and +Integration discovery finds all nineteen names with their real case rows. The +Architecture method total stays 254. CI-mode Release compilation has zero +warnings/errors; scoped fourteen-file formatting reports no changes. + +This is naming/discovery qualification, not a new executed-test receipt, a claim +that any one named method covers its full assertion, or catalogue promotion. +Each complete obligation also retains its schema, native runtime and fault +companions. Combined privileged capacity and complete regression/packaging/boot/ +CI-budget qualification remain pending before full Step 9 reviews and closeout. +All nineteen obligations remain Registered. + +#### Combined physical-capacity qualification + +The actual registered job runtime, outbox and delivery processors share the +captured keyed guarded source at Pooling=true/MaxPoolSize=52. Their actual +completion tasks remain bound; the fixture explicitly starts those instances, +without claiming GenericHost startup ordering. One real stock expiration +invocation waits on a unique-key conflict for its exact resource. An independent +observer identifies its backend through the setup transaction's blocking PID; +a finite caller wait expires while that actual invocation remains Retained. + +Two independently selected terminal-audit scopes forward the genuine writer and +hold cleanup after their actual terminal/MUST commits, before connection disposal. +Three distinct confined-role, tagged backend PIDs and all pending cleanup facts +are checked before and after TenantB's actual native job creates an organization, +commits its business/MUST row and reaches stock Succeeded. An absent-owner control +fails the same conjunction. Observers use a separate source. Finally every hold +releases, all three real owners join, Busy reaches zero, native server rows vanish +and the disposed tagged pool has no remaining backends. + +The [canonical ledger](../standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity) +counts all current simultaneous/nested/retained owner classes.52 remains a +conservative supported floor, not a measured exact peak. Pinned source review +corrects an earlier planning premise: ordinary Worker state-lock disposal precedes +PerformJob, so its wrapper lifetime does not establish an extra nested checkout. +The existing actual composition51 refusal and maximum158 topology/cleanup proofs +remain complementary; no52-socket saturation or51 impossibility claim is made. + +Validation: CI=true Release build has zero warnings/errors. Four real PostgreSQL +cases pass with zero failures/skips, including the new combined case, both actual +messaging/source lifetime cases and retained-expiration native progress. The +closed382-file source receipt is +`b1fbb3344ff9df6f905937705a5c6ce493e59792f7facdccc947a8074aa9b451`. +The initial new-case run reached its business observer but failed on a test-only +text/UUID comparison; the corrected observer and all four cases pass on the final +receipt. Independent focused source review confirms the corrected expiration +physical witness, selective audit forwarding and actual joins, with no remaining +verified finding. This is not a full Step9 review round or complete packet +regression. All nineteen rules remain Registered pending that qualification. + +#### Step 9 full review round 1 (2026-10-18) + +Three fresh independent reviewers inspect `390515b8..d2bb2ee7` and the necessary +adjacent paths: runtime/security/ownership, enforcement/test falsifiability, and +corpus/composition/CI/distribution. The corpus reviewer also inspects the later +two-file frontend inventory correction. These are full Step 9 reviews; earlier +focused preflights do not count toward this round. Reviewers perform read-only +source inspections and do not claim independently executed regression results. + +No Blocker or Major is verified. One Minor finding identifies two live +observation summaries that still describe delivered stage/trace/lease/control +signals as pending. Both summaries are corrected and independently rechecked; +full packet qualification remains explicitly pending. All nineteen catalogue +obligations remain Registered. + +The complete non-Docker CI filter executes 3,043 passing cases with zero failures +or skips: 2,452 Unit, 410 Architecture, 177 HTTP Integration and four Contract. +Its local wall time is 1,641.70 seconds, with part of the run sharing the host +with Docker validation. This is not a hosted-runner benchmark or proof of the +unchanged twenty-minute whole-job budget. Repeated observation-body selection +inside a fresh detector evaluation is the next measured optimization candidate; +case identity, every mutation/restoration and the parallelism bound must remain. + +Full frontend typecheck, lint and build pass. Its first full test run exposes +unclassified offline Hangfire probe/kit files. An exact 32-path inventory fixes +that test-only classification; unknown probe/vendor/runtime paths still reject, +and runtime import modelling is unchanged. The corrected complete guarded test +run passes all 1,616 cases with zero skips/todos; corrected typecheck and lint +also pass. No application build output changes with these test-helper edits. + +The complete Docker complement is still running on the same frozen C# source. +It exposes an exhaustion-plan fixture whose entire population makes the broad +and narrow indexes equivalent, and a routing-wait observer that requires an SQL +suffix beyond PostgreSQL's default activity-text buffer. Source cross-checks +identify test-fixture defects, not demonstrated production failures. Corrections +and actual PostgreSQL reruns remain pending until this frozen run ends. A third +failure compares the latest schema to a historical predecessor while assuming +only the terminal-history function changes; later indexes invalidate that +premise. The correction will test the exact target/predecessor boundary and +retain a separate complete latest job-inventory round trip. Full +regression, demo/boot, CI-budget qualification, promotion and fresh full round 2 +remain open; this record does not declare Step 9 or P02b-4 complete. + +The completed Docker run executes 2,428 cases: 2,425 pass, the three identified +fixture cases fail, and none are skipped. Local wall time is 2,287.77 seconds; +this also supplies no hosted-runner or whole-job budget claim. The closed +382-file first-run receipt is +`1f44da4ddb710b882952141858a2a4fc49bf4e962ce9741c5ed1c3660eecf25c`. + +Corrections retain the real planner and exact exhausted-index assertion by adding +an independently counted due, zero-attempt population; stable cutoff and volatile +dirty-control bounds remain unchanged. The routing observer opens before the +operation and uses the exact blocking backend dependency, with absent/wrong-PID +controls and a genuinely pending operation before caller cancellation. The +rollback test retains singleton function differences at its exact target boundary, +then separately compares the entire latest job inventory. No production SQL, +lease/retry limit, migration, grant or schema exception changes. + +The observation traversal now groups actual bodies by reference-identical owner +once per fresh detector evaluation. Every original root, diagnostic and +clean/dirty/restored visit remains; the existing companion independently checks +actual group identity/order/multiplicity, linked async bodies and missing owners +through its real metadata mutations. No Fact or case is removed or added. + +CI-mode Release build has zero warnings/errors; scoped formatting reports no +changes. All twelve affected real PostgreSQL cases and eleven Architecture cases +pass with zero failures/skips, including the cache, credential, runtime, three +metric and five corpus guards. Their closed 383-file receipt is +`7337d9765902903797a50a222ad44adc41033444917c8a23e3d5ab2fb2bc3e95`. +Independent correction checks of all five C# files find no remaining issue; these +are round-1 fix verification, not full round 2. The runtime-lifetime case records +129.93 seconds versus 176.09 in the earlier full run, while the credential case +records 211.55 versus 204.60. Different cohorts/shared load prevent attributing +those durations to an isolated speedup or claiming CI-budget fit. Whole-job +qualification remains required without raising its ceiling. + +#### Canonical enforcement reconciliation + +All nineteen packet obligations now report Implemented in the +[catalogue](../standards/21-architecture-tests-catalogue.md#backgroundjob_submission_is_transactional_and_stamped). +Each status names its actual compiled canonical owner and links its exact source; +the full assertion also retains its structural, native runtime and PostgreSQL +companions. Ten canonical owners run in Architecture and nine in Integration, +including the actual Program composition case in the non-Docker partition. + +The closed first full run executes all 35 case rows of those nineteen methods +successfully. The later runtime-detector correction also passes its canonical, +metric, credential and independent mutation-equivalence cohort. This executed +evidence replaces the earlier discovery-only receipt; identifier alignment alone +did not authorize promotion. The three failed full-run fixture cases are +separately corrected and qualified as recorded above. + +The five corpus guards pass after promotion: 254 Architecture method declarations, +221 Implemented catalogue entries, 131 canonical Architecture entries and 90 +outside that assembly. Integration statuses name their own canonical class; +Architecture companions do not silently reclassify those rows. Link/fragment and +diff checks pass. Related live infrastructure/architecture summaries now reflect +implemented enforcement and the completed Step 8 reviews. Full Step 9 round 2, +demo/boot, packet closeout and exact PR-head CI/job-budget qualification remain +separate pending work. + +#### Step 9 full review round 2 (2026-10-18) + +Three new independent reviewers inspect the complete 150-path Step 9 range +`390515b8..720fca12` and necessary adjacent paths. Runtime/security/ownership, +enforcement/falsifiability and corpus/composition/CI/distribution lenses close +with no verified Blocker or Major. Reviews inspect source and existing receipts; +they do not claim independently executed regression or CI. + +Three deduplicated Minor prose inconsistencies are verified: the live catalogue +preface still calls promoted entries Registered, the glossary still calls stage +instrumentation remaining work, and the architecture summary still calls both +full reviews pending. Narrow corrections point to the owning status record and +retain the distinction between local qualification and packet/CI closure. Both +affected reviewers independently recheck the actual corrections and canonical +owners/counts, with no remaining verified finding. This is correction verification +within round 2, not another full review round. Both full Step 9 reviews and their +verified corrections are now complete. + +An inspected provider-stage `NeverStarted` label is not treated as a defect: +stage telemetry preserves the raw pre-checkpoint report, while the durable owner +still treats the unresolved report after ExecuteIntent as Unknown and grants no +quiescence, retry or release. The current observation contract distinguishes +those meanings; no runtime or vocabulary change is justified by this candidate. + +At that correction check, the catalogue, glossary and architecture hashes are +`35a184d078b587817fdffb1dcc07e2bb7ec332dbb8510adeac88548cc8aeae52`, +`b2597922840fa98a7992721f05de816565820a093f56133af27727999bdaa311` +and `bdaf367b047bed602dd8a2c4597eef90851b6f236522b3dd9e549b687a017494`. +These three prose corrections change no C#. The fresh complete non-Docker +rerun subsequently passes all 3,043 cases with zero failures/skips in 1,660.34 +seconds. Its closed 383-file source/artifact receipt is +`f6f01737022f2013483967ddbff89e06daa4abd2eea6dd1ffbeed7a7de80e3dd`. +This local result does not establish fit under the unchanged twenty-minute +whole-job limit; real PR-head CI/job-budget qualification remains required. + +#### Fresh demo and browser/audit qualification + +A fresh actual `development` checkout at `d2bb2ee7` contains no private root/web +configuration or previous demo artifact. Later commits change only tests and +documentation; the functional sources are unchanged. The normal seven-service +CI lifecycle restores, migrates, seeds, stops Keycloak, builds and boots the real +API/native HTTPS renderer, then exercises all nine linked seeded pages. The +earlier archive-only preparation boots successfully but cannot pass the required +Git source-provenance check because it lacks `.git`; that failed setup attempt is +retained separately and is not described as a product or audit failure. + +The actual clean-checkout `make demo DEMO_MODE=ci` exits zero in 662.69 seconds. +The proof completes in 582.168 seconds, within its unchanged twelve-minute bound. +All 27 JSON/HTML audit pairs and nine browser screenshots are present; every +automated accessibility score is 1, maximum normalized gzip JS is 106,575 bytes +and maximum CLS is zero. English catalog and Turkish lesson screenshots are also +visually inspected. These checks preserve earlier human/VoiceOver evidence and +do not claim a new complete manual accessibility audit. + +The nine LCP medians remain advisory at 2,012.61–2,197.74 ms against the existing +1,500 ms warning threshold; response-time and blocking-time medians raise no +warning. No timing advisory is relabeled a hard-gate success. Cleanup passes: +owned processes stop, the disposable Compose project is empty, private files, +environment and lock disappear, and application ports are free. Only sanitized +receipt/report/screenshot artifacts are retained. Artifact/graph distribution +verification and real API boot are separate evidence; this demo runs the normal +Release build output and does not claim modified-library or publish-folder +execution. Real PR-head CI and whole-job budget qualification remain pending. + +#### Final completion-budget scan qualification + +After the second full review and the completed 3,043-case run, a source-only +performance correction replaces six whole-instruction walks for three owner +budget fields with the existing fresh field-name index. Exact declaring identity, +opcodes, private/instance declarations, permitted/forbidden owners and duplicate +write counts remain. The standalone canonical Fact opens the same disposable +detector scope already used by each mutation evaluation. No Fact, case, mutation, +restoration, production subject, filter, timeout or concurrency bound changes. + +Independent applied-diff inspection verifies both hunks and all 35 unchanged +mutation call sites/fixtures. CI-mode Release build has zero warnings/errors and +scoped formatting reports no changes. All eight canonical, actual owner-mutation, +independent instruction-index and corpus cases pass, zero failures/skips, in +110.92 seconds. Their names match the preceding complete-run receipt. The owner +mutation case records 109.69 seconds versus 186.35 in that earlier full cohort; +different cohorts/load prevent claiming an isolated causal gain or CI-job fit. +The closed 383-file source/artifact receipt is +`e39d6d9a101b8d5b56246f262dd946c8ec82206c75db9bfd603ce363a6610dbe`. +This is qualification-correction verification, not a third full review round. +Real exact-head CI must still qualify the complete unchanged job budgets. + +### P02b-4 local closeout (2026-10-18) + +**Local implementation and review complete; [PR #32](https://github.com/HodeTech/LearnStack/pull/32) open.** +All nine approved steps are delivered on `development`. Every step completed both fresh +independent review rounds and its verified correction checks. The full Step 9 +rounds and final qualification corrections are recorded above; focused checks do +not count as additional full rounds. Accepted ADR bodies/metadata and earlier +as-of receipts remain intact. + +| Step | Delivered | Implementation / two review rounds | +|---|---|---| +| 1 | Typed contracts, closed registries and ordinary authority ceiling | Complete / complete | +| 2 | Authoritative/vendor storage, exact grants and guarded bootstrap | Complete / complete | +| 3 | Immediate transactional submission, trusted stamping and committed admission | Complete / complete | +| 4 | Recoverable wakeups, independent pools and owned lifecycle/cleanup | Complete / complete | +| 5 | Existing transaction owner, fenced completion and atomic terminal MUST audit | Complete / complete | +| 6 | Cross-instance tenant capacity and quiescence-bound reservations | Complete / complete | +| 7 | Durable external prepare/execute/finalize and known-failure policy | Complete / complete | +| 8 | Durable UTC recurrence and recipient-bound tenantless fan-out | Complete / complete | +| 9 | Complete observation, nineteen enforcement owners, skill/distribution and regression | Complete / complete | + +LearnStack state remains authoritative; stock Hangfire carries only opaque wakeup +references. Production business and recurrence manifests remain empty. The actual +Program manifest/route census, context restoration, transaction/terminal witnesses, +capacity and external uncertainty, recurrence/fan-out, grants/RLS and real worker +proofs back the nineteen Implemented catalogue obligations. The catalogue records +221 Implemented rules: 131 Architecture and 90 elsewhere, with 254 Architecture +method declarations. Discovery-only alignment was not used as executed evidence. + +**Local validation.** CI-mode Release build passes with zero warnings/errors; +scoped formatting passes. The final complete non-Docker command before the last +test-only optimization passes 3,043 cases, zero failures/skips: 2,452 Unit, +410 Architecture, 177 HTTP Integration and four Contract. Its closed receipt is +`f6f01737022f2013483967ddbff89e06daa4abd2eea6dd1ffbeed7a7de80e3dd`. +The completion-budget correction receipt above qualifies the final changed +detector and unchanged case identities. Local command duration remains explicit +above; it is not substituted for the unchanged real CI job limit. + +The full Docker complement executes 2,428 cases, with three fixture failures +retained honestly in the first receipt. All three are corrected without changing +production code or test limits; twelve affected real PostgreSQL cases then pass +with zero failures/skips. The source is frozen separately for each run. No fully +current all-green local Docker rerun is claimed; the actual PR-head integration +job must execute the whole complement. Frontend typecheck/lint/build and all +1,616 guarded tests pass, zero skips/todos. The fresh real demo/browser/audit and +complete cleanup receipt is recorded above. Packaging checks qualify the actual +publish artifacts/dependency graph, both offline verifiers, replacement-source +kit and dirty controls; actual normal Release API/native-renderer boot is proved +separately by the fresh demo. No modified-library execution is claimed. + +All PR commit messages pass the actual strict hook. ADR lifecycle, relative +links/fragments, source/count/no-skip guards, workflow lint and diff checks pass. +The working branch remains `development`; protected stashes are preserved. + +**Accepted limits and next owner.** ADR-0059 permits a whole pool to wait until +actual work/cleanup ends; ADR-0060's bounded unsafe startup/unwind class can kill +the API process. Neither process exit nor lease expiry releases uncertain +external reservations. Phase 03 owns operator recovery permissions/routes and +privileged execution; Phase 04 owns actual media adapters/process-tree quiescence; +Phase 11 owns mapped readiness, supervision/dumps, retention and measured +production capacity. P02b-8 still owns the erasure inventory. These are the +Accepted workload boundaries, not undisclosed unfinished P02b-4 mechanisms. + +The next packet is **P02b-5 API authentication**, beginning with G10/G11/G12 +(client), G14 and G20 decision review. No authentication/session implementation +starts in this closeout. P02b-5–8 and the overall Phase 02b exit remain open. +Real exact-head seven-job CI, its unchanged duration ceilings and the maintainer's +PR review/merge remain separate; this local closeout does not claim them passed. + +#### PR handoff and current CI ownership + +[PR #32](https://github.com/HodeTech/LearnStack/pull/32) opens `development` → +`main`, based on `ed60157c14d33fad926fd201b49c08e2d24eed1f`. The locally qualified +implementation is committed at `199b033e`; this handoff adds only documentation. +The closed C# receipt above remains byte-identical after normal commit hooks. + +The PR's [live checks](https://github.com/HodeTech/LearnStack/pull/32/checks) own +current exact-head CI results, durations and downloadable artifacts. The initial +[run](https://github.com/HodeTech/LearnStack/actions/runs/39120117263) starts on +`199b033e`; a subsequent documentation push supersedes that unfinished run and +requires a fresh complete check set. No partial or superseded result establishes +final-head success. All seven required names and strict freshness remain enabled; +backend, integration and demo keep their unchanged twenty-minute job ceilings. +The maintainer owns PR review and merge; no merge is claimed here. + +#### Hosted CI qualification follow-up (2026-10-18) + +The completed [run 39120501520](https://github.com/HodeTech/LearnStack/actions/runs/39120501520) +at `2e1d227ad1e0150fcbdcbde8df6d68374dc2f682` is **failed**. Frontend, +meta, secret scan and OpenAPI pass. Backend and integration reach their unchanged +twenty-minute ceilings; backend's completed TRXs retain 2,452 Unit, 177 HTTP and +four Contract passes, with Architecture unfinished. Integration has actual early +native-supervisor failures as well as cancellation; no complete Docker TRX passes. + +The actual native preflight reports `collector_pipe` on the hosted kernel. +Zero inherited core limits do not qualify a piped collector. Earlier topology +failures may race that refusal, but their precise endpoint states are unrecorded. +[ADR-0062](../decisions/0062-native-crash-proof-ci-provisioning.md) proposes explicit +disposable-VM provisioning authority; it is not accepted or implemented. ADR-0060 +does not allow a failed precondition to authorize a host-wide setting change. + +The demo hits its separate sixteen-minute outer setup/proof budget during final +report handoff; its inner proof lasts 659.906 seconds. Twenty-seven clean report +pairs on disk do not repair the incomplete 26-row accepted receipt. Cleanup is +confirmed; the run remains failed. Independent corrections address repeated +architecture identity work and duplicate migration/API builds, preserving all +cases, assertions, complete filters and existing deadlines. Final exact-head +hosted success remains pending. The earlier local receipts and completed review +rounds retain their stated scopes. + +The demo correction is committed at `bc3691fb`: normal migration entry performs +one fresh Release API build before all unchanged EF chains consume that build, +and the demo launches the resulting API without a duplicate build. Nine executed +Makefile controls cover freshness, chain discovery/order and sticky failures. +The guarded frontend suite passes 1,625 cases with zero skips/todos; typecheck and +lint pass. A fresh Git clone at that commit completes the actual CI-mode demo in +658.115 seconds: setup 71.168 seconds, proof 575.766 seconds and confirmed cleanup +10.686 seconds. All 27 accepted report pairs and nine screenshots are present; +maximum normalized gzip JavaScript is 106,574 bytes, CLS is zero and all 27 +accessibility scores are one. Nine LCP medians remain advisory warnings. Owned +processes/containers, private configuration and locks are removed. This local run +overlaps Architecture CPU work and does not establish hosted budget fit or new +manual accessibility evidence. + +The first census correction completes the unchanged non-Docker filter with 3,043 +passes and zero skips: 2,452 Unit, 410 Architecture, 177 HTTP and four Contract. +Every case identity matches the preceding full run. Its closed 383-file C# receipt +is `c367357d21cf39ae2d339b0d166651a5969891cb1d6c55a4c1a7bbaad22dc9e0`. +Local duration is 1,565.200 seconds; this is not a passing twenty-minute CI claim. +A subsequent measured-cost correction uses fresh per-evaluation instruction/name +indexes while retaining exact identities, opcodes, duplicates, all original +mutation controls and independent raw-traversal comparisons. It additionally +requires the actual authority detector to reject an unrelated detached target. +Plain fixture setup SQL uses the same real PostgreSQL through an owned nonpooled, +non-enlisting connection; the roles script retains its actual `psql -f` path. +The four added transport rows and 311 existing role/guard/migration/provider cases +pass together (315 passes, zero skips, 73.715 seconds). They verify actual roles, +ambient isolation, intact batches, rollback and observed physical-session exit. +The short server-cancellation row does not prove expiration of the helper's own +thirty-second deadline. Independent targeted source reviews find no blocking or +major defect; they are correction checks, not another full Step 9 review round. +The latest ten selected Architecture cases also pass with zero skips in 390.999 +seconds, including actual authority/application-source/runtime mutations, exact +raw/index parity and the catalogue/Docker-trait controls. Their requested case +identities match exactly. These and the 315 PostgreSQL cases close the unchanged +385-file C# receipt +`919b1ef74b5b6d456abd628ac6e664f5f61fbd9c6184fde9737234a219dd259c`. +The Release build has zero warnings/errors; scoped whitespace formatting is clean. +PostgreSQL qualification overlaps Architecture CPU work; these subset timings +are not causal speedup measurements. Final hosted full-filter results remain +pending; no complete current Docker run or seven-check success is inferred. + + +##### ADR-0062 revision and read-only baseline (2026-10-18) + +The maintainer's review requests changes; it is **not approval** of ADR-0062. +The revised [proposal](../decisions/0062-native-crash-proof-ci-provisioning.md) +selects a dedicated native-proof VM, verified fixed-pattern setup without +restoration, and complete native/ordinary Docker partitions behind the existing +fail-closed required result. It preserves seven required names and each existing +twenty-minute execution ceiling. Host changes, the partition and its launcher +remain unimplemented pending approval. The unmeasured 17:30/150-second allocation +is withdrawn; actual fit remains a qualification gate. No Accepted ADR body or +protection setting changes in this proposal pass. + +Two fresh independent targeted proposal reviews cover governance/authority and +CI/process/coverage ownership. Both find no Blocker/Major; the first review's +container-versus-VM wording is corrected. The final CI review has no remaining +finding. These are proposal reviews, not a third full Step 9 round or hosted +qualification. Private research also executes an isolated unprivileged +.NET 10.0.10 nondumpability spike against the existing file collector: every exec +resets the flag, per-child set/readback succeeds, actual FailFast gives SIGABRT +without cleanup markers, and the benign twin keeps both. No pipe is installed or +exercised; the pre-managed startup interval is not qualified by this experiment. +The ADR records that narrower alternative and its boundary rather than claiming +host mutation is technically unavoidable. + +[Run 39131069558](https://github.com/HodeTech/LearnStack/actions/runs/39131069558) +measures source `0fe0db2b5b584d141fc2c37aeeaf102f8ba0781c` with read-only observation +and the unchanged complete filters. Its PR merge checkout is +`c705ea2eaa39df1c1ccafc0ee67b615b573383a1`; artifact metadata ties it to that source. +There is no provisioning, changed collector, new partition or shortened deadline. +The actual observation classifies `systemd_coredump`, four CPUs, VM present, +container markers absent, noninteractive sudo available, writable proc mount but +no caller write access, inherited host soft core zero/hard unlimited, and an +empty readable all-state Docker baseline. These are closed observations, not +exclusive-VM attestation, successful-write evidence or child-limit qualification. + +The full Docker command is canceled at the twenty-minute job ceiling. Console +retains 629 recognized completed rows: 600 passes and 29 failures. Six direct failures report +native supervisor refusal; 23 phase failures comprise fifteen exact pipe refusals +and eight membership failures. The latter's endpoint states are still unknown; +do not relabel them. Ordinary completed rows continue until cancellation, but no +complete Integration TRX exists; three zero-selection assembly TRXs do not supply +that missing evidence. The full non-Docker command also reaches its ceiling after +16:21 in tests and 3:52 setup/format/build. Its final TRXs confirm 2,452 Unit, +177 HTTP and four Contract passes with zero skips; Architecture retains 346 +completed passing console rows but no final TRX. No complete Architecture/job +result or budget fit is inferred from those partial rows. + +Meta, secret scan, OpenAPI and demo pass. The actual demo retains all 27 accepted +report pairs, nine screenshots, maximum normalized gzip JavaScript 106,551 bytes, +CLS zero and all 27 accessibility scores one. Setup is 173.023 seconds, inner +proof 653.561 seconds and confirmed cleanup 12.742 seconds; whole job is 15:04. +This supersedes no historical failed demo receipt and supplies no new manual +accessibility claim. + +Frontend's hosted run has 1,564 passes and one source-census failure: the two new +CI-only Python files lacked explicit non-runtime classification. All nine new +Makefile cases pass on actual hosted Ubuntu. Commit `641ba365` adds only those two +exact paths; the unknown-Python rejection and runtime import graph remain intact. +The corrected local guarded frontend runs all 1,625 cases with zero skips/todos; +typecheck/lint pass. This local correction is not a passing hosted frontend result. +Final full-source CI remains red; native authority approval and independently +measured backend/Docker budget corrections still block PR closure. + + +A subsequent independent budget correction retains typed owners until the capacity +and recipient detectors select their actual targets, and formats recipient field +writers only for the two target-type families the detector actually consumes. +Global detached-target checks, exact assembly/signature/opcode/duplicate checks, +all existing mutation schedules and fresh per-evaluation caches remain intact. +Three standalone recipient checks use the same disposable evaluation scope. +An independent applied source review has no finding. The CI-mode Release build +has zero warnings/errors. All 29 selected capacity/recipient rows, raw/typed/index +parity companion and five corpus guards pass with zero skips in 191.804 seconds; +case identities exactly match the previous complete run. The unchanged 385-file +source receipt is +`c2521f3b2fe67289f796c9442e77f0977f96a9ec6272d2bfa39f7ef3e8d96c09`. +These local subset timings are not a causal speedup measurement or a full hosted +budget result. Other completed hosted cost evidence and repeated fresh-database +migration work remain assigned to P02b-4's active CI qualification; no case, +required check, timeout or production behavior is removed to obtain a pass. + +The complete unchanged non-Docker filter at `82d5307c` subsequently passes all +3,043 cases: 2,452 Unit, 410 Architecture, 177 HTTP and four Contract, with zero +skips and the exact previous case-identity multiset. The closed unchanged +385-file C# receipt is +`6ee75c41c60c1f4f48d7e096834b43f5e7c54574d2a90cc10d4e56acab0fdfe0`. +Local test-command duration is 1,221.712 seconds, excluding hosted setup and +artifact work; this does **not** qualify the twenty-minute whole-job budget. + +A separate local setup measurement invokes the existing fresh database CREATE, +all five real migration chains and DROP six times on one owned fixture. The cold +migration observation is 0.770250 seconds; five subsequent observations have a +0.296865-second migration median and a 0.317290-second CREATE/migrate/DROP median. +The first scratch run's empty receipt is rejected; after correcting only its +writer initialization, all fixed numeric stage rows and successful disposal are +verified, with no new container remaining. The CSV receipt hash is +`15cb39f977c200bb5374819dfa7b21610ba071f5899edfdea4b1feadb8b29c1a`. +This private measurement is not a committed regression, per-test seed/host/body +measurement, template-equivalence proof or hosted fit claim. No template path is +adopted from it. A collection-only parallelization is also rejected: distinct +databases leave shared mutable dynamic hooks and Hangfire filter restoration +exposed to races. The original serial proof semantics remain intact. + +A further narrow source-cost correction selects the three concrete completion +owner writes from the existing fresh field-name instruction index. Exact full +constructor identity, attached type, opcode, multiplicity, task constructor and +live instruction adjacency checks remain unchanged. Two independent targeted +source reviews find no issue. The CI-mode Release build has zero warnings/errors; +all twelve selected pool, metric, tracing, credential, raw/index-parity and corpus +cases pass with zero skips and unchanged identities in 106.375 seconds. Their +closed 385-file C# receipt is +`1da1475eb0d13b473007d10bbc69047903b7140c6a3a3081b8d814e9a115351e`. +This correction has focused validation; the complete 3,043-case receipt above +belongs to the preceding `82d5307c` source. No new full-run or hosted budget result +is inferred, and ADR-0062 remains Proposed pending maintainer approval. + +##### ADR-0062 acceptance and CI implementation (2026-10-18) + +The maintainer explicitly approves revised ADR-0062 at `51346376` and authorizes +implementation on `development`. Acceptance and ADR-0060's dated disclosure are +committed before dependent CI code. The exact required integration name remains +`backend integration (Testcontainers)`; it becomes a fail-closed aggregate of +both complete Docker execution jobs. The other six required names, strict +protection settings and twenty-minute execution ceilings remain unchanged. + +This follow-up implements one coherent CI boundary: closed provisioning and its +offline meta controls; native process/cgroup ownership, complete complementary +partition and result validation; then actual hosted qualification with complete +artifacts and measured failure-cleanup reserve. It receives two fresh independent +review rounds, with verified findings fixed and committed before final CI closure. +Existing native child assertions and all ordinary test cases remain mandatory. +No passing hosted result, new catalogue enforcement or completed implementation +is claimed by this acceptance. The earlier failed and source-specific local +receipts remain historical evidence; native separation alone is no budget proof. + + +###### Native CI implementation and local qualification + +Acceptance commit `c4e64b52` precedes this implementation. The closed provisioning +owner validates copied scalar workflow identity, actual platform/checkout, +container/VM evidence, empty all-state Docker baseline and eligible collector +before privilege. It independently compares actual reads and verifies either +no-change or the one fixed literal write. Sixteen offline copied-owner subprocess +controls pass; no developer host setting is changed by those controls. + +The native launcher owns finite execution/cleanup/export allocations, a delegated +non-root systemd unit and separate supervisor/work cgroups. The live supervisor +retains the work subtree until actual child join and an existing populated-zero +witness; unit disappearance is not proof. Ordinary Docker receives equivalent +process ownership on its separate VM, with no collector provisioning. The same +required integration name is an always-running fail-closed aggregate of both +successful, complete matching artifacts. The launcher's 203-second reserved tail is an allocation, not measured fit. +Twenty offline launcher/result controls pass, including actual subprocess, +setsid, live/missing cgroup, precise discovery IDs, sanitized TRX, incomplete +aggregate, bounded export and composed pre-privilege collector controls. Actual +hosted ownership, failure-tail +measurements and whole-job fit remain pending. + +The CI-mode Release build passes with zero warnings/errors. Nine selected source, +corpus and native predicate cases pass with zero skips; no canonical rule or test +method count is added. The source census covers qualified/partial identities, +shared traits, actual launch markers and transitive declared helper dependencies, +with planted dirty and clean controls. It does not prove arbitrary dynamic-call +analysis. The unchanged all-source snapshot covers 1,209 C# files; its snapshot-file +hash is `91e9be8b8c7fb77954ed70638168ace4dabd761283526d8b0b19a8eaa7120b27`. + +Fresh actual Release discovery selects 2,432 Docker case IDs: 31 native and 2,401 +ordinary, disjoint and complete; the other three test assemblies select none. +Twenty display-name collisions make a name-only set insufficient. The launcher +parses only bounded identities from private VSTest protocol diagnostics; raw +serialized theory inputs are not export artifacts. + +The complete local native partition passes all 31 cases with zero skips and exact +fresh-discovery IDs, including benign twins and actual same-child mutants over +real PostgreSQL. Its test interval is 166.889 seconds. The source snapshot stays +unchanged; no new container remains and all 22 pre-existing container states are +unchanged. Its TRX hash is +`1cc3004dd5d67f18a577088bc52a06cd80e91e7ed984037dca63eb20750e63f7`. +This qualifies the existing local native fixture, not hosted provisioning, +systemd delegation or either twenty-minute whole-job path. + +Guarded frontend validation passes all 1,625 cases with zero skips/todos; +typecheck and lint pass. Only the four new CI Python paths gain exact non-runtime +classification; unknown paths and runtime import coverage remain guarded. Seven +ADR-parser and five read-only observer controls, actionlint and changed-document +links/fragments pass. Two fresh follow-up review rounds and actual final-source +hosted qualification remain pending; PR #32 stays open and no merge is claimed. + + +###### Native CI follow-up review round 1 + +Commit `ee11bc94` contains the coherent implementation after acceptance +`c4e64b52`. Normal commit hooks pass and preserve all 24 validated source hashes. +Two new independent reviewers inspect the exact committed boundary through +process/authority and coverage/corpus lenses. Their four findings are verified +against that source before correction: + +- A failed optional preflight-log inspection drops the already bounded topology + facts from the exported reason. The exact topology form now permits an absent + preflight suffix while retaining its finite fields and refusal allowlist. +- A contradictory positive TRX skip counter is accepted and then erased by + sanitization. Counter parsing now checks nonnegative values, row reconciliation + and zero error/skip/incomplete buckets before projecting a file for export. +- Display-name-only interrupted records cannot distinguish 20 duplicate display + rows. The private incremental VSTest execution stream now supplies actual + assembly/case IDs, outcome and duration independently of final TRX. +- A statically declared instance-extension helper escapes the source closure. + Its planted dirty control fails the original detector; source method symbols, + reduced extension declarations and ambiguous candidates now retain the helper + edge. An unrelated same-named extension remains a clean control. + +The extension correction builds with zero warnings/errors and all seven selected +source/corpus controls pass with zero skips. This modifies only the Architecture +source file; all native fixture and production C# files remain unchanged from the +31-case local native proof. No extra rule or test method is added. + +Twenty-four corrected Python controls pass, including interrupted colliding IDs, +partial event lines, completed tails, missing/duplicate/wrong identities, truthful +failed rows, contradictory counters and missing optional diagnostics. The actual +pinned runner also executes the two existing pure native predicates with +`RunConfiguration.BatchSize=1`; each result arrives in its own StatsChange event, +and the real parser's five-field records exactly match both actual TRX rows. +Without that setting this small run delivers results only at Completed. Raw +execution diagnostics remain private. The setting changes event batching, not +case membership or assertions; nonempty projects receive distinct private streams +and zero-case projects retain complete discovery coverage. + +This narrow wire experiment and offline controls do not qualify the hosted unit, +provisioning, full ordinary partition or tail budget. The +[VSTest 17.12 configuration](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs) +and [result cache](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs) +are the pinned source basis. The corrected commit and a second fresh independent +review round still precede actual hosted qualification; PR #32 remains open. + +###### Native CI follow-up review round 2 + +The round-1 correction is committed at `779b6007`. Two fresh independent +reviewers inspect the complete acceptance-to-correction boundary: GPT-6-sol +xhigh reviews runtime/authority and GPT-6.1-sol xhigh reviews proof/partition +and corpus claims. The runtime review reports no verified finding; the proof +review identifies two additional issues, both verified before correction: + +- GitHub's absent job-services context serializes as `null`, while both owners + accept only an empty object. Both now accept exactly those two empty forms; + missing, malformed, non-object and nonempty service contexts remain refusals. + Copied-owner controls exercise the real absent-services input before launch. + All 17 provisioning and 25 launcher controls pass. +- A native call under a compiler-defined conditional symbol is invisible to + a parser with no defines. The source census now reuses the existing bounded + MSBuild symbol reader against the actual Integration Release project, + including SDK implicit defines. Whole-class and method-body controls under + `NET10_0` and `TRACE` reject unclassified callers; inactive `DEBUG` source + remains a clean control. The planted control fails the original parser. + +The corrected Release build has zero warnings/errors; all seven selected +source/corpus cases pass with zero skips. Scoped whitespace verification passes +with the separately reported workspace-loading warning. No native fixture or +production C# source changes in this correction, and no rule/method count changes. + +The actual complete 31-case native fixture also passes with private incremental +execution diagnostics and `RunConfiguration.BatchSize=1`. All five exported fields +for every result match the final TRX exactly, including fresh-discovery IDs; +there are zero skips, zero remaining new containers and unchanged states for +all 22 pre-existing containers. The TRX hash is +`03e826a07d94e06ec22f748ca80586eef1fe709de279a4914d29569c21729bf9`. +This is a local fixture/protocol receipt, not hosted systemd/provisioning, +ordinary-workload or whole-job timing qualification. Both full independent +follow-up rounds are complete; verified corrections and final-source hosted +qualification still precede PR closure. PR #32 remains open and unmerged. + +###### First hosted split qualification and meta control correction + +Source `6daa9a1c` is pushed normally on `development`; PR #32 remains open. +[Run 39140874785](https://github.com/HodeTech/LearnStack/actions/runs/39140874785) +starts actual hosted qualification. Independent API readback confirms all main +protection settings, including seven required contexts and strict mode, are +unchanged. + +The meta job passes all 17 provisioning controls, then exposes a synthetic-file +race in the launcher suite: a forked fixture child truncates its fake +`cgroup.events` before writing `populated 0`, while the owner reads concurrently. +The strict production parser correctly refuses the impossible empty snapshot. +The fixture now publishes the complete snapshot through same-directory atomic +replacement; production checks are unchanged, and missing/malformed-event dirty +controls remain. All 25 launcher controls pass after correction. An independent +focused review confirms the race and correction without broadening the owner. +This correction does not make the failed meta receipt pass; final-source hosted +qualification remains required. Other jobs continue to measure their actual paths. + +The native job builds successfully with zero warnings/errors, then refuses +before collector provisioning or test launch on `unexpected_crash_artifact`. +Its read-only environment receipt confirms an empty Docker baseline and +`systemd_coredump`; the retained receipt does not identify the matching file. +No legitimate source/build candidate is established, and no exclusion is added. +The scanner retains its exact roots, predicates, deadline and strict refusal, +using NUL-delimited private output to classify only a finite root/name category +in the refusal. Paths, contents and provider text are not exported. All 26 +launcher controls pass; an independent focused review confirms that nonempty +or malformed candidates still refuse. Actual hosted requalification remains +pending; this diagnostic correction supplies no passing native proof. + +###### First split-run result and bounded topology proposal + +Run 39140874785 completes with failure on source `6daa9a1c`, merge checkout +`853678c01c2c877e8bf5d7f81f559fc86ffbc9c4`. Backend reaches its twenty-minute +ceiling: complete TRXs contain 2,452 Unit, 177 HTTP Integration and four Contract +passes with zero skips; Architecture has no final TRX. Its 152 recognized passing +console rows do not qualify the remaining population or a complete run. + +Ordinary Docker discovers all 2,401 cases and records 503 distinct passing case +IDs before `deadline_exhausted`; 1,898 cases remain censored. There is no final +Integration TRX. Failure cleanup positively joins its owned workload in the +recorded 0.475-second path, with forced cleanup and no successful natural Docker +disposal claim. The aggregate correctly fails. This is measured failure of the +current arrangement, not permission to change timeouts or omit cases. + +Frontend passes all 1,625 cases and its ingress proof; OpenAPI and secret scan +pass. Demo's verified artifact contains 27 JSON/HTML report pairs, nine screenshots, +accessibility 1 throughout, CLS 0 and maximum normalized gzip JavaScript 106,553 +bytes. Its setup/proof intervals are 182.954/658.518 seconds; 10.647-second owned +cleanup passes. These successes remain specific to this source. + +Corrections `14584012` and `37ff4c59` are pushed normally after that run finishes. +[Run 39142456800](https://github.com/HodeTech/LearnStack/actions/runs/39142456800) +requalifies the separate meta/native corrections. Meta, frontend, OpenAPI and +secret scan pass. Native still refuses before provisioning/test launch; its new +closed reason is `unexpected_crash_artifact_docker_dump`. The actual matching +file/format remains unknown. No candidate is excluded, no host setting is +changed and no native hosted pass is claimed. + +A further read-only diagnostic invokes fixed `/usr/bin/file` only for the +private NUL-delimited candidate and maps its captured description to a finite +format label. It shares the original scan's twenty-second allocation. Every +candidate still refuses, including unknown formats and failed/timed-out probes; +no description, path or contents are exported. All 26 launcher controls pass, +and an independent focused review finds no defect. Actual classification and +native hosted qualification remain pending; this adds no collector authority +or file exclusion. + +Diagnostic commit `b4ee65b2` is pushed normally with the Proposed ADR-0063 +documents. Run 39142456800 is superseded/canceled after its independent +meta/native observations; no complete backend/ordinary result is inferred. +[Run 39143417261](https://github.com/HodeTech/LearnStack/actions/runs/39143417261) +again passes meta, frontend, OpenAPI and secret scan. Its native job builds +successfully but refuses before provisioning/tests on +`unexpected_crash_artifact_docker_dump_unknown`. Further fixed diagnostic labels +distinguish Docker storage regions and common formats/probe refusal, without +changing scan traversal, predicates or any failure decision. All 26 controls +pass and independent focused review approves. The candidate remains unexplained; +no allowlist, deletion, shard implementation or passing native result is claimed. + +Diagnostic source `d39233d5` starts +[run 39144033895](https://github.com/HodeTech/LearnStack/actions/runs/39144033895). +Meta, frontend, OpenAPI, secret scan and demo pass. Native still refuses before +provisioning/tests, now classified as an overlay-area `.dump` with generic binary +data format. Neither its contents nor image ownership is established by that +classification. Ordinary Docker records 146 passing case IDs before +`owned_completion_missing`; its failed receipt records forced cleanup and a +positive cleanup-ownership witness, not successful execution or natural Docker +disposal. No final Integration TRX exists. This early failure is distinct from +the earlier measured deadline exhaustion and remains under investigation. + +The next read-only diagnostic compares the private candidate's canonical path +with exact-ID-bound image-layer metadata from the fixed local Docker socket. +Only classic `overlay2` at the expected root is understood; stable inventory and +canonical paths are required. Only finite match/no-match/unavailable labels can +leave the owner. Every crash candidate still refuses, including a positive +image-layer match; no path is pruned or declared benign. A separate closed +workload-error fact supplements a failed ownership receipt without replacing its +failure or supplying completion evidence. Malformed ownership remains a failed +receipt; a planted control first exposes an unguarded cleanup shape and then +passes after the explicit dictionary guard. The provisioning owner is unchanged. +All 30 launcher controls, the unchanged 17 provisioning controls and seven ADR +parser controls pass. The independent focused source/proof review verifies the +corrections and reports no remaining finding. This is offline diagnostic +validation; actual hosted provenance, workload cause and full qualification +remain pending. Main protection is independently read back unchanged in full, +including strict mode and all seven required contexts. + +Source `f53c36fc` starts +[run 39145489321](https://github.com/HodeTech/LearnStack/actions/runs/39145489321). +Meta, OpenAPI and secret scan pass. Its native job still deliberately refuses, +but now positively binds the private candidate to a presently inspected image +layer: `unexpected_crash_artifact_docker_overlay_dump_binary_data_image_metadata_match`. +This proves that candidate's path provenance on that source, not its content or +earlier runs' files. Docker's +[classic overlay2 documentation](https://docs.docker.com/engine/storage/drivers/overlayfs-driver/#image-and-container-layers-on-disk) +distinguishes image lower layers from the separate writable container layer. + +The resulting applicability correction retains the first scan unchanged. Only a +fresh, stable exact-ID image snapshot containing that same candidate authorizes +a second scan over every original root, pruning solely verified existing image +`diff` directories. A complete matching snapshot after that scan is mandatory +before a clean return. Unsupported/unreadable metadata, non-directory layers, +drift, malformed output, budget exhaustion and all nonpruned candidates remain +failures. Each pre-launch and cleanup scan independently requalifies its own +snapshot and records only its verified-directory count. No filename, format, +overlay-parent or writable-container allowance is added; no file is deleted. + +All 32 copied-owner controls pass. They include real `find` traversal in an owned +temporary tree: the image file is first, yet a later writable/prefix/merged/work/ +volume artifact still appears; malformed and post-scan-changing metadata cannot +make the result clean. No developer Docker state or host collector is changed. +Focused review and actual hosted qualification still precede closure. + +The first fresh focused scope review approves `7cd07a18` without findings and +independently passes all 32 controls. A second fresh independent review follows. +Run 39145489321's ordinary job separately records `workload_internal_refusal`; +its failure remains red. The child now classifies unexpected faults solely by +a fixed owner-stage map and finite exception families, never exception text, +provider type names, filenames or stack output. The closed fact supplements +the failed receipt; no retry, passing result or completion witness is invented. + +The second fresh focused review approves `f53c36fc..e710bb61` without findings, +independently passing all 33 controls. On source `e710bb61`, +[run 39146395561](https://github.com/HodeTech/LearnStack/actions/runs/39146395561) +passes the complete hosted native job in 420 seconds. The verified artifact +contains 31 passing native cases, zero skips and exact fresh-discovery IDs; +all five completed-result fields equal the final TRX and every exported hash +matches. Actual setup/execution/cleanup intervals inside the launcher are +2.825/231.561/10.628 seconds. Ownership and natural Docker absence are positive; +forced cleanup is false. The collector changes from `systemd_coredump` to the +supported file policy with inherited zero limits. Independent pre/post scans +verify 78/94 image directories respectively; neither reuses the other's snapshot. +This qualifies that source's native job, not the complete PR or another source. +The same hosted meta job passes 17 provisioning and 33 launcher controls, +including actual GNU `find` traversal. Backend/ordinary fit remains separate. + +An independent source/filesystem investigation also verifies a normal VSTest +diagnostic-rotation incompatibility. It does not establish the cause of any +hosted ordinary failure. The inspected release sources +[v17.12.0](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/RollingFileTraceListener.cs) +and [v18.6.0](https://github.com/microsoft/vstest/blob/v18.6.0/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/RollingFileTraceListener.cs) +rename the current file to one expected backup before publishing its replacement. +The old reader rejects a shorter replacement; a reproduced exists/open race +throws `FileNotFoundError`. The package pin `Microsoft.NET.Test.Sdk` 17.12.0 does +not itself pin the SDK console; the observed local console is +`18.6.0-release-26329-109`. Release-source equivalence is not an assertion about +an unobserved hosted build commit. + +The reader correction owns generation zero before launch, retains its descriptor +and requires exact device/inode/backup continuity before each handoff. It drains +old tails, preserves partial lines and defers only a live rename gap; a final +unresolved gap, missing generation, unknown backup, truncation or replacement +remains red. The cumulative 64 MiB bound spans generations; handoffs are bounded +and descriptors close on success/refusal. All 38 copied-owner controls pass, +including actual rename/race, hidden generation and cumulative-bound controls. +Two real local pure predicate cases also pass with the pre-owned file and actual +SDK writer: exact discovered IDs and all five final-result fields match TRX. +This small append/protocol receipt does not qualify actual rotation, Docker, +hosted cgroups or whole-job fit. Fresh review rounds and final-source hosted +qualification remain pending for this independent reader correction. + +Reader implementation `9aad3c57` completes the first fresh review without +findings; the reviewer independently passes all 38 controls and verifies both +private append/protocol receipts. A further controlled local experiment fills +only its private pre-owned generation zero above 10 MiB, triggering the +unmodified SDK writer's actual normal rotation. The reader follows one handoff +across 10,613,523 bytes; both real predicate cases pass with exact discovered IDs +and all five result fields equal TRX. This is deliberate local feasibility, not +a reproduction of a hosted fault. The new reader still owes final-source hosted +qualification and its second fresh review. + +Run 39146395561's ordinary artifact is independently verified: 517 unique passing +case IDs belong to the 2,401-case expected set; 1,884 cases remain censored and +no final Integration TRX exists. Its error is `deadline_exhausted`, distinct from +the earlier internal fault. The 0.777-second cleanup positively witnesses owned +join but is forced and supplies no natural Docker-disposal success. The +integration aggregate correctly fails despite the separate native success. + +ADR-0062's reopen condition is met. Proposed +[ADR-0063](../decisions/0063-complete-bounded-ci-test-shards.md) describes one +backend-base VM retaining non-test gates and cheap non-Docker suites, four +Architecture method shards, ten ordinary Docker method shards and the unchanged +native VM. The two backend required names become complete fail-closed aggregates; +all seven names, strict protection and twenty-minute execution ceilings remain. +Actual Release discovery and exact method-filter rediscovery must prove every +theory row has exactly one owner, with independent aggregate recomputation. +Timing estimates are advisory; the proposed counts are not a hosted fit proof. +Repeated restore/build across fifteen base/Architecture/ordinary VMs replaces +two such VMs; the runner and queue cost is explicit. No shard code is implemented +before maintainer acceptance. The proposal names three implementation steps, +each requiring commit and two fresh independent review rounds. + +Two independent proposal reviews (GPT-6-sol xhigh and GPT-6.1-sol xhigh) +approve the revised ADR and index without remaining findings. They independently +check retained failure artifacts, the pinned method-filter contract, exact +bounded supersession, cross-VM population agreement, aggregate-side independent +assignment recomputation, backend-base non-test gates and the sixteen-VM cost. +Actual selection, ownership, reserves and fit remain pending implementation and +hosted qualification. This is proposal review, not maintainer acceptance. + +###### ADR-0063 review revision (2026-10-18) + +The maintainer's response reviews the proposal; it does **not** accept it. +ADR-0063 remains Proposed. The initial `3f5f09e3` proposal and its first two +reviews above are historical inputs, not reviews of this revision. No shard +implementation or ADR-0062 amendment is authorized yet; `development` is retained, +PR #32 is open and P02b-5 has not started. + +Fresh read-only API/artifact verification of +[run 39148006960](https://github.com/HodeTech/LearnStack/actions/runs/39148006960) +binds source `3553ff16` to merge checkout +`6de31fcce66d7f53e4d5d28fd163f65ab8af4d85`. Native succeeds in 465 job seconds: +31/31 cases, zero skips, exact fresh IDs/TRX fields/hashes, positive ownership, +natural Docker absence and no forced cleanup. The launcher-only intervals are +1.535/240.221/10.468 seconds; these exclude checkout/restore/build. Both fresh +reader correction review rounds are complete. Meta passes 17 provisioning and +38 launcher controls; frontend, OpenAPI, secret scan and demo also pass. + +Backend again lacks a completed Architecture TRX and reaches the configured +ceiling. Its API interval includes the cancellation/post-step tail; that does +not extend its twenty-minute configuration. Ordinary is a distinct failed path: +416 passing IDs, 1,985 censored cases, no final TRX, `owned_completion_missing` +and `workload_internal_membership_io`. Forced 0.459-second cleanup witnesses +cleanup ownership, not successful workload completion. The retained facts do +not identify an errno or establish the root cause. ADR-0062 owns that correction; +sharding cannot count it as a measured deadline or waive it. The integration +aggregate correctly fails despite native success. Protection API readback still +has the same seven app-bound contexts and strict mode; no setting is changed. + +Review dispositions are verified against the current tree and retained evidence: + +| Review topic | Verified disposition | +|---|---| +| Stale native/meta Context and reader follow-up | Corrected source-scoped history: meta race fixed; image provenance and reader both reviewed; native now passes. Earlier ordinary internal/completion faults remain separate. | +| Four Architecture bins, 152 versus 346 rows | Confirmed weak sizing, not a fit proof. First/current/earlier console prefixes are 152/294/346 with no final TRX. Ordinary's ratio cannot predict CPU-bound Architecture. Local maximum is not a hosted upper bound. | +| Sum/wall confusion and 782-second window | Corrected: the window includes discovery/fixtures/test lifetime; 203 seconds already includes 60 seconds upload. Historical sums do not establish spare capacity or ordinary-only wall time. | +| Backend-base sizing | Newly extracted complete suite intervals and pre-test walls appear in ADR-0063. Base candidate remains one VM; its new discovery/owner/export and isolated fit still require measurement. | +| Repeated fixture/discovery costs | Confirmed: SharedSchema spans 75 classes; split VMs repeat container/migration/seed and other fixtures. Missing per-fixture/CPU measurements are unknown, never zero. | +| Fixed counts and new ADR per tuning attempt | Revised proposal permits reviewed manual Architecture 4–6 / ordinary 8–12, at most twenty backend/test execution VMs; initial 6/12. No automatic/dynamic expansion or larger ceiling. | +| Process composition and independence | Require two genuinely different A/B assignments on the same source via two full attempts; bin renumbering cannot qualify. Fix actual dependence if exposed. | +| Collection versus process/VM alternatives | Existing Integration collection parallelism and Architecture's two-thread cap clarified. Separate processes on fewer VMs are a credible unqualified alternative; VMs are not required merely to isolate static state. | +| Non-Docker cgroup privilege | Explicit new bounded hosted-only transient systemd authority requires acceptance; child stays non-root. Non-Docker gets no Docker baseline/cleanup, crash scan or collector authority. | +| Plan, timing/default costs and selector bounds | Proposed tracked JSON/owner, versioned frozen weights with provenance, unknown-method census, explicit 60-second estimate and finite direct-argv/filter bounds; actual selection still independently rediscovered. | +| Aggregate outcomes/names/ceilings | Backend requires base/all Architecture; integration requires all ordinary/native. Each unique required name belongs solely to an always-running aggregate, each bounded to five minutes. All seven protection settings remain. | +| Rerun/attempt/artifact semantics | Single-attempt receipts with immutable artifact IDs and attempt-specific job verification. Failed/aggregate-only reruns cannot reuse old siblings; recovery is Re-run all jobs. | +| General control owner and meta ceiling | Proposed general `CI_Test_Shards_Are_Complete_And_Bounded`, Registered only at acceptance, then Implemented with actual Python/meta controls. Native/Hangfire and Docker-trait rules keep their own scope; meta stays five minutes. | +| Cost, queue, toolchain and filter identity | Public standard minutes are free; effective organization concurrency is unknown. Queue extends feedback, not running ceiling. Each receipt records actual console/adapter; actual xUnit FQN producer is cited. | +| Probe path, terminology, diagnostics | Full probe README named; base is project-owned, only Architecture/ordinary selector-sharded. Finite/private diagnostics remain bounded; raw provider output is not added. | + +The first fresh full revision review (GPT-6.1-sol, xhigh) approves with no +Blocker/Major/Minor finding. It independently verifies native result integrity, +base intervals, the current ordinary failure, source/merge identity and all seven +strict app-bound protection contexts. Its suggestions are incorporated: explicit +initial A/B algorithms and the 56-second current meta baseline with a provisional +30-second new-control allocation. Only aggregates propose +job-level `actions: read` beside `contents: read`; no execution token gains +permission. + +The second fresh full review (GPT-6-sol, xhigh) independently approves +`3553ff16..b3ee4ea6` with no Blocker/Major/Minor finding. It verifies the actual +A/B/retry contract, bounded new authority, retained API/artifact/timing evidence +and current primary toolchain contracts. Seven ADR parser controls, all 653 +relative links/anchors in changed documents, prose width and diff checks pass. +Both revision review rounds are complete. This is proposal review, not acceptance +or hosted fit; ADR-0063 remains Proposed and its implementation waits for the +maintainer's explicit decision. + +The revised three steps are specified once in +[ADR-0063 Implementation Notes](../decisions/0063-complete-bounded-ci-test-shards.md#implementation-notes): +actual selector/plan controls; bounded execution/phase evidence; workflow/aggregate +and two-assignment qualification. Each retains commit and two fresh independent +review rounds before advancing. New general-rule registration and ADR-0062's dated +bounded replacement/additive disclosure happen **only after acceptance**. Their +future implementation must update actual catalogue counts in the enforcement +change, not preclaim them here. Full execution fit and the independent ordinary +owner failure remain open qualification work; no runtime feature is added. + +###### ADR-0063 acceptance and implementation (2026-10-18) + +The maintainer explicitly approves revised ADR-0063 and its three implementation +steps and requests implementation. Acceptance binds +`b3ee4ea6`, with two fresh independent review receipts recorded at `2e1fedc7`. +It authorizes the initial base + six Architecture + twelve ordinary + native +plan, manual Architecture 4–6 / ordinary 8–12 under twenty execution VMs, +complete A/B attempts, confined non-Docker systemd ownership and aggregate-only +read Actions API authority. Seven required contexts, strict protection and +execution twenty-minute / aggregate five-minute ceilings remain unchanged. + +ADR-0062 Amendment 1 discloses the bounded replacement/additive seam without +rewriting its Accepted body/metadata. The new general CI rule is Registered; +implementation and actual final-source fit remain pending. This acceptance +commit precedes any dependent code. The three steps follow ADR-0063's canonical +plan, each with commit and two fresh independent review rounds. Verified owner +faults remain corrections under ADR-0062, not presumed consequences of sharding. +Work stays on `development`; PR #32 stays open and the maintainer owns merge. + +###### ADR-0063 Step 1 — complete selector plan (2026-10-19) + +Implementation follows acceptance commit `94f201ab`. The tracked JSON plan starts +with six Architecture and twelve ordinary owners, bounded by the Accepted manual +range. Its method weights retain artifact hashes, partial/local provenance and +unknown fixed costs; estimates never select membership. The actual discovery +protocol supplies assembly, case ID, display name and `FullyQualifiedName`. +The owner builds whole-selector A/B assignments, bounded direct filters and exact +per-owner/complete-union checks. Shared-fixture class observations support the +independence witness; they do not define the test population. The general +catalogue rule remains Registered until execution and aggregate enforcement ship. + +Fresh Release discovery identifies 5,475 cases: 3,043 non-Docker and 2,432 Docker, +the latter exactly 31 native plus 2,401 ordinary. Both A/B plans independently +rediscover all 44 generated project filters and match every assigned case field; +their Architecture, ordinary and shared-fixture co-memberships differ. This +local selection proof took 38.429 seconds after complete discovery, using SDK +10.0.302. It does not execute the assignments or establish hosted fit. The +assignment digests are +`8c4459848fae3279b4bc60b7c4614945a282db4862042ca6565c331e9e56f4ad` +and `8a113fac9c26a7595d930effcc1c307f030cd7ede1b8d38592c55cac7d55099c`. + +Real discovery/result reconciliation also exposed two existing identity edges: + +- An Exception-valued Unit theory advertised one discovered ID for three executed + rows. Primitive inline inputs now construct the same three exceptions inside + the test, preserving all assertions and producing three distinct IDs. +- VSTest's TRX logger escapes supplementary Unicode as UTF-16 code units. Result + validation binds assembly/ID first and accepts only the exact discovered name + or its exact forward XML representation. It does not decode arbitrary names or + relax the raw completed protocol. Unicode test inputs remain unchanged. The + [resolved VSTest source](https://github.com/microsoft/vstest/blob/e2f248338b5756f82d38c0d9551ff08bea0947de/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs#L652-L689) + supplies this transformation. + +Local validation: normal solution Release build passes with zero warnings/errors; +the corrected Unit suite passes 2,452 cases with zero skips and unique discovered +IDs. All those TRX identities reconcile: 2,450 names directly and two through the +expected-bound XML representation. This Unit run did not capture the completed +protocol, so it is not claimed as a complete new launcher receipt. The actual +TRX SHA-256 is +`0597c5be316aab7ddb50ca1754e3b7cd29f2d3e689ae8862fea4fddc1375b395`. +Five focused corpus checks pass. Twenty new offline controls pass in 0.183 seconds +and all 38 existing launcher controls pass in 17.340 seconds. The changed C# file +passes project format verification; the solution-format invocation reported a +workspace-load warning, so it is not a clean full-solution format claim. + +The new controls run in meta inside a finite 30-second allowance. Workflow test +matrices, new execution authority, aggregate/API enforcement and actual two-attempt +hosted qualification remain Steps 2–3. Step 1's commit and both fresh independent +review rounds must complete before Step 2 starts; their receipts follow here. + +**Step 1 review round 1.** A fresh `gpt-6.1-sol` reviewer at `xhigh` examines +`94f201ab..480fb1b4` across the standards and code-review lenses. One Major is +verified: disjoint case-ID populations could still split the same assembly/FQN +between original trait partitions. Manifest validation now refuses that conflict; +controls cover every non-Docker/native/ordinary boundary under both assignments. +All 21 controls pass, including the supported equal-FQN/different-assembly case. +The reviewer independently verifies the prepared fix, all five timing artifact +hashes, complete discovery/filter diagnostics and unchanged A/B assignment +digests. No other actionable finding is confirmed. + +The reviewer also replays a real focused VSTest protocol/TRX proof: all eleven +cases across both Unicode methods and the three corrected exception rows pass +with unique IDs and exact completed-stream fields. Its local execution took +1.082 seconds; this supplies the protocol boundary proof missing from the full +Unit run, without claiming cgroup or hosted execution qualification. The fix +commit precedes the fresh second review. Step 2 has not started. + +**Step 1 review round 2 and closeout.** A new `gpt-6-sol` reviewer at `xhigh` +independently reviews `94f201ab..0c97dd29` and approves with no actionable finding. +The reviewer verifies the committed partition refusal, all 21 new and 38 existing +controls, all 44 real selected-filter diagnostics, both exact unions and changed +co-memberships, all five timing-source hashes and both Unit identity/protocol +receipts. The current plan reports three ordinary selectors with unknown weights; +they remain owned and use the declared advisory default. Step 1 is complete with +both required review rounds and the verified correction committed. Step 2 now +owns bounded execution and resource/identity receipts; Step 3 owns workflow/API +enforcement and actual two-attempt hosted qualification. No hosted fit follows +from this closeout. + +###### ADR-0063 Step 2 — bounded shard execution (2026-10-19) + +After Step 1 closeout `357b97fd`, the existing CI execution owner gains the +finite base, Architecture, ordinary and native-shard paths. They use complete +fresh selector discovery, recomputed plan ownership, independent selected-filter +rediscovery before execution and exact completed-protocol/TRX reconciliation. +All new dotnet argv pass the plan's byte bound before spawning. Base retains +format and actual Hangfire publish/distribution/replacement controls; normal +Release builds remain a prerequisite in the Step 3 workflow arrangement. +Existing unsharded workflow paths remain active until that wiring ships. + +Non-Docker paths qualify the exclusive hosted Ubuntu 24.04 VM and use only the +owned systemd/cgroup process boundary. They perform no Docker census/cleanup, +collector read/write or crash inventory. The native setup writer remains +native-only; a read-only qualification call explicitly excludes Docker for +non-Docker jobs. Only the delegated owned unit enables CPU/memory accounting. +The supervisor retains positive join and empty-subtree evidence before reading +its work-cgroup CPU/memory peak. VM memory is separately sampled during polling: +its observed maximum includes other VM work and is not a continuous peak bound. +Container-specific peaks and uninstrumented fixture counts remain unknown. + +Receipts retain the actually selected SDK/console versions and binary hashes, +the loaded adapter's diagnostic version/path-bound binary hash, per-project +first-result and test-process intervals, discovery/selection, non-test gates and +result export intervals. Advisory estimates retain unmeasured fixed terms and +no invented wall bound. The existing finite whole-job/cleanup/upload budget is +unchanged; forced termination cannot become success. Workflow/API aggregate +validation of these receipts and actual hosted fit remain Step 3 obligations. + +The independent ADR-0062 membership fault is also addressed narrowly. Linux can +return ENOENT/ESRCH when an enumerated task exits before its cmdline read. Only +that candidate read, or a positive vanished-task recheck, is tolerated. An +enumeration fault, non-exit cmdline fault, unreadable live candidate cgroup or +outside testhost still refuses with finite stage/reason diagnostics. The +previous hosted receipt lacks errno/suboperation evidence, so this is not a +claim that ESRCH caused that run or that the hosted fault is already closed. + +Local checks: all 31 shard controls pass, including real owner selection/result +flow, negative pre-spawn selection/bound checks, non-Docker parent authority +controls, exit-race controls and metadata/resource shape checks. All 38 existing +launcher controls and 18 provisioning controls pass. The latter execute a +byte-verified copy through real temporary subprocesses, including the new +non-Docker runtime reader with no Docker/collector/sudo operation. The reviewed +provisioner source hash is updated for its explicit read-only Docker exclusion; +all other copied bytes still must match. Actual local SDK/console observation +and retained loaded-adapter diagnostics resolve SDK 10.0.302, console +18.6.0-release-26329-109 and adapter assembly 2.8.2.0. These controls and local +observations do not qualify hosted systemd, cgroups, Docker disposal or fit. + +Step 2's implementation commit and two fresh independent reviews follow before +Step 3 begins. The general CI catalogue rule remains Registered; no final-source +hosted success, complete packet CI or merge is claimed. + +**Step 2 review round 1.** A fresh `gpt-6.1-sol` reviewer at `xhigh` reviews +`357b97fd..17f9cd4f` and approves with no actionable finding. All 31 shard, +38 launcher and 18 provisioning controls independently pass. The reviewer checks +the authority split, independent pre-execution selection, exact results, +retained lifecycle/deadlines and honest resource/toolchain observations against +the Accepted decisions and primary Linux/systemd sources. This unprivileged +review does not supply actual hosted containment or fit. The second fresh review +is required before Step 3 begins. + +**Step 2 review round 2.** A new `gpt-6-sol` reviewer at `xhigh` reviews +`357b97fd..9d3c7b4f`. All 31/38/18 controls pass independently, but one Major +startup fault is verified: accounting can refuse before publishing readiness, +while the parent waits for that file without observing an already failed unit. +The original path can consume the execution allocation and hide the prerequisite +failure behind `deadline_exhausted`. Root independently reproduces zero terminal +unit observations on that path. + +The correction publishes a bounded closed startup-failure record before any +workload fork, observes terminal unit state during readiness and caps the entire +startup handshake at thirty seconds inside the existing execution budget. A +live but unready unit times out; a terminal unit refuses immediately with the +allowlisted cause. Failed startup still stops only its owned unit, starts no +business workload and cannot become successful ownership/cleanup evidence. +All 34 shard controls pass, including real leaf refusal before fork, prompt +parent detection, finite live-start timeout and retained failed-start cleanup. +The fix commit and fresh focused verification follow before Step 3 starts. + +**Step 2 correction verification and closeout.** The correction is committed at +`fc67d1f8`. A fresh `gpt-6.1-sol` reviewer at `high` approves the focused change +without findings. All 34 shard and 38 launcher controls independently pass; +42 supplemental assertions exercise malformed/absent startup diagnostics, +terminal/disappeared units, readiness races, earlier deadlines and cancellation +followed by actual parent cleanup. These unprivileged controls do not qualify +hosted Linux containment. Both full Step 2 reviews and the verified correction +are complete. Step 3 now owns finite workflow/API aggregate enforcement, corpus +reconciliation and actual two-assignment final-source qualification. + +###### ADR-0063 Step 3 — workflow and aggregate enforcement (2026-10-19) + +After Step 2 closeout `83be42d6`, the workflow connects the initial base + six +Architecture + twelve ordinary + one native execution arrangement. Every +execution remains on an exclusive Ubuntu 24.04 VM with a twenty-minute ceiling; +both always-running required aggregates retain five minutes. Their canonical +names and the other five required names remain unchanged. Only aggregates gain +job-scoped read-only Actions permission; execution gains no token authority. + +The aggregate source owner parses actual workflow YAML through the runner's +bundled Ruby/Psych safe parser, with duplicate keys, aliases, tags and complex +keys refused. No package is added. Literal indices/counts, unique protected +names across workflows, mandatory Release/execute/upload gates and narrow +permissions must agree with the tracked plan before execution. PR head and +actual merge checkout remain distinct and are related through the raw commit's +parent header, including shallow checkouts. + +Every aggregate uses current-attempt job API outcomes and immutable artifact +IDs/digests before independently recomputing complete selection/result unions. +Private bounded ZIP extraction allows only named sanitized files and refuses +paths, symlinks, duplicate entries and oversize evidence. Case IDs, five result +fields, complete TRX counters, non-test gates, actual toolchain hashes and +scoped resources are checked again. Native provisioning/crash/no-refusal and +natural Docker disposal stay mandatory. Missing, failed, skipped, stale or +forced work cannot become a passing aggregate. Partial reruns cannot reuse +previous-attempt siblings; recovery is Re-run all jobs. + +Source enforcement and its planted controls update the general CI catalogue +rule to Implemented; its mechanically verified count is now 222 Implemented, +131 in Architecture and 91 elsewhere, with 254 declared Architecture methods +unchanged. This does not close Step 3 or qualify fit. Implementation commit, +two fresh comprehensive reviews, verified corrections and two genuinely +different complete final-source hosted attempts remain required. No complete +P02b-4/PR CI or merge is claimed by local validation. + +Step 3 local validation passes 47 actual-owner shard/aggregate controls (34 +retained plan/execution controls plus 13 new result/API/topology controls), +37 launcher controls and 18 provisioning controls. The retired unsharded +aggregate's single test is replaced by the new complete API/result controls; +its duplicate discovery/workload/aggregate and CLI paths are removed. The +launcher descriptor-cleanup proof now exercises the real shard workload. +Five CorpusConsistency cases verify the new catalogue counts, and seven ADR +parser controls pass. Changed-document relative links and diff whitespace are +clean. A retained predecessor native artifact is independently downloaded by +immutable ID and its exact API ZIP digest is verified by the new safe extractor; +this is archive-format evidence, not final-source execution qualification. +No host privilege, collector, Docker mutation or Linux containment is exercised +by these local offline controls. The implementation commit and required fresh +reviews precede final qualification. + +**Step 3 review round 1 and verified corrections.** A fresh `gpt-6.1-sol` +reviewer at `xhigh` reviews `83be42d6..10e1b164` and requests changes with one +Blocker (cross-scope concordance) and one Major (mutable PR projection). All +47 shard/result, 37 launcher, 18 provisioning, seven ADR parser and five +CorpusConsistency controls independently pass on that reviewed source. Root +verifies both findings before correction. The cross-scope coverage gap is: matching manifests inside each aggregate alone +cannot prove that the two scopes agree on the same classification. Integration +now additionally requires the same current-attempt immutable base artifact that +backend already verifies. All producers' full manifests/toolchains are bound +transitively to that common witness; integration's union/count excludes base's +non-Docker cases. A planted whole-selector classification change is refused. + +A second verified API issue concerns old-event reruns: REST's pull-request +projection follows the current branch head even while the run's head SHA stays +at its original event. Root independently observes this on run 39148006960. +Verification retains immutable run head plus the raw checked-out merge-parent +relation, and binds the PR number without treating its mutable head as a run +snapshot. A control supplies a newer PR projection with the older valid event. + +The initial hosted run 39170247704 exposes one additional frontend failure: +the exhaustive product-source classifier does not yet classify the new CI +files. The five exact CI plan/owner/control paths are added to its existing +non-runtime inventory, with classification assertions. Unknown scripts remain +refused. The guarded full frontend suite then passes 1,625 cases in two +packages with zero skips/todos; lint and typecheck pass. No product behavior or +broad extension exemption changes. All 48 shard/result controls and 37 launcher +controls pass after these corrections. These local results do not qualify the +initial hosted execution or the final two assignments. + +**Step 3 review round 2 and final control corrections.** A fresh `gpt-6-astra` +reviewer at `xhigh` reviews `83be42d6..98ae41a8` and approves the source with no +new Blocker/Major. Independent checks pass 48 shard/result, 18 provisioning, +seven ADR parser, five CorpusConsistency and 19 targeted frontend cases. The +37-launcher suite first exposes an existing 200 ms fixture-start race; an +unchanged rerun passes, and a fixture-only 250 ms startup delay reproduces the +race. Root replaces that proof's timing assumption with actual first-result +and partial-next-event admission before deterministic cancellation, under a +separate five-second test guard. A delayed real child still runs, is actually +joined, preserves the exact completed ID and leaves incomplete JSON/no TRX. +Production execution and cleanup budgets remain unchanged. + +The second verified Minor is that non-native preflight checks but discards the +weekly image release. Receipts now retain its already validated OS/release, +CPU/kernel/virtualization values; aggregates validate and retain each producer's +observed identity independently, without inferring equal images from equal +labels or SDKs. Controls reject missing/invalid image evidence. The suites now +pass 49 shard/result and 37 launcher cases. + +The initial hosted run also exposes one stale environment-control assertion +that expects test filters directly in the former backend execution job. It is +adapted to the actual complete topology owner and verifies that the read-only +collector/Docker observer runs only before native execution. Non-Docker paths +gain no observation authority. All five environment controls pass. The other +four read-only observer controls remain intact. + +Initial source `10e1b164` supplies a real passing base receipt: 2,633 cases, +393 seconds whole job, actual SDK 10.0.402/console 18.7.0-release-26505-111, +43.811 seconds discovery/selection and 113.792 seconds non-test gates. +Immutable artifact 12152067468 and its API ZIP digest, exact results, natural +ownership and raw merge-parent relation are independently verified. This is +pre-correction base evidence only, not final-source/global fit. Initial +ordinary-10 reports two failed facade cases; their related three rows pass +locally in isolation and exact-shard diagnosis continues. A fresh focused +correction review and full final-source hosted qualification remain required. + +**Focused correction verification and hosted diagnosis.** A fresh +`gpt-6.1-sol` reviewer at `high` approves `98ae41a8..70c8fdea` with no findings. +It independently passes 49 shard/result, 37 launcher, five environment and +18 provisioning controls, plus malformed-image, distinct-image aggregate, +actual cancellation/reaping and topology-mutation probes. Both full source +reviews and those verified corrections are complete; actual hosted +qualification remains separate. + +Initial run 39170247704 finishes with all six Architecture producers, base, +native and eight ordinary producers passing. The backend aggregate passes; +integration correctly refuses failed producers. Four ordinary producers fail +five facade cases: ordinary-0 capacity completion, ordinary-3 grouped cleanup, +ordinary-9 common database outage, and ordinary-10 control timeout and +never-started admission. Their failure receipts report forced cleanup and +missing owned completion, not natural completion. Frontend and meta expose +the already corrected classifier and obsolete observer assertion above. +This predecessor run is not final-source qualification. + +An independent investigator runs the exact initial ordinary-10 assignment +locally: all 176 IDs match its hosted selection and pass in 212.449 seconds. +The three focused facade rows also pass. This macOS/SDK 10.0.302 evidence +does not close the hosted Linux/SDK 10.0.402 failures. No test budget, method +assignment, policy or outcome is changed on that evidence. + +To locate the next actual failure without exporting provider diagnostics, +the existing measurement receipt retains only fixed source codes for the +five affected facade source files and bounded line numbers, tied to an +already validated failed case ID. Raw stacks, paths, exception types and +messages remain private; missing frames remain unknown. Successful aggregate +validation requires no failed-location entries. A real two-failure probe +using the pinned SDK/adapter confirms the actual wire field and sanitization; +49 shard/result and 38 launcher controls pass. This diagnostic provides no +completion, containment or passing-test evidence. A fresh focused review and +subsequent full hosted runs remain required. + +The fresh `gpt-6.1-sol` / `high` diagnostic review approves +`70c8fdea..4a14a812` with no findings. It independently passes 38 launcher and +49 combined selector/aggregate controls, 18 focused privacy/boundary probes +and eight rehashed measurement mutations. Passing cases export no diagnostic; +missing or nonempty failure-location evidence cannot qualify a successful +producer. The next hosted source incorporates both full review corrections +and this independently verified diagnostic. Five failed facade rows and +complete final-source A/B qualification remain open. + +**Candidate `ec5b045a` hosted diagnosis.** Run 39172490912 incorporates both +verified full-review corrections and the focused diagnostic. Frontend and meta +now pass. Its native artifact 12153083206 independently verifies 31 passing +cases, exact results/hashes and natural ownership/cleanup in a 497-second job. +The five affected facade methods also pass all eight exact IDs in a task-owned +local Linux ARM64 / SDK 10.0.400 focus; this is not the hosted x64 toolchain. + +The hosted outage failure repeats. Its finite source locations identify the +post-pause all-heartbeat-fault premise, not a proven runtime cause. The +90-second case deadline includes startup and pre-pause work; stock heartbeats +wait thirty real seconds, and a failed transient attempt remains faulted while +the manual pacing clock is frozen. A new public admission rendering failure +has no retained source location under the original five-file diagnostic. + +The next narrow diagnostic adds that verified test basename and decodes only +its existing closed helper stage/detail, or the outage's existing bounded +elapsed/pause/since-pause durations and finite per-pool generation facts. +Extraction is limited to the two exact failed test identities, with unknown +values left unknown. No raw error text, path, provider value or free-form +state crosses the diagnostic boundary. These facts neither change test +outcomes nor satisfy ownership/containment. Root causes, focused review and +complete final-source A/B qualification remain open. + +The first fresh diagnostic review (`gpt-6.1-sol`, `high`) verifies one Major +in `ec5b045a..2b8d6cbe`: the pool parser expects an internal metadata property +that the actual record's generated text omits. All forty synthetic controls +pass, but reflection over the real Release record reproduces absent pool +details. Root verifies that actual output, removes the nonexistent suffix and +aligns the control with the real shape; an extra-field mutation remains +unknown. The corrected parser consumes all three actual record strings, and +all forty launcher controls pass again. No application record or runtime +policy changes. A new second focused review follows before publication. + +The fresh second `gpt-6-astra` / `high` review approves +`ec5b045a..30ef90d4` without findings. Forty launcher and fourteen aggregate +controls independently pass, alongside actual-record decoding, seven invalid +protocol/privacy probes and rehashed success-receipt refusal mutations. Root +also runs two deliberately failed pinned-xUnit scratch cases through the real +wire: the exact test names expose only their closed stage or all three real +record snapshots, both remain Failed, and the private canary is absent. + +Run 39172490912 finishes with 24 successful jobs and three failures: ordinary-9, +ordinary-11 and their required integration aggregate. Backend and the five +other required checks pass. Its longest Architecture job is 779 seconds; +the longest ordinary job is 683 seconds and base is 314 seconds. These +observations do not waive the two failed cases or qualify final-source A/B. +The next source publishes the twice-reviewed diagnostic without changing any +test, assignment, runtime behavior or bound. The live PR owns subsequent +source/run receipts until packet closeout. + + +The next full run, 39174286516 at `e0124baf`, finishes with 24 successful +jobs and three failures: ordinary-9, ordinary-11 and their integration +aggregate. The actual outage record now exposes all three original pools: +control reports a heartbeat fault, while external and transactional do not; +none is draining. The pause completes at 503 milliseconds and the failed +observation follows 89,497 milliseconds later. This rules out insufficient +post-pause allowance and prior drain for that observation, but does not +locate the two unfinished heartbeats. The independently hashed ordinary-11 +artifact instead identifies the capacity-control lost-checkpoint test; the +public-rendering case passes in this run. Its missing source location is +not evidence of any particular failed stage. + +Pinned source inspection confirms three separate native heartbeat threads. +A narrow owned Linux/Npgsql pause experiment returns every open, UPDATE and +disposal within 15.029 seconds; it does not reproduce the hosted stall or +qualify a total hosted provider deadline. The next diagnostic records only +heartbeat entries, attempt count and the closed lifecycle-wrapper phases +Created/Acquiring/Invoking/Disposing/Returned. These are non-atomic observations +of progress, not successful-cleanup, join or admission authority. Invoking +includes the stock provider's own connection acquisition, SQL and release. +No timeout, scheduler policy, retry, ownership or assignment changes. +The verified capacity-control basename joins the closed source-location map. + +Local validation of this observation includes the warnings-as-errors Release +build, 2,452 unit cases and three actual PostgreSQL heartbeat/capacity-control +cases, all without skips. The actual compiled diagnostic record is passed +through two deliberately failed pinned-xUnit wire cases: three pool details +retain their bounded phase/count facts, both cases stay Failed, and the +private canary is absent. The fresh `gpt-6.1-sol` / `high` and +`gpt-6-astra` / `high` focused reviews each approve `e0124baf..2c7d4300` +without findings. Both independently pass forty launcher and 49 combined +shard/result controls; the second also runs the fourteen result controls +separately and probes actual compiled phases, numeric boundaries and privacy. +The observation supplies no root-cause correction or ownership witness. +Actual hosted root causes and complete final-source A/B remain open. + +**Candidate `89fd8450` and native qualification corrections.** Run +39176455522 finishes with 22 successful jobs and five failures: ordinary-1, +ordinary-3, ordinary-4, ordinary-9 and their integration aggregate. All six +Architecture shards, base, native and the other five protected checks pass. +The independently hashed ordinary-9 artifact records all three metadata +heartbeats inside their first stock invocation, without a published fault, +89,553 milliseconds after the database pause. This narrows the observation +to the provider invocation; it does not distinguish physical acquisition, +SQL or provider release. An owned Linux ARM64 experiment using the hosted +SDK version, 10.0.402, returns paused pooled calls within 15.014 seconds and +fresh opens within 5.009 seconds. It does not reproduce hosted x64 behavior. + +The other three failed cases concern the lost capacity checkpoint ACK, +completion after row-lock expiry, and retained auxiliary cleanup. Their +original failure locations are absent from the previous closed map. Source +inspection also verifies a qualification race: a native hint can complete +without business admission while the bridge ACK holds the application row; +the committed ACK then leaves repair behind its accepted grace, longer than +the fixture's initial wait. A new real-PostgreSQL control deliberately locks +that row, observes the actual skipped native hint and zero business attempts, +commits the real ACK, and resends through the real stock provider. Exactly +one business execution and attempt complete. This proves the fixture gap is +reachable; it does not establish the cause of earlier hosted failures. + +Execution-focused fixtures now observe either their actual start signal or +the committed bridge ACK before supplying that additional native hint. A +started body need not wait for an ACK blocked by its own row lock. Existing +repair, lease, execution and cleanup bounds remain unchanged. Their explicit +finally blocks preserve the original body failure together with a cleanup +failure. This does not claim to cover every later implicit disposal fault. +All facade source basenames join the fixed diagnostic map. A thread-local, +synchronous observation adds PhysicalOpening around the actual connection +factory; it has no admission, retry or cleanup authority and does not flow +into child work. + +Local validation passes the warnings-as-errors Release build, all 2,452 unit +cases, eight actual PostgreSQL regression rows, five affected Architecture +boundary cases, forty launcher controls and 49 selector/result controls, +without skips. Two deliberately failed pinned-xUnit wire cases retain both +original and cleanup source locations and the three actual compiled +PhysicalOpening records, while private canaries remain absent. The earlier +full Architecture run passes 410 cases at `2c7d4300`/`89fd8450`; the five +focused cases cover the changed production boundary. Two fresh correction +reviews precede publication. Actual hosted root causes and the two complete +final-source A/B attempts remain open. + +Both fresh correction reviews (`gpt-6.1-sol` / `xhigh` and +`gpt-6-astra` / `xhigh`) approve `89fd8450..15d5161d` without introduced +findings. Each independently passes 24 storage unit cases and forty launcher +controls, inspects the actual wire proof and verifies the authority limits. +The second review separately confirms the same pre-existing fixture gap in +capacity admission, never-started admission and control-lock execution tests. +An adjacent audit applies the helper to those and the equivalent capacity +cleanup/stop/takeover, combined-pool and held-expiration execution premises. +Initial bridging, repair, future-due and fairness subjects keep their paths. +The additional eight test files change only start qualification and its +signals; all original assertions and bounds remain. Their fourteen real +PostgreSQL rows pass without skips in 84 seconds, and the warnings-as-errors +Release build remains clean. This adjacent correction receives its own +focused reviews before publication; it supplies no hosted failure attribution. + +The fresh focused `gpt-6.1-sol` / `high` and `gpt-6-astra` / `high` reviews +both approve `15d5161d..6f5025ce` without findings. Each independently traces +the actual-entry signals, lost-admission-ACK branch, stock hint and duplicate +admission fences, and verifies all fourteen distinct passing PostgreSQL rows +and the clean build receipt. Neither repeats the suites or claims hosted fit. +The original eight and adjacent fourteen regression rows supply twenty-two +local passing cases. Publication includes both twice-reviewed corrections; +the next full hosted A attempt, then a complete same-source B attempt, must +still qualify the final source. No required check or ownership rule is waived. + +**Candidate `c3564e08` and acquisition-path correction.** Full hosted run +39180047008 completes with 25 successful jobs and two failures: ordinary-9 +and its integration aggregate. All six Architecture shards, base, native, +the other eleven ordinary shards and the other six required checks pass. +The independently hashed ordinary-9 artifact identifies only the common +database-outage case. Control/external heartbeat attempts return their faults; +the transactional heartbeat remains inside PhysicalOpening after 89,293 +post-pause milliseconds. That phase includes the authority check, lazy-source +resolution and driver open/physical initialization; it does not identify a +specific internal driver stage. The failed run reports missing owned completion +and forced cleanup, not successful natural resource release. + +An unchanged actual Linux ARM64 fixture on SDK 10.0.402/runtime 10.0.13 passes +alone in 39.343 seconds. The exact independently verified ordinary-9 cohort +then passes all 207 actual case IDs, including that case in 38.127 seconds, +without missing/extra/duplicate/skipped rows. Both use the direct Docker bridge; +all their PostgreSQL containers are naturally absent after completion. These +local results do not establish the native hosted x64 cause or final CI fit. + +Independent pinned-driver source inspection and an owned socket-pair experiment +verify a separate acquisition hazard: the pinned +[read-buffer timeout setter](https://github.com/npgsql/npgsql/blob/v10.0.0/src/Npgsql/Internal/NpgsqlReadBuffer.cs#L49-L57) +truncates a positive sub-millisecond budget to socket timeout zero. The actual +pinned read buffer stays held +past that budget until its exact owned peer sends a byte; the same buffer's +asynchronous cancellation source cancels a real asynchronous socket read. +This is source-level evidence, not a reproduction of the hosted open path. + +The stock synchronous factory now joins the guarded source's supported +asynchronous acquisition, retaining its actual completion and existing budgets. +The shared physical-role initializer's query/disposal awaits are context-free. +No vendor SQL, role grant, timeout, owner, admission, retry or assignment changes. +An actual-driver control holds its asynchronous physical initializer: the factory +cannot return early or dispatch through a caller's deferred synchronization +context, and a planted synchronous initializer refuses. A second actual-factory +control verifies the unmodified role guard on a fresh connector, a planted +NOBYPASSRLS refusal and restoration. Validation and two fresh correction reviews +precede publication; actual final-source A/B qualification remains open. + +Local validation passes the warnings-as-errors Release build, all 2,452 unit +cases and 24 actual PostgreSQL factory/role/heartbeat cases without skips. +Temporarily restoring only the old synchronous factory call makes the new +async-initializer premise fail; restoration of the correction is checked again. +Both restored factory cases pass, with no skip. +A separate Ubuntu 24.04 SDK 10.0.402/runtime 10.0.13 x64 process passes the +actual corrected outage case in 42.882 seconds. The local engine and child +PostgreSQL remain ARM64, so this cross-architecture experiment does not claim +native hosted x64 equivalence or root-cause closure. Its two PostgreSQL +containers are naturally absent afterwards, with exact owned cleanup verified. + +The first fresh review verifies the factory correction and identifies bootstrap +as the other production synchronous source caller. Owning its startup wait does +not remove the same acquisition hazard. The correction moves to their shared +`PrivilegedDataSource.OpenConnection` entry, preserving the authority check before +lazy resolution. Both direct/bootstrap-source and factory paths now receive the +same actual-driver initializer/context control. Bootstrap verification SQL stays +synchronous; neither all SQL internals nor the hosted root cause are claimed +corrected by this acquisition change. The central source correction is requalified +before its fix commit and the second fresh review. + +The central implementation passes the warnings-as-errors Release build, all +2,452 unit cases, 26 actual PostgreSQL source/factory/role/bootstrap/heartbeat +cases and both exact credential/bootstrap Architecture guards, without skips. +Restoring only the old driver call at the shared source makes both direct and +factory initializer controls fail their actual async-entry premise. These +controlled mutations are not passing regression evidence; the corrected source +is restored before the fix commit and follow-up review. +All three corrected source/factory cases pass again after restoration. + +The fresh `gpt-6.1-sol` / `xhigh` round approves `c3564e08..78c51320` +without introduced findings and verifies bootstrap's adjacent existing hazard. +After its central correction, a fresh `gpt-6-astra` / `xhigh` round approves the +combined `c3564e08..da8a5958` source without findings. It independently traces +both callers, actual driver failure/disposal, authority and role checks, and the +recorded positive/mutant/restored results. Both correction review rounds are +complete; no retrospective hosted root cause is certified. + +At this source freeze, complete final-source A/B CI remains a required exit +gate. [PR #32](https://github.com/HodeTech/LearnStack/pull/32) owns its subsequent +live source/run/attempt status and immutable API/artifact receipts. Dated records +above remain historical observations against their named source, not a substitute +for the PR's current qualification or the maintainer's review/merge. + +**Candidate `0634280b` and remaining execution premises.** Its full A run +39183839130 verifies the common-outage case on hosted Linux x64 in 39.170 +seconds. The API-hashed ordinary-9 receipt passes all 235 cases with natural +ownership/cleanup and no forced stop; the new source/factory theory rows also +pass in ordinary-10. This is positive current-source execution, not proof of +the predecessor's internal driver cause. Fresh discovery owns 5,479 actual cases. + +Ordinary-6 instead fails the native business-overrun/private-callback case +after 30.890 seconds at its body-entry wait. Its API-hashed artifact retains +that exact source location and a failing ownership/forced-cleanup result; +neither is accepted as successful qualification. Source inspection verifies +that this execution/cleanup subject and the admitted-renewal subject still +rely only on the initial bridge hint. Both receive the existing actual-start +or committed-handoff qualification before their entry wait. All original +assertions and deadlines remain; no runtime code, assignment or retry changes. +The separate terminal-backlog fairness proof retains its natural bridge path. +The run ends with 25 successful jobs and the ordinary-6/integration aggregate +failures; it is not a complete A receipt and no B rerun is requested. + +An independent remaining-premise audit inventories all facade entry waits and +adjacent native external subjects. Five external constructor/recovery-cleanup +rows also leave the repair grace at 60 seconds while waiting for entry under a +30-second startup token. Both normal routing and external recovery may skip +the actual ACK-locked row without provider entry. These execution-only subjects +receive an external-specific qualifier: actual entry short-circuits; otherwise +a committed vendor handoff supplies its current stored wake generation for one +real stock external hint. Provider/recovery, cancellation, accounting and final +state assertions remain unchanged. Intentional bridge/repair, fairness, +future-due, recurrence and no-admission subjects retain their natural paths. +This is a verified permitted interleaving, not a retrospective cause claimed +from the failed hosted artifact. Release warning-as-error build passes. Four +actual PostgreSQL business/locked-hint/fairness cases and six external +constructor/recovery/history cases pass, with seven corpus/Docker-trait guards; +all have zero failures/skips. Two fresh reviews precede publication. The next +final source still needs complete A/B qualification. + +Correction `65afb4d5` completes two fresh independent reviews: Round 1 +(`gpt-6.1-sol`, high) and Round 2 (`gpt-6-astra`, high) approve without verified +findings. Both independently trace the actual normal/recovery locks, stock +route, ownership, cleanup and unchanged subjects against the passing receipts. +Round 1 additionally verifies the live job API and immutable artifact hashes +for the source-specific claims above. These are completed correction reviews, +not a claim that either final hosted assignment has passed. + +**Candidate `39adff20` and owned completion witnesses.** Full A run +39185926530 finishes with 24/27 successful jobs. Ordinary-6 now passes; the +31-case native and 2,633-case base receipts pass with actual cleanup and +API-matching archive hashes. The two failing cases are ordinary-1's public +client-pool disposal proof and ordinary-8's grouped no-start/private-callback +proof; their API-hashed archives retain the failures. The integration +aggregate rejects the failed execution evidence. No B is requested for this source. + +The public case's exported result has no raw assertion message or mapped source +location, so its precise hosted assertion is unknown. Independent pinned-source +inspection verifies two missing synchronization premises: client connector +closure does not join PostgreSQL backend exit, and competing framework host +disposals need not join one another's service cleanup. The proof now observes +the actual captured application-source lifetime without disposing it itself, +requires a used, uniquely tagged pool and refused borrowing after disposal, +then boundedly observes only that pool's server sessions disappear. Another +connection's exit cannot hide a leak. + +The no-start artifact identifies its exact generation-snapshot assertion but +does not retain the observed tuple. Source inspection confirms that the +optional qualification hint may itself own the held callback; waiting only for +the bridge hint's success does not establish its native wrapper's return. +That case and the matching auxiliary-cleanup case now retain the optional hint +identity and await its actual stock success before the unchanged exact snapshot. +The callbacks remain held throughout. An independent sweep checks all eighteen +qualifier calls; the other sixteen already use sufficient actual owner/cleanup +or retained-only witnesses. Native snapshot and held-owner assertions remain +intact; runtime, assignment and retry behavior do not change. +The next final source still requires both complete hosted assignments. + +Local qualification passes a warning-as-error Release build, 35 actual +PostgreSQL public-site/native-owner cases and seven corpus/Docker-trait guards +with zero failures/skips. The public-pool case also passes alone. Removing +only child-factory disposal makes that case fail its bounded actual-completion +wait; exact source restoration, a fresh clean build and the isolated case pass +again. This planted failure is a falsifiability control, not passing suite +evidence. Two fresh correction reviews precede publication. + +Correction `18ba1700` completes fresh Round 1 (`gpt-6.1-sol`, high) and Round 2 +(`gpt-6-astra`, high) reviews with no actionable findings. Both independently +verify real lifetime/consumer ownership, tagged pool use, passive completion, +refused borrowing, native hint identities and held callbacks against the +source-specific passing and planted-failure receipts. The restored source is +clean. These approvals do not infer a missing historical assertion or replace +the next final source's complete A/B qualification, owned live by PR #32. + +### P02b-4 review corrections (2026-10-19) + +**Status: local validation and both fresh independent review rounds complete; +final-source hosted qualification remains pending.** Work stays on +`development`. These corrections apply the existing Accepted contracts and the +explicitly approved quota accounting below; no new job runtime, role, grant, +quarantine-release authority or ADR is introduced. + +#### Verified corrections + +- **Capacity visibility.** Transactional work parked in `reconciling` with an + unreleased reservation now makes unmapped `jobs` health unhealthy. One boolean + joins the existing complete immutable observation statement and snapshot; gauge + callbacks issue no SQL and acquire no new labels. Parking and reservation + retention remain intact. The actual PostgreSQL proof covers pending/live work, + peer recovery, empty-registry observation and the original invocation's late + positive no-start cleanup, which restores routability without another attempt. +- **Actual admission in checkpoint proofs.** The checkpoint fixture now invokes + `AdmitBackgroundJobAttemptCommandHandler` through the real pipeline instead of + copying its INSERT/UPDATE SQL. Bounded runtime options supply explicit attempt + deadlines. Recovery/fairness scenarios declare capacity for their sibling + histories; admission still locks/counts every reservation. The first run caught + three fixture scenarios trying to exceed the original one-slot declaration. + They pass with explicit fixture capacity; the initial failure is not green + regression evidence. The independent attempt observer also accepts an explicit + tenant, with positive tenant-B and tenant-A isolation controls. +- **Distribution qualification.** The verifier uses its reviewed checkout as the + manifest authority and requires published manifest copies to match. It checks + each source archive's pinned PAX commit as well as its trusted digest. Actual + binary/notice/source co-tamper controls must fail. Dapper notice versions are + pinned alongside the existing graph checks. The documentation distinguishes + archive identity and the four original shared binaries from a reproducible + upstream build or a whole-dependency-tree integrity claim. +- **CI refusal and fork shape.** GitHub may return an empty pull projection for a + fork run. The aggregate accepts it only with the API's explicit distinct fork + repository, while preserving exact run/attempt/head/workflow, raw merge-parent + and checkout bindings. Same-origin, malformed or substituted identities still + fail. Unexpected CLI/import/API-shape faults return a closed refusal rather than + exception text. Python bytecode is excluded from repository source inventory. +- **Fixture bounds.** Zero-value controls now cover all positive-only runtime + budgets. Held-COMMIT proxies in the capacity completion/no-start scenarios have + explicit two-minute lifetimes so their configured transport outlives the + scenario's bounded holds and cleanup. +- **Live corpus.** Isolation/security/observability and downstream consumers now + describe identifier-only typed submission, authoritative job rows and opaque + Hangfire hints. Retired base-class/rule examples no longer teach a live contract. + Catalogue/audit status headers reflect delivered enforcement. Front doors link + this phase's current status instead of copying Step 4–8 histories. Phase 03 + explicitly owns the audited quarantine-reconciliation design and its required + trigger/grant migration; no such authority is activated here. + +#### Dispositions without runtime changes + +| Examined concern | Verified disposition | +|---|---| +| Late renewal refusal cancels work | Existing lease/admission safety closes permission on uncertainty and prohibits reopening it from a late response. Probing before refusal would change that policy. | +| Cleanup queue overflow should clear its sticky fault | No production path exceeding the bounded 64 execution owners and 128 request slots was demonstrated. Clearing a retained-cleanup fault without a witness is unsafe. | +| Acknowledged COMMIT becomes a failed job after cleanup | The executor reads the commit gate's ACK and preserves definitive success separately from retained cleanup. Suppressing the coordinator exception would lose cleanup evidence. | +| Failed native thread startup should signal completed cleanup | Ambiguous `Thread.Start` failure deliberately retains ownership; catch entry is not a positive join witness. | +| Opaque startup refusal should keep its inner exception | Provider text is intentionally excluded. A finer closed diagnostic taxonomy is an optional operability change, not a demonstrated correctness defect. | +| Quarantined rows cannot currently be edited | Phase 03's operator surface and authorization are not delivered. The freezes preserve uncertainty; nonterminal does not promise an ordinary-role release path. | +| Consolidate historical trigger bodies | Versioned Up/Down snapshots must not read a mutable shared body. No historical migration is rewritten. | +| Duplicate reservation index | The full FK/history index and unreleased-only occupancy index have different predicates and purposes. | +| Native observation masks a Python error | GitHub's default Ubuntu run shell uses `bash -e`; a Python failure stops before the following `cat`. | +| The bounded shard control runs only one suite | Its entry point loads plan and result controls under the same finite budget; earlier native controls have separate ownership. | +| Old counts, amendments and prior CI failures should be rewritten | Dated receipts retain their original source/population. Existing ADR amendments already redirect the retired model. Accepted bodies and historical counts remain unchanged. | +| Fixed 31-second sleeps | The cited occurrences are unit-test manual-clock advances, not real sleeps. Held-callback negative windows test an explicit barrier, not readiness by delay. | +| Broad refactors, caching, extra labels or dependency-wide notices | No reproducible correctness/isolation defect was established. Detector/fixture decomposition, bounded allocation/polling optimizations and repository-wide packaging policy are not bundled into these corrections. | + +Observation-only diagnostic naming, aggregate failure-artifact convenience and +source-test reflection coupling do not change admission, durable state, audit or +qualification. They are not reasons to weaken existing fail-closed paths. + +#### Evidence availability and final qualification + +Run `39188256776` completed both layouts on source `1dbde1a3`. Each was independently +reconstructed while its complete archives were available. On 2026-10-19 the +attempt-A aggregate IDs `12159885492` and `12159366005` return HTTP 404, and the API +lists no attempt-A execution archives. Attempt B remains available; all twenty +execution archives and both aggregate ZIPs were downloaded and checked against +API digests. No deletion cause is inferred, and the current API cannot reconstruct +attempt A. Earlier local verification is not a promise of indefinite remote +artifact availability. + +The PR's ready-for-review claim was withdrawn while these corrections run. Final +qualification retains ADR-0063's two full attempts of the **same workflow run**, +with unchanged plan, required checks and ceilings. Before retrying all jobs for B, +retain A's twenty execution ZIPs, two aggregate ZIPs, API metadata/digests and +independent reconstruction. Recheck remote availability after B and distinguish +verification performed at the time from artifacts still downloadable today. +PR #32 owns the final source, actual outcomes and retained evidence location. + +#### Local validation and review gates + +The Release solution build passes with zero warnings/errors. Unit 2,455, HTTP +177 and Contract 4 pass with zero skips. The PostgreSQL checkpoint/admission/ +control run passes 334 of 335 cases; the new capacity fixture initially carried +an invalid lease/progress pairing. After correcting and rebuilding that test, +its complete parking/late-cleanup proof passes. Four actual native capacity +completion/no-start cases also pass, including lost acknowledgements. Thus all +339 distinct affected PostgreSQL cases have a passing applicable result; the +intermediate failed run is retained as failed evidence, not renamed as success. + +The real distribution baseline and 23 dirty/replacement controls pass. Combined +plan/aggregate controls 51, native environment 5, provisioning 18, native owner 40, +ADR parser 7 and focused frontend source inventory 19 pass. Full frontend +verification passes 1,625 cases across both packages with zero skips or todos. +Changed-document link inspection finds no new broken target; the catalogue's literal placeholder +`#name_lowercased` remains documentation syntax rather than a real anchor. + +Full Architecture verification passes all 410 cases with zero skips. Final-source +hosted qualification remains pending in PR #32; no skipped or forced-cleanup +result will be counted as a passing proof. + +**Fresh review round 1.** Two new independent reviewers examined +`1dbde1a3..df6e2761` across runtime/ownership/tests and tooling/CI/corpus. Both +approve the runtime and test corrections. One reviewer found five additional +live-corpus passages still teaching `JobParams`, payload trace metadata or +`JobActivator` authority. The isolation table, observability, pipeline guidance +and shared skill instructions now use the authoritative row and `JobExecutor`. +A scoped residual scan leaves only the explicit retired catalogue navigation and +an example owned by the separate Hub repository. The second reviewer independently +ran all 51 plan/aggregate and 23 distribution controls and reconstructed the +339-case PostgreSQL receipt union. No code defect or weakened assertion was found. + +**Fresh review round 2.** Two different independent reviewers examine +`1dbde1a3..bc5bf1c2` and the final documentation correction. Both approve with no +open actionable finding. They independently run all 51 plan/aggregate controls +and the actual distribution baseline with all 23 dirty/replacement controls; +one also runs seven ADR parser controls and verifies 36 added local links. Both +verify the remaining correlation delivery-table correction: authoritative rows, +delivery ownership and `JobExecutor` restore context, while Hangfire hints stay +opaque. They run no C# builds or hosted qualification; the local suites above +are separate evidence. All verified corrections are committed before freezing +the source for two complete hosted assignments. PR #32 owns the final hash, +actual A/B outcomes, independent reconstruction and current archive availability; +this local receipt does not claim those pending runs have passed. + + +**Qualification follow-up.** The first hosted run of `8cd789de`, +[39231264902 / attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39231264902/attempts/1), +exposes six failures in two ordinary shards. They share one test-only SQL helper: +it searches for the previous complete six-column output projection after the +capacity observation adds a seventh field. A local unchanged-source run reproduces +all five invalid-fact theory failures at that exact guard. This is a verified +coverage gap in the earlier focused test selection, not a passing qualification. + +The helper now identifies the unique terminal projection prefix and final output +suffix before replacing that projection. Every production CTE, hash arithmetic, +validity check and typed binding remains intact; the planted date/hash/history +mutants retain their assertions. The actual Release build passes without warnings +or errors, and the complete recurrence store suite passes all 110 cases with zero +skips, including all six affected cases and their mutant controls. The production +query is unchanged. Two fresh sequential focused reviews independently approve +`8cd789de..6bcc2b9a` with no actionable finding. They verify the unique cut, +unchanged production SQL, all caller/mutant assertions and both actual TRX +receipts; neither reruns .NET or claims hosted qualification. The failed hosted +run completes with 24 successful jobs, the two affected ordinary failures and +the correctly failing integration aggregate. It is retained as failed evidence. +Renewed complete A/B qualification follows the corrected source freeze; PR #32 +owns the final hash, actual outcomes and archive availability. + + +**Native fence proof follow-up.** On corrected source `12c79f38`, +[run 39233496115 / attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39233496115/attempts/1) +passes the six recurrence cases but fails one native final-fence expiry case. +The retained location identifies its strict `last_error` read. A controlled local +schedule waits for the next generation's actual bridge ACK before that read and +reproduces `Column 'last_error' is null`. The bridge intentionally clears this +transient diagnostic on successful pending-row handoff; the test was racing +that separate, valid operation after observing rollback. + +The fence case now observes the first real committed handoff and positively joins +only the bridge before releasing the held business handler. Business execution, +lease expiry, app-role row-lock fencing and control recovery remain real. Every +strict rollback/error/attempt/effect assertion remains unchanged; no nullable +alternative replaces the error assertion. Bridge repair has its separate actual +native proof. A fresh warning-as-error Release build succeeds; both final-fence +branches, that repair proof, all bridge cases and the retry-progress proof pass +32/32 with zero skips. The deliberate old-schedule failure is retained as a +falsifiability receipt. The hosted run ends with 25 successful jobs and the +correctly failing ordinary/integration pair, not qualified A/B evidence. Focused +independent review and complete final-source qualification remain pending. + +The first fresh focused reviewer finds a valid ordering gap in `f8c003a7`: the +staged child's parent FK already holds KEY SHARE, so the initial ACK's FOR UPDATE +can wait behind the held handler. The corrected test signals native body entry +before staging, asserts no child exists, observes the committed ACK and joins the +bridge, then opens the staging gate and waits for its completion. Cleanup opens +both handler gates. All original fence/rollback/effect assertions remain intact. +A fresh warning-as-error build and the same complete 32-case selection pass with +zero skips; the earlier passing schedule did not cover this ordering and is not +presented as proof against it. Focused fix verification and a new second review +precede another final-source freeze. + +The first reviewer verifies `2b626235` resolves that finding and approves. A new +second independent reviewer approves `12c79f38..2b626235` without findings, +checking both ACK/native-entry orderings, bridge/execution gate separation, +cleanup and every preserved assertion. Both inspect the actual 32-case TRX and +the deliberate null-diagnostic failure; neither reruns the suites or claims +hosted qualification. Both focused rounds and verified corrections are complete. +PR #32 owns the renewed final-source A/B results and retained evidence. No new +runtime code, source-selection rule, privilege or deadline is introduced by +these test corrections. + +#### Additional verification and evidence reconciliation (2026-10-19) + +**Status: all local corrections and both independent review rounds complete; +renewed final-source qualification pending.** +This pass retains existing ADRs, durable-state authority and phase boundaries. + +##### Previously qualified source and retained evidence + +[Run 39236406151, attempt A](https://github.com/HodeTech/LearnStack/actions/runs/39236406151/attempts/1) +and [attempt B](https://github.com/HodeTech/LearnStack/actions/runs/39236406151/attempts/2) +both pass all 27 jobs on development head +`62ad318cc79b1f3f4888c03158b158336bea6010`. The checkout SHA +`3104c0fc2d812bfacda4825594263cc339363556` identifies GitHub's generated PR #32 +merge-ref commit, not a development commit. GitHub's commit API identifies its +parents as `ed60157c14d33fad926fd201b49c08e2d24eed1f` and that development head; +the retained source/aggregate checks independently verify the binding. + +Each exact union contains 5,482 backend cases, zero skips: 2,455 Unit, 410 +Architecture, 177 HTTP, four Contract and 2,436 Docker, including 31 native. +The older 2,432 Docker count belongs to an earlier source and is not substituted +for this result. Both actual assignments differ, including SharedSchema groups. +Execution jobs take at most 809/777 seconds for A/B; all aggregates remain within +five minutes. The seven strict required contexts and protection readback agree. + +All 22 A archives and their API metadata were retained before rerunning all jobs +for B. Afterwards A's IDs return 404; B remains downloadable. The complete local +bundle `learnstack-pr32-evidence-39236406151.tar.gz` has 44 ZIPs, 40,756,752 bytes +and SHA-256 +`9630ede9052e7f20b1d9db18440a8a595030c519cf52daeed8a9d1644370e0db`. +Its `verify-retained.py` entry point is packaged inside the bundle, not under +repository `scripts/`. From its extracted directory, run +`python3 verify-retained.py /path/to/qualified-checkout` at `62ad318c`. +Independent reconstruction again passes both 5,482-case unions and checks the +different co-membership. This verifies captured API responses and archives; it +does not reauthenticate unavailable responses or rerun tests. The bundle is a +shared-workspace artifact, not a public GitHub download. New source still requires +renewed complete A/B qualification; this prior receipt is not proof of these +subsequent corrections. + +##### Verified scope and dispositions + +| Examined concern | Current verification and action | +|---|---| +| Eager dispatcher parsing breaks absent configuration | Existing null/empty/whitespace controls pass: Npgsql's builder supplies defaults, the lazy source remains uncreated, and mandatory resolution refuses with the named key. No production change. | +| Duplicate statistics-history filters are tolerated | Existing code rejects more than one. Zero is valid after intentional one-time removal. No filter-policy change. | +| Blank application settings reach a raw first-query error | The lazy application source calls its named validator before building/opening the pool. No eager validation added. | +| Pool worker bound lacks an independent discriminator | Add one 17-worker pool below the total-worker ceiling, retain the accepted 16-worker control, and test retained-bound arguments zero and seventeen. | +| Domain-event drain boundary lacks a direct unit proof | Add inclusive 256 and rejecting 257 controls with FIFO, repeated-collection and rollback-only assertions. Existing PostgreSQL rollback proofs remain. | +| Explicit Retry-After is overwritten | Preserve an existing delta/date value; supply the existing default only when absent or empty. | +| Cleanup wait's boolean is ignored | `Completion` is a Task, not Task<bool>; awaiting WaitAsync already requires successful completion. No weakened or discarded boolean exists. | +| Dependency/comment drift | Remove the unused audit-adapter MediatR reference; align its catalogue/coordinator description, Next patch comment, middleware XML summary and P02b-5 authentication owner. | +| Moving CI action tags and scanner admission | Pin all 39 uses to seven reviewed upstream commits; future updates require review. Go already uses its checksum database; additionally require exact module and go.mod hashes before scanner installation. Keep aggregate upload identity exact and reject a tag or substituted commit. | +| ADR comparison silently skips an unresolved base | Require the actual PR base SHA, push predecessor or explicit manual base, and refuse an unresolved base or failed diff. Require the SARIF artifact instead of warning when absent. | +| Plan-gated content-type count is unenforced | Confirmed pre-existing gap. The maintainer approves distinct nondeleted custom keys, shared revision slots, excluded card default and last-live-revision deletion releasing capacity; the shared writer must serialize count/insert tenant-wide. Approval precedes implementation. | +| Broken ADR-0038 anchor | Standards 13 already provides the exact `adr-amendments` HTML alias. The accepted record is not edited. | +| Historical SQL copies or loose-then-tightened policies should be folded | Up/Down snapshots preserve versioned rollout and reversal. Current canonical bodies have parity proofs; no historical migration is folded or made dependent on mutable SQL. | +| Vendor installer leaves search_path set | Pinned Install.v23.sql ends with RESET search_path. No session-setting change. | +| environment.json is unbound | The API-authenticated SHA-256 covers its entire ZIP, including this observation file. No independent qualification authority is attributed to the file. | +| Control cleanup limits are below the supported topology | At most 32 workers plus eight pools times four retained executions is 64; 128 request slots allow the documented cleanup boundaries. The proposed 160-owner premise exceeds the accepted topology. | +| Catalogue guards should source-parse integration methods | The architecture guard explicitly owns its compiled assembly and a repository-wide orphan check. All nine job integration owners are real discovered tests. Source parsing would reintroduce the documented conditional-compilation blind spot; no absent current owner was found. | +| Test reflection, real-time negative windows and canary naming | No bypass of a production boundary was demonstrated. Narrow two test names to their actual copy/closed-shape assertions; retain real gate/cleanup negative windows and native proofs. | +| Display locale, enum fallback and fifth public route | English is the accepted display fallback; the two-value enum is checked in domain/storage; served OpenAPI and its extra-route mutant already reject surface drift. No speculative refactor. | +| Audit diagnostics, slug helpers, tracker complexity and startup round trips | No incorrect durable outcome, isolation leak or unbounded admitted input was reproduced. Existing closed diagnostics remain; batching/helper extraction requires evidence beyond code similarity. | +| Terminal timestamp/transaction liveness symmetry | Existing event witnesses bind the fenced row and same live transaction under ADR-0046. Job witnesses have their separate ADR-0047 contract; copying their wider shape is not an established event defect. | +| Unused assert-tests-ran helper and FailureDescriptor constant | The first remains a source-inventory subject and its cited dated receipt is historical. The second documents the storage descriptor ceiling. Neither silently bypasses the current CI owner. | +| Broader refactors, generated-file headers and recurring protection recorder | No current contract failure established. Do not hand-edit generated output, add a recurring automation or expand this correction into unrelated extraction work. | + +Phase 03 retains first production definitions, audited operator recovery and any +new terminal caller census. Phase 04 retains real media capacity/limit consumers; +Phase 06 owns the Studio audit-config writer and public error experience. Phase +11 retains mapped readiness, supervised deployment/dump policy, retention/purge, +connection-pooling qualification and production/browser operational diagnostics. +These are existing owners, not delivered features of this correction. + +The warning-as-error Release solution build passes with zero warnings/errors. +All 2,463 Unit cases and five compiled corpus guards pass with zero skips, as +does the actual production-manifest test. The 51 combined shard controls, seven +ADR lifecycle controls and seven new supply-chain controls pass. The real scanner +installation verifies both pinned sums and its resulting Go module metadata; +actionlint accepts the pinned workflow. The quota proposal remains non-runtime +and was awaiting the maintainer's accounting choice at this source. + +**Additional review round 1.** Two fresh independent reviewers examine +`62ad318c..cd69bbc6` across backend/contract tests and CI/dependency/evidence +boundaries. The backend reviewer runs 70 focused cases, zero failures/skips, +and identifies one valid documentation mismatch: Standards 09 still calls thirty +seconds unconditional. It now describes the absent/empty default and preservation +of an explicit value. The CI reviewer independently verifies all seven upstream +commit identities, 51 shard, seven lifecycle and seven supply-chain controls, +actionlint and both retained historical 5,482-case unions. These are separate +local checks, not qualification of the new source. + +**Additional review round 2.** Two different fresh reviewers examine +`62ad318c..abd5320b`. Both approve without a correctness/security finding. +The backend reviewer runs 111 focused unit/configuration/corpus cases, zero +failures/skips; the CI reviewer again runs all 51 shard, seven lifecycle and +seven supply-chain controls and actionlint. The latter independently verifies +official action identities, both Go sums, the historical merge parents and the +bundle hash/implementation, but does not rerun its offline reconstruction. +An optional new weekly Dependabot schedule is removed after scope review; exact +SHA admission and its mutation controls remain. Parent verification also passes +177 HTTP and four Contract cases, zero skips, and complete format verification. +All 512 relative links in the changed documents resolve, including HTML aliases. +No reviewer claims full hosted qualification for this corrected source. + +**Quota acceptance.** The maintainer explicitly selects the proposed accounting +on 2026-10-19; its +[accepted rule](phase-04-cms-media-pages.md#content-type-quota-accounting) +precedes the shared-writer change. No new ADR or unapproved counting policy is +introduced. Runtime implementation and its two independent review rounds follow. + +**Source-inventory qualification failure.** On `617ed087`, +[run 39250697987](https://github.com/HodeTech/LearnStack/actions/runs/39250697987) +passes frontend lint and production build, then fails its real genericity census: +the two newly introduced Python CI tools lack explicit non-runtime ownership. +The failure identifies `scripts/install-leakwatch.py` before reaching the second +new entry. Both exact paths are added alongside the existing CI tools, with +positive classification controls; unknown Python files still refuse. The full +guarded frontend run then passes all 1,625 cases in both packages, zero skips or +todos. The earlier focused frontend omission is a real verification gap. The +failed run is cancelled after that failure because the approved quota also +changes its source; neither that run nor its interrupted jobs qualify A/B. + +**Quota implementation and local proof.** The shared registration writer now +acquires the tenant-wide quota lock before its concept lock, then checks distinct +nondeleted custom keys and inserts on the same ambient transaction. Revisions +share one slot, the built-in card is excluded, and the last live revision's +tombstone frees its slot. Unlimited feature/numeric grants bypass the ceiling; +zero admits no new custom key. The explicit `limit_exceeded` mapping returns 403, +preserves the limit key/allowance in field errors, records Denied audit outcome +and is permanent in the existing job failure taxonomy. No migration, new default +entitlement or deletion/restoration authority is introduced. + +Full Unit passes 2,471 cases, zero skips. The PostgreSQL quota/default/publication +selection passes 41 cases, zero skips; the final seven quota cases also pass after +the controlled mutation is restored and rebuilt. A temporary removal of the real +quota advisory lock makes the actual advisory-wait proof fail; production bytes +are restored exactly before the positive rerun. The initial PostgreSQL run's one +failure was a fixture assumption that the Null provider supplied a finite plan; +it intentionally supplies all-enabled/unlimited under ADR-0045. The corrected +tests preserve that default and exercise the real resolver against an explicit +plan projection. That failed receipt remains failed evidence. Independent quota +and source-inventory reviews precede renewed complete hosted qualification. + +**Quota review round 1.** Two fresh independent reviewers examine +`617ed087..04b4e782` across transaction/isolation/concurrency and +API/audit/job/error/corpus/source-inventory contracts. Both approve without a +verified finding. They independently run seven PostgreSQL quota cases and 181 +focused Unit cases on current Debug binaries, plus all 19 genericity cases with +their result guard. Their initial stale Release selections are not current-source +evidence. The parent rebuilds the entire Release solution with zero warnings or +errors, then runs all 2,471 Unit and 41 quota/default/publication PostgreSQL cases +in Release: all pass, zero skips. A different fresh review pair follows before +source freeze; no hosted qualification is claimed by these local receipts. + +**Quota review round 2 and source freeze.** Two different fresh reviewers examine +`617ed087..d2c414ee` and approve without verified findings. They independently +confirm all new cases are present in current Release binaries before running +seven actual PostgreSQL quota cases and 181 focused Unit cases, zero skips. +All 19 genericity cases and the result guard pass; unknown Python files still +refuse. The contract reviewer verifies all 607 relative links/fragments in the +changed documents. No test mutation, disabled guard, schema/grant change or new +lifecycle authority remains. Parent Release build/format, all 2,471 Unit, 177 +HTTP, four Contract and 41 affected PostgreSQL cases pass, zero skips; complete +frontend remains 1,625 cases across both packages. The source is frozen after +this receipt for both complete hosted assignments. PR #32 owns the exact final +head, actual A/B outcomes and retained evidence availability; none is claimed +passed here before execution. + +### P02b-4 merge and closeout (2026-10-19) + +The maintainer merged [PR #32](https://github.com/HodeTech/LearnStack/pull/32) +on 2026-10-19 at **17:08:09 Europe/Istanbul** (14:08:09 UTC). +GitHub records final development source +`1261c38268ff194a047f987c4ee8ffdb68ab1382` and squash merge +`b81006c7af7d38f1587ecb3bf93dbcca16f353e0`, whose parent is previous main +`ed60157c14d33fad926fd201b49c08e2d24eed1f`. Source and squash merge have the +identical tree `9c2ad62ca821ff7c886553518eab50c28094a29c`; the direct tree diff +is empty. Development incorporates the main merge without switching branches or +rewriting published history. This closeout changes no runtime, migration, grant +or Accepted ADR. + +**Final-source hosted qualification is complete.** Both full assignments of +[run 39253376497](https://github.com/HodeTech/LearnStack/actions/runs/39253376497) +pass all **27 jobs and 5,505 backend cases per attempt**, with zero skips: + +| Assignment | Actual attempt | Backend case union | Cleanup | +|---|---|---|---| +| A | [Attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39253376497/attempts/1) | 3,062 non-Docker + 2,443 Docker | Natural, complete | +| B | [Attempt 2](https://github.com/HodeTech/LearnStack/actions/runs/39253376497/attempts/2), Re-run all jobs | Same complete union | Natural, complete | + +The non-Docker union contains 2,471 Unit, 410 Architecture, 177 HTTP Integration +and four Contract cases. Docker contains 2,412 ordinary and 31 native cases. +Frontend, meta, secret scan, OpenAPI and public demo/Lighthouse pass in both +attempts; the complete guarded frontend suite contains 1,625 cases. +The checkout/workflow SHA is GitHub's generated PR merge-ref +`d062b67ed79f9c85d46d8faab44189e20b959729`, whose verified second parent is the +final development source above; it is distinct from the later squash merge. + +Independent reconstruction checks both complete protocol/TRX unions, artifact +API digests, producer-job ownership, source identity and actual natural cleanup. +Both attempts use the same source, plan, manifest and actual toolchain, with +verified different co-membership including SharedSchema: 218/254 Architecture +and 992/1,085 ordinary selector groups change owner. Maximum execution-job walls +are **846 seconds (A)** and **812 seconds (B)**, below 1,200 seconds. Each +aggregate finishes below 300 seconds; backend/integration pre-upload processing +is 16.441/31.655 seconds for A and 11.347/17.068 seconds for B. All seven strict, +app-bound required contexts and the entire branch-protection configuration are +unchanged in the final readback. + +| Aggregate | Artifact ID | SHA-256 | +|---|---|---| +| A backend | `12187997537` | `9b34b0a92d55ecd74555224987e3bf11dbcc9680d0e5fb7e694f3823ecac7a41` | +| A integration | `12187354369` | `4eac0bacedd3f30e99472db97eb8cd20a44c7855bdd085a8d0b4927d57063e5f` | +| B backend | `12191355246` | `18b1f18c57cabe19ad07e9aa7b7890f1e33364bd3cc9697e906fa381b8488400` | +| B integration | `12191520422` | `0482a80e92d608f06f305ff9b2bd749df36f0ee44fc0366c90104f1fbd8565ee` | + +**Evidence availability has a narrower bound.** All 22 A archives and their API +metadata/hashes were downloaded and independently verified before B began. +Final qualification readback returns HTTP 404 for all 22 A artifact IDs, while +all 22 B archives remain available. No deletion cause is inferred; the current +API cannot independently reconstruct A. The retained review bundle contains +all **44 ZIPs**, captured metadata, source/hash manifests, both receipts and the +comparison: `learnstack-pr32-evidence-39253376497.tar.gz`, 40,974,306 bytes, +SHA-256 `028de8d8d2bc6584a90e84f16755187cd2c32d600c2e80d98ad3ea19e18ce98d`. +Its packaged `verify-retained.py` reconstructs both attempts offline against +checkout `1261c382`; that entry point is inside the bundle, not repository +scripts. This verifies retained integrity/results without reauthenticating +unavailable API responses or rerunning tests. + +The separate post-merge push +[run 39266220267](https://github.com/HodeTech/LearnStack/actions/runs/39266220267) +was queued when merge verification began. It is not counted as a completed +post-merge proof; its live result remains separate from the final PR-source +qualification and identical-tree verification above. + +**P02b-4 is closed.** All nine runtime steps in the +[delivery table](#p02b-4-local-closeout-2026-10-18), all three ADR-0063 CI steps +and verified review corrections are delivered. Their independent review rounds +and negative controls remain recorded above. The final corrections also enforce +the approved distinct-key content-type quota under one tenant-wide transaction +lock, preserve explicit Retry-After values and close CI dependency/diagnostic +verification gaps. Earlier dated receipts retain their pre-merge or failed state; +this closeout does not relabel them as successful final-source evidence. +Production job and recurrence definitions remain empty. + +**Next: P02b-5 API authentication decision pass.** Re-verify G10/G11, G12's +BFF-client choice, G14 and G20 before implementation: UUID claims/actor identity, +host/JWT reconciliation (including organization and claimless-token outcomes), +client/issuer/audience validation, an explicitly bounded authenticated read +surface, validated-subject rate limits and the agreed anonymous 404/401 rules. +The pass must reconcile the existing ADR-0036, Security Standards and catalogue +carriers before code. No new gate is accepted by this closeout. + +P02b-6 owns realm mappers, admin-only UUID attributes, warm-realm reconciliation +and token/TTL proof. P02b-7 owns BFF token custody, single-flight refresh, CSRF, +logout and studio/session behavior. P02b-8 owns LS0002, retained-store erasure +inventory, remaining carrier reconciliations and the Phase 02b exit. Phase 02b +therefore remains in progress. Operator recovery/privileged execution stays +Phase 03, real media adapters/process-tree proof Phase 04, and mapped readiness, +supervision, retention and production sizing Phase 11. + +**Documentation-only closeout validation.** Five Release corpus consistency +cases and seven ADR status/parser controls pass, zero failures/skips. All 1,002 +relative links/fragments in the seven changed Markdown files resolve. Added prose +wrapping, whitespace and residual checks pass; every dated delivery/review record +and every Accepted ADR file is byte-preserved against the final PR source. The +runtime suites are not rerun locally for these status/navigation edits; their +final-source qualification is recorded above. This closeout starts no next packet. + +## P02b-5 — API authentication + +### P02b-5 decision package (2026-10-19) + +**Accepted — 2026-10-19.** The maintainer explicitly approved revised +[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md) and this +five-step package together. G10/G11/G12-client/G14/G20 are Accepted. All work +stays on development, with commit plus two fresh independent review rounds +for each step. P02b-0–4 remain complete and merged; P02b-5 implementation begins +with the acceptance commit before dependent runtime code. + +**Maintainer review follow-up — 2026-10-19.** The revised contract below addresses +verified review findings. The earlier decision-review opinions remain historical; +this follow-up replaces their readiness conclusion. Both fresh independent +revision review rounds are complete; the dated acceptance record below records +the subsequent maintainer approval before runtime work. + +#### Problem statement and verified entry + +Deliver the API half of tenant authentication: validate a signed access token, +reconcile it with the independent host scope, attribute rejections through the +existing recorder, and expose one genuinely read-only authenticated production +operation with an independently checked host ceiling. Keep public rendering +independent of Keycloak, and keep role, +membership, realm reconciliation and session work with their named owners. + +The entry audit used `development` at `0e23cb14`, following the verified P02b-4 +merge. Three independent read-only audits checked HTTP/isolation, identity/client +boundaries and corpus/test ownership. Their facts were cross-checked against the +current tree; they executed no tests and made no runtime edits. + +A fresh read-only check also confirms the post-merge +[main CI run 39266220267](https://github.com/HodeTech/LearnStack/actions/runs/39266220267) +completed successfully at `b81006c7af7d38f1587ecb3bf93dbcca16f353e0`. +The earlier merge closeout retains its honest queued-as-of receipt. This check +starts no new workflow and is not a P02b-5 implementation test. + +| Verified premise | Consequence for this packet | +|---|---| +| No JwtBearer package, scheme, `UseAuthentication` or `UseAuthorization`; the resolver's reserved claim site supplies no claims | Configuration/DI checks and supplied factory attempts are not authenticated HTTP evidence. Use real signed tokens through the actual handler. | +| Two public controllers expose four GET/HEAD pairs; no protected production route | Add a real protected subject. Existing public census does not constrain future protected routes. | +| Application `AuthorizationBehavior` still delegates; `HostAndClaim` admits ordinary requests | Bound production routes and their transitive request dispatch before activating claims. No authoring command can be exposed during the window. | +| Membership reader denies everyone; row 10 asks about the host's organization | Row 10 stays 404. A matching Yoga organization claim takes row 9; it does not implement membership. Correct the older staging claim using dated errata. | +| Rejection record has only tenant, dimension, asserted UUID and authenticated bit; resolver failure only logs | Carry source/actor/correlation/trusted organization explicitly, call the existing recorder and retain its two operation keys. | +| Existing admission spends visitor 60/min and physical peer 600/min before classification | A later 600/min subject limit is an additional ceiling. It cannot establish independent throughput past these floors. | +| Keycloak 26.6.2 export has no custom mappers/scopes, a public web client and slug-valued tenant attributes; seed only polls readiness | P02b-5 qualifies the API contract with a controlled issuer. P02b-6 must independently deliver actual token issuance and warm reconciliation. | +| Framework authentication can return failure/NoResult without terminating an anonymous endpoint | A scoped credential-result gate must reject present invalid credentials even on public routes. | +| `BackgroundJobExecutionAdmission.ModeFor` selects physical ReadOnly only for public requests and two exact framework reads | Add the exact new authenticated query to positive read-mode selection. Do not label it public or use a query-name heuristic. | +| SDK `PUBLIC_GET_WRAPPERS` presently covers every generated GET path | Separate the exact public operations from the new authenticated contract during regeneration; preserve credential-free public transport. | +| Name-based telemetry redaction does not sanitize arbitrary exception messages | Token canaries must be absent from logs/spans/error captures, not merely response bodies or named properties. | + +#### Accepted decisions + +This table summarizes owner choices. ADR-0064 is the canonical contract; the +summary does not redefine its validation details. + +| Gate / choice | Recommendation and explicit cost | +|---|---| +| G10: identity | Scalar UUID `tenant_id`, stable admin-assigned `user_id`, optional scalar `organization_id`; opaque `sub` remains external identity. Reject empty/reserved actors and malformed/duplicate claims. No memberships array or realm-role authority. | +| G11: organization | P02b-6 issues Yoga's matching organization claim; P02b-5 proves row 9 with real signed test tokens. Tenant-only row 10, tenant-host organization row 7 and platform claim row 14 still fail until Phase 03 membership. | +| G11: claimless token | Preserve the validated actor for attribution while HostOnly still limits authority to public reads. Emit one fixed Debug diagnostic without claim text; protected read is 404. No new origin, error code or actor suppression. | +| G11: platform membership audit | Refuse row 14 with 404 but no durable tenant row when there is no confirmed host tenant. This explicitly replaces only its `+ record under T_j` clause; no claimed/sentinel tenant is fabricated for audit. | +| G12: API/BFF client split | Convert `learnstack-web` to the confidential PKCE BFF client in P02b-6; API pins its `azp` and `learnstack-api` audience now. Old API-client service-account tokens do not satisfy this user profile. API needs no client secret. | +| Token/key posture | RS256, exact tenant issuer, duplicate-free JOSE allowlist (`alg`, `typ`, `kid`), payload Bearer, stable actor, 30-second skew and one-hour maximum lifetime. Suppress raw JWT vendor diagnostics at all levels and replace them with closed outcomes. Old-configuration reuse cannot reaccept an observed withdrawn key; immediate session revocation is not promised. Issuance TTL remains G13/P02b-6. | +| G14: quota | Preserve existing early visitor/peer floors for every credential; add stable issuer+subject 600/min accounting before audit. Reduced-subject whole-chain proof plus separate actual-default boundary. Cost: NAT/BFF sharing can throttle users below 600/min; independent end-to-end 600/min is not promised. | +| G14: routable read | One GET `/api/v1/account/site`: own actor/resolved scope and existing live `PublicSite` data, non-public Off query, physical ReadOnly, no scope parameters. The query itself checks HostAndClaim and matching HostScope before any reader, even when future membership permits row 14. No authoring/private content or platform route. | +| G20: precedence | Early admission/unknown-host 404 precedes JWT work. Invalid present credentials on known hosts give 401 even on public routes. AccountSite absent credentials give masked 404 on tenant, organization and platform hosts; a scoped authorization result handler prevents a default 401. Rows 8/11/12 and authenticated header mismatches give `tenant_mismatch`; rows 7/10/14 membership refusal and anonymous mismatches give `not_found`. | + +The maintainer accepted these decisions, disclosure instruments and five-step +plan as one package. No additional permission question is needed for routine +implementation within that accepted scope. A genuinely new security or +cross-module decision reopens only its affected boundary before implementation. + +#### Document audit actions and acceptance instruments + +The pre-code work uses `implement-task`'s scoping/decision pass and `write-adr`. +The implementation additionally uses `add-mediatr-handler`, `add-audit-coverage`, +`add-architecture-test`, `add-integration-test`, `run-tests-locally`, +`update-glossary` and `commit-and-pr` where applicable. Each review uses +`standards-check` followed by `code-review`. + +| Carrier | Verified issue and required action | Owner | +|---|---|---| +| ADR-0064 and decisions index | New security contract starts Proposed. Move its row only after explicit approval; no inferred acceptance. | Decision pass / Step 1 | +| ADR-0036 matrix row 14 and recording prose | Conflicting audit targets are resolved by the named bounded supersession. Append its own dated disclosure; preserve Accepted body/metadata. | Acceptance | +| ADR-0036 staging table and 2026-09-02 erratum | Both omit that row 10 is membership-dependent. Add adjacent dated errata and a correction section in the same new Amendment, with evidence of falsity at entry; do not edit the earlier erratum. | Acceptance | +| ADR-0036 delegated claim shape and new attribution | Distinguish additive profile/claimless clarification from the preceding replacement and correction; no new context writer. | Acceptance | +| ADR-0040 Amendment 8 and ADR-0052 Decision/Context | Each receives its own dated disclosure of the bounded public-read mode-ordering extension to this exact authenticated query; ADR-0040 also records exact-type selection. Preserve bodies, public guarantees and the setter set. | Acceptance | +| ADR-0032 and ADR-0053/0054 | Preserve the canonical pipeline and coordinated ingress policy. ADR-0052 public host provenance/anonymous projection remain unchanged despite its named read-mode scope extension. | All steps | +| Architecture 09/13/14/28/30/33 | Reconcile memberships-array/role sketch, scalar active tenant, actor projection and middleware order; Architecture 30 also repeats blanket non-public 401 and the no-authentication status. Update that carrier with the catalogue/Step 4 activation. Preserve reissued-token selection, public transport and Phase 03 membership. | Steps 1/4/5 | +| Standards 02/04/05/09/10/11/20 | At acceptance, Standards 11 § Tenant Context names the additional exact ReadOnly query; Standards 04 distinguishes its outer masked refusal from the unchanged generic unresolved gate. Reconcile stable quotas, source-aware recorder labels and fixed Debug diagnostics, plus vendor failure events 1/3/7 and credential privacy. No SQL policy/grant change. | Acceptance / Steps 1–5 as mechanisms land | +| Standards 21 | Narrow blanket-401 row; authority rule has real behavioral owner. Register five ADR-0064 obligations and update canonical counters/statuses only with actual delivery. | Acceptance / Step 5 | +| Tenancy README, audit and permissions | Document AccountSite query/DTO, Off nonsensitive-query audit registration and no permission-sensitive disclosure before Phase 03. No new permission key. | Step 2 | +| SDK/OpenAPI / API route and response policy | Explicit account resource/site route; outer no-store applies even before early errors. Exact disjoint public/authenticated GET sets form an exhaustive union. AccountSite is never a public wrapper; bearer/session attachment stays P02b-7. | Step 4 | +| Glossary / `UserId`, `TenantContextOrigin` and resolver XML | Explain authentication/actor versus tenant authority and HostOnly claimless attribution; fix Identity domain ownership and obsolete bodyless-only resolver description. Implementation comments change only after approval. | Decision pass / Steps 1–3 | +| Phase 03 / 06 / 11 | Phase 03 consumes P02b sessions rather than owning their first wiring; preserve durable identity/permissions. Phase 06 owns the full browser journey; Phase 11 owns production IdP provisioning/edge/readiness. | Step 5 | +| Realm JSON, Keycloak README, seed | P02b-6 prerequisite receipt: attach audience mapper to issuing client, access-token-only API audience; admin-only identity attributes; preserve `basic` and actual `sub`; converge fresh/warm realms without deleting users or Hub realm. No realm runtime change in P02b-5. | P02b-6 | +| Frontend auth layout/native admission | P02b-7 owns Auth.js in `apps/web`, bounded auth route/method admission through current GET/HEAD ingress, cookie propagation, refresh/CSRF/logout. No generic ingress exemption. Remove stale `packages/auth` illustration with that decision. | P02b-7 | + +The acceptance commit records the exact dated instruments before dependent +code; G10/G11/G12-client/G14/G20 are Accepted together. G12's realm +reconciliation, G13, G16 and phase exit stay Open. +No prior dated delivery record is rewritten. + +#### Five implementation steps + +All work stays on `development`. For each step: implement and validate, commit; +run review round 1 with fresh independent agents; verify findings against the +current code, fix valid findings and commit; run round 2 with different agents; +verify/fix/commit again. Start the next step automatically after both rounds +close. Findings are evidence to check, never instructions to execute. + +| Step | Deliverable and safety boundary | Principal validation | +|---|---|---| +| 1 — accepted contract and token foundation | Commit acceptance/disclosures/registrations first. Add pinned JWT package/options, one immutable profile, credential/purpose checks, controlled discovery/JWKS issuer and secret-free diagnostics. Defer production authentication/authorization service registration too: minimal hosting can insert middleware automatically. Test-only composition remains isolated until Step 4 closes the complete HTTP boundary. | Real-handler signature/profile and duplicate JSON controls, wrong issuer under trusted key, ID-token purpose, duplicate JOSE header/unsupported extension, lifetime/skew, reserved actor, key rotation/withdrawal and stock/base handler events 1/3/7 canary capture with positive diagnostics. | +| 2 — real read-only application subject | Add AccountSite contract/handler, exact ReadOnly selection, nonsensitive audit registration and module docs; do not route it yet. Read actual public configuration under the independent host ceiling. | Actual app-role PostgreSQL tenant/org data positives/negatives, lifecycle/missing config, missing/mismatched HostScope and future ClaimAndMembership refusal before reader calls, Off success with zero query audit rows, physical write-refusal and no nested-public workaround. | +| 3 — attributed reconciliation and subject admission | Add bounded subject quota, credential-result and surface-admission components; extend recorder and resolver to consume only the validated projection. No production JWT middleware/route activation yet. | Whole-chain component harness, rows 6/9 positives and 7/10/14 negatives, claimless outcome, row 7 one tenant-wide audit with trusted-org metadata/captured correlation, row 10 zero rows, row 14 zero rows plus one source-aware unresolved count; preserved denial on audit fault, claimless attribution/Debug event, quota lifecycle and stops-audit proof. | +| 4 — atomic HTTP activation and typed contract | Wire all guards at their specified positions in one change; map the GET with authorization and exact census; emit no-store/security/errors; regenerate OpenAPI and split public/authenticated SDK contracts. No session transport or realm changes. | Actual API host with real signed tokens, protected 200; absent credentials on all three known host classes masked404, invalid-public401; exact resolver/header/membership codes; no-store on early refusals; future row-14 hostless access404; planted extra endpoint/write/reorder; public/IdP-down regression, SDK partition and served OpenAPI equality. | +| 5 — production enforcement and packet closeout | Complete transitive production censuses and dirty/clean controls, cross-host/actor/key/telemetry matrices, all related carrier reconciliation and local/hosted verification. Update statuses only from actual proof; prepare the PR for maintainer review. | Complete backend/architecture/HTTP/contract/PostgreSQL suites under existing bounded CI plan, frontend guarded suites, OpenAPI compatibility, all seven required checks and retained public demo/Lighthouse proof; no skip or reduced population. | + +No partially safe authentication goes live between steps: Step 4 activates the +validated principal only together with quota protection, recorder, read-only +route and surface fence. Before that, tests exercise completed components and +real handlers in isolated composition. No temporary development bypass is added. + +#### Required non-vacuous proof obligations + +- Real signed JWTs enter the real handler, not a fake authenticated principal. + The negative issuer token uses a trusted signing key; the negative ID token + also has acceptable audience/client so purpose enforcement is what fails. +- Duplicate JOSE `alg`/`typ`/`kid`, equal duplicates and every forbidden header + (including `crit`, `cty`, `jku`, `x5u`, `jwk` and certificate material) are refused. + Only configured issuer keys can verify a token; a header/key URL is never authority. +- Repeated/equal JSON properties, singleton identifier arrays, object/null/numeric + identifiers, malformed/empty/reserved UUIDs, timestamp boundaries and actor + substitution have planted controls. No invalid credential is treated as absent. +- A previously accepted unexpired token fails after its key is removed and the + new metadata snapshot is observed. Added-key success alone is insufficient. + Respect the framework's refresh minima and bound every wait. +- The actual non-public query and production route are nonempty census subjects. + Test-only endpoints do not count. A helper/nested dispatch or minimal route + cannot evade the permitted request set. A planted write fails physical ReadOnly. +- AccountSite reads the database: contrasting tenant settings, a visible + organization, an inactive organization and cross-tenant/org claim controls must + distinguish clean from widened scope. No id-addressed resource route is added; + future such routes still owe their separate visible/foreign-id controls. +- Resolver rows 8/11/12 and authenticated header mismatch return `tenant_mismatch`; + membership rows 7/10/14 and anonymous header mismatch return `not_found`. + Row 7 writes the existing slug once under the host tenant; row 10 writes none; + row 14 writes none and increments the source-aware unresolved counter once. + Audit rows remain tenant-wide (`OrganizationId=null`) with trusted organization + in metadata and the previously captured actor/correlation/source. No rejected + ambient context or fake tenant is installed for attribution. +- Claimless profiles preserve actor attribution but retain HostOnly authority: + public read 200, AccountSite404 and exactly one fixed Debug diagnostic without + a claim value. New origins/error codes/metrics are not an implicit requirement. +- AccountSite independently rejects missing/mismatched host provenance and + ClaimAndMembership before any reader, even with a future active membership. + Explicit Off registration yields no normal query audit row. Its outer response + policy returns no-store for success and early401/404/429; route and generated + public/authenticated GET ownership are exact and disjoint. +- Whole-chain reduced-budget tests isolate subject A's refusal from subject B + behind one peer; actual production-floor tests separately demonstrate that + shared IP/peer throttling remains. Token rotation and tenant switching do not + reset subject quota. Rejection stops downstream audit work. +- Invalid credentials on a public known host give 401; no credentials remain + anonymous. Both public sites render with Keycloak stopped. Unclassified health + and contract endpoints do not acquire tenant authentication dependencies. +- Raw-token/issuer/audience/metadata/provider-exception canaries are absent from + all enabled sinks; explicitly sanctioned typed UUID/correlation attribution + remains testable. Exercise stock JWT failure events 1/3 and inherited event 7; + a Warning threshold alone must fail. Positive LearnStack closed outcomes remain + observable, and unrelated application diagnostics are not disabled. +- Every new structural detector has a planted offender/clean control and a + mutation of its predicate which must fail. Complete discovery and existing + shard ownership remain enforced; any required plan reassignment is explicit. + +#### Decision-pass review round 1 (2026-10-19) + +Two fresh independent reviewers applied standards-check and code-review to the +proposed contract and package. The security/runtime review used xhigh effort; +the corpus/test-ownership review used high effort. No runtime proof is claimed. + +The verified carrier omission was corrected: Architecture 30 repeats the old +blanket-401 rule and no-authentication status, so it is now explicitly paired +with the catalogue/error reconciliation and Step 4 activation. The read-mode +instrument now names the public-only ordering scope extension separately from +additive exact-type selection. Row 7's existing membership-denial audit and +row 10's no-audit disposition are explicit. Production service registration is +also held until Step 4 because minimal hosting can insert middleware implicitly. +The final security inspection found no remaining actionable finding. + +Local documentation verification passes: seven ADR parser controls, five Release +`CorpusConsistencyTests` with zero skips, 851 relative links/fragments, added +prose width and whitespace checks, exact source-clause verification and +byte-preservation of every prior dated delivery/review record. Only seven +Markdown files change; no Accepted ADR or runtime file is edited. The second +fresh independent review round remains pending. + +#### Decision-pass review round 2 and readiness (2026-10-19) + +Two different fresh reviewers, both at xhigh effort, independently inspected +`0e23cb14..5bfe3c3b` and the final mutable introduction corrections. Both approve +for maintainer decision with no verified actionable finding. They checked the +actual handler/factory/recorder/reader, exact bounded source clauses, pending +catalogue names, SDK coupling, shared quota limitations and first-consumer +ownership. Pinned ASP.NET Core 10.0.12, IdentityModel 8.19.2 and Keycloak 26.6.2 +sources support the profile, refresh and implicit-hosting premises. This remains +a static decision review, not authentication or database qualification. + +The final introduction corrections assign realm mappers to P02b-6 and replace +leftover P02b-4 worker/merge-pending pointers with the actual merge closeout. +Every prior dated phase delivery/review record and existing ADR remains +byte-preserved. Final checks pass: seven ADR parser controls, five Release +corpus tests with zero skips, 852 relative links/fragments, exact source-clause, +added prose-width and diff/whitespace checks. Runtime, database, realm issuance, +browser and hosted CI tests were not rerun for this seven-Markdown-file proposal. + +**Ready for maintainer approval; not Accepted.** The five implementation steps, +G10/G11/G12-client/G14/G20 and dependent runtime remain pending. Approval covers +ADR-0064, the exact disclosure/correction instruments and this implementation +plan together; it does not approve any P02b-6/7/8 gate implicitly. + +#### Maintainer review follow-up (2026-10-19) + +**Changes requested; revised proposal remains Proposed.** Findings were treated +as review data and rechecked against `c94abe1b`, the actual resolver/factory, +recorder/reader, Accepted clauses and pinned upstream sources. No runtime test +or current-production exploit is inferred from a static contract gap. The earlier +rounds' no-actionable-finding opinions concerned their reviewed draft and were +not maintainer acceptance. Their original text is preserved; this dated follow-up +supersedes their readiness conclusion instead of silently editing the receipts. + +| Finding group | Verified disposition and revision | +|---|---| +| Platform-host absence401 vs row13 | Valid contradiction. Remove the absent-token401 permission; AccountSite absence gives masked404 on tenant/org/platform hosts. Name the scoped authorization result handler so `[Authorize]` cannot silently restore the default401. Generic unresolved MediatR behavior remains separate. | +| Future row14 and HostScope | Valid latent contract failure, hidden by today's deny-all membership. The exact query now refuses before readers unless HostAndClaim, valid actor and matching host provenance hold. Test active-membership ClaimAndMembership, missing/mismatched host scope and no reader call; do not wait for Phase03. | +| Resolver/header/membership error codes | Valid ambiguity. Rows8/11/12 and authenticated header mismatch use `tenant_mismatch`; rows7/10/14 membership refusal and anonymous header mismatch use `not_found`. HTTP uses shared Problem Details; pure factory Refused stays unchanged. | +| Missing recorder paths / row7 tense | Valid. Existing resolver writes no audit, so implement the already-required row7 audit rather than claim it is delivered. Extend source/actor/correlation/trusted-org attribution. Keep defended audit tenant nonnullable; add a synchronous source-aware no-tenant refusal method. Row7 one audit, row10 zero, row14 zero plus one unresolved count. | +| JOSE duplicate/extension policy | Valid gap in the selected profile. Require exact duplicate-free alg/typ/kid header, configured-issuer keys only, and reject every other parameter. RFC7515 does not itself require this exact allowlist or reject every duplicate; it is LearnStack's stricter proposed profile, not a claim that stock JwtBearer trusts token URLs. | +| Stock handler diagnostic leaks | Valid source-level gap. Failure events1/3 carry exceptions and inherited event7 logs failure text in the same concrete category. Warning-only filtering is insufficient because event3 is Error. Suppress raw category output at all levels and emit independent closed outcomes; qualify every enabled sink with negative canaries and positive diagnostics. | +| Claimless UserId / HostOnly | Documentation ambiguity valid; a current authority leak was not established. Factory preserves actor independently of HostOnly, and the ceiling already blocks non-public requests. Retain attribution, clarify origin/XML, prove public200/protected404. A new origin, null actor, metric or `lockey_tenant_claim_absent` is unnecessary; the diagnostic is one fixed Debug event without claim values. | +| Read-mode authority | Valid missing carrier. ADR0052 authorizes the public ordering departure on which ADR0040 Amendment8 relies. Acceptance therefore adds each ADR's own bounded scope-extension disclosure and reconciles Standards11's PublicSurface-only wording for this exact query; no Accepted body is rewritten and no general read-mode exception is created. | +| Query audit classification | ADR clarity gap; the package already prescribed Off. The ADR now explicitly names builder.Off, module audit documentation and zero normal query audit rows. No ReadSensitive/MAY classification or new operation slug. | +| Response/route/SDK contract | Valid implementation handoff gaps. Require explicit account/site route, outer no-store before early errors and exact disjoint public/authenticated generated GET ownership with exhaustive union. Public transport remains credential-free. | +| Status/instrument/revocation/attribution wording | Clarify Registered catalogue status, Accepted ADR bodies vs supersession, three dated disclosures, scope=platform restriction only within this tenant scheme, TTL/key withdrawal vs immediate revocation, tenant-wide audit column vs trusted-org metadata and captured correlation/source. Add missing module/standards/architecture references. | +| Earlier IdentityModel source wording | The round2 receipt called8.19.2 pinned. It was the inspected upstream tag and JwtBearer10.0.12 dependency floor, not an existing repository pin. Preserve the receipt with this correction; implementation resolves and qualifies the actual dependency graph. | +| Per-occurrence audit vs first disagreement | No behavior contradiction found: a rejected resolver short-circuits before assertions. Clarify separate requests remain separate occurrences with no coalescing or tenant ceiling. | + +The source check also found a failure-message log beyond the two cited JWT events: +`AuthenticationHandler.AuthenticateAsync` emits inherited event7 under the concrete +handler category. Its negative/positive controls are now part of Step1 alongside +stock events1/3. Pinned upstream and RFC references live in ADR0064; no transient +review input is a committed reference. + +Revision validation passes: seven ADR parser controls, five Release corpus +tests with zero skips, 857 relative links/fragments, prose/diff checks, and +byte-comparison of all pre-existing ADRs plus both earlier P5 review receipts. +Two new independent review rounds remain pending. No acceptance, runtime, realm, +migration, grant or authorization-domain change is made by this follow-up. + +#### Revised proposal review round 1 (2026-10-19) + +Two fresh independent reviewers, both at xhigh effort, inspected +`c94abe1b..5e8539c9` against the actual code, Accepted clauses and pinned vendor +sources. Both found no verified actionable finding. One implementation detail +is now explicit: initialized Vogen identifiers can still contain nil UUIDs, so +the exact query mirrors the existing host guard's nonnil/nonsentinel checks as +well as profile validation. This does not introduce a new authority or origin. + +The contract review reran all seven ADR parser controls and whitespace checks; +the security review inspected sources and diff without rerunning runtime tests. +Neither review is maintainer acceptance or proof of the future implementation. +The second fresh independent revision review round remains pending. + +#### Revised proposal review round 2 and readiness (2026-10-19) + +Two different fresh independent reviewers, both at xhigh effort, inspected +`c94abe1b..9ff8c8a3` within the complete seven-file proposal. Both found no +verified actionable finding. The security review checked the actual resolver, +factory, recorder and reader against the proposed JWT, diagnostic and admission +contracts. The contract review checked the exact Accepted source clauses, +separate disclosure/correction instruments, carrier ownership and five-step +activation boundary. Pinned upstream logging and JOSE sources were rechecked. + +Final documentation checks pass: seven ADR parser controls, five Release +`CorpusConsistencyTests` with zero skips, 857 relative links/fragments, exact +source-clause and added prose-width/diff checks. All pre-existing ADR documents, +earlier dated phase records and both original P5 decision-review receipts remain +byte-preserved. Only seven Markdown files differ from the entry baseline; +runtime, database, realm issuance, browser and hosted CI suites were not rerun. + +**Ready for renewed maintainer approval; not Accepted.** These four revision +reviews qualify the revised proposal for a decision, not its implementation. +ADR-0064, G10/G11/G12-client/G14/G20 and all five implementation steps remain +pending explicit approval together. No dependent runtime has started. Acceptance +first commits the three dated ADR disclosures, row-10 corrections and named +mutable carrier/catalogue reconciliation, then follows the per-step commit and +two-round review loop without further routine approval pauses. + +#### Maintainer acceptance and implementation start (2026-10-19) + +The maintainer explicitly approved the revised ADR-0064 and five-step package +and requested implementation. This accepts G10/G11/G12-client/G14/G20 together; +realm/reconciliation, session/TTL and remaining phase-exit decisions are not +accepted implicitly. The two original and two revision review rounds remain +as-of receipts; this record closes their approval hold without rewriting them. + +The first commit records acceptance, ADR-0036's own bounded audit replacement, +additive attribution clarification and row-10 errata; ADR-0040 and ADR-0052 each +receive their own exact-query read-mode scope disclosure. Standards 04/10/11 and +the five new Registered catalogue obligations carry the accepted contract. +Registration is not implementation evidence. The existing authorization +behavior, database roles/grants, realm export and production HTTP composition +remain unchanged in this acceptance commit. + +Step 1 now implements the token foundation in isolated composition. Production +scheme/authorization registration and middleware activation both remain Step 4. +Every step retains commit, two fresh independent review rounds, verified fixes +and automatic progression. No further routine implementation approval is needed. + +Acceptance checks pass: seven ADR parser controls, five Release corpus tests +with zero skips, 1,788 relative targets/fragments (one existing illustrative +placeholder), prose/whitespace checks and insertion-only preservation in all +three previously Accepted ADRs. No runtime file changes in this first commit. + +#### P02b-5 Step 1 — token foundation (2026-10-19) + +**Complete after both independent review rounds.** Acceptance was +committed first at `493d7f92`. The API now contains the closed options/profile, +immutable typed identity, request-local credential outcome and isolated stock +JwtBearer registration. `Program.cs` remains unchanged: no production scheme, +authorization registration, middleware or protected route activates in this step. + +The resolved graph uses JwtBearer 10.0.12 and IdentityModel 8.19.2. The latter is +the selected dependency version at this receipt, not a separate pre-existing pin. +Raw compact/header and post-signature payload checks reject duplicates, invalid +shapes, reserved IDs, wrong purpose/client/scope and malformed escaped Unicode. +The stock handler still owns cryptography, issuer/audience and key refresh. + +The owned backchannel refuses redirects and bounds each document to five seconds +and 256 KiB, including streamed multibyte bodies. Metadata HTTP instrumentation is +suppressed; unrelated outbound HTTP diagnostics remain observable. Last-known-good +reuse is disabled. The real rotation proof lowers only the stock manager's public +on-demand interval to its one-second minimum in isolated test composition; its +automatic interval remains five minutes and production on-demand remains 30 seconds. + +The production Serilog boundary excludes the exact raw JwtBearer category at all +levels, independently of the ILogger filter. Closed LearnStack outcomes replace +raw failures. Real loopback gRPC OTLP log/trace collection and the L1 capture path +prove privacy with allowed-log/error/HTTP-span positives. Natural initial metadata +failure is stock event 1; a documented test-only interface adapter delegates to +the same real manager/retriever to qualify stock event 3. Event 7 is independently +observed. No fabricated provider exception is called a natural metadata failure. + +The initial combined integration run exposed concurrent test hosts replacing +process-global Serilog/OTel state. A dedicated nonparallel diagnostics collection, +matching the existing public-log test ownership pattern, fixes the test isolation; +production behavior and every canary assertion remain unchanged. + +Validation passes: warnings-as-errors Release solution build; 2,471 unit, +209 Docker-free integration and four contract cases, all with zero skips. The +integration total includes 18 configuration cases, eight real-handler cases with +independent negative/positive matrices and six full diagnostic cases. The complete +architecture suite passes all 410 cases with zero skips; scoped format verification +and the acceptance-carrier link/prose checks also pass. No database/realm/frontend +runtime changes or Docker-suite evidence are claimed for this isolated token slice. +Catalogue obligations remain Registered until their complete active-path owners ship. + +##### Step 1 review round 1 (2026-10-19) + +Two fresh independent xhigh reviewers inspected `493d7f92..65263623` across +security, correctness, performance, ownership, diagnostics and test falsifiability. +They independently verified one shared finding: request-local instrumentation +suppression removes metadata HTTP spans, but native HTTP/DNS metrics still export +the destination hostname. Actual retriever-to-OTLP controls reproduced it. No +token or full-URL leak was established; neither review found another confirmed +defect in this isolated slice. Focused independent reruns pass 26 profile/config +and six diagnostic cases, all with zero skips. + +**Correction to the initial receipt:** its general metadata-instrumentation +suppression statement qualifies spans only. The initial full-URL canaries did +not detect destination-only metric tags. The verified correction projects native +HTTP/DNS metrics onto fixed non-destination dimensions and adds a distinct-host +canary plus exported metric positives. This projection applies to all outbound +metrics; unrelated traces/logs and metric counts, durations and status remain. +The new regression fails on the initial runtime and passes after the projection; +its unprojected SDK control still exports the private hostname. Actual metadata +GET and DNS duration positives are checked before unrelated traffic, and the +temporary test proxy override is restored under the nonparallel collection. +The correction passes a zero-warning Release solution build, all 2,471 unit and +210 Docker-free integration cases, plus 23 affected cross-cutting/corpus cases; +all have zero skips. Format, link/prose and whitespace checks pass. The earlier +complete 410-case architecture run remains the initial implementation receipt; +no complete rerun is claimed for this metric-only correction. The second fresh +independent review round is pending. + +##### Step 1 review round 2 and closeout (2026-10-19) + +Two different fresh independent xhigh reviewers inspected the complete +`493d7f92..c6108bf9` slice, including the round-1 correction and its documented +all-outbound metric dimension tradeoff. Neither found a verified actionable +finding. Each independently ran all 33 authentication integration cases in +Release, with zero failures or skips; whitespace checks also pass. These reviews +claim no Docker, real Keycloak, frontend or production-activation qualification. + +Step 1 is complete. The next step implements AccountSite's real application +contract, independent host guard, exact physical read-only selection, explicit +Off classification and application-role PostgreSQL proofs. Production scheme, +middleware and HTTP route activation remain Step 4. + +#### P02b-5 Step 2 — real read-only application subject (2026-10-19) + +**Complete after both independent review rounds.** Entry is `e67c3299`. +Tenancy declares the unmarked `GetAccountSiteQuery` and typed `AccountSite` +projection. Its independent guard requires HostAndClaim, a real non-system actor, +real matching tenant/host provenance and coherent initialized organization IDs +before configuration, settings or feature access. Future ClaimAndMembership +contexts remain refused even with a planted matching HostScope. Refusals use the +shared `not_found` error. The validator admits no query parameters. + +The public and account handlers call the same internal projection directly; +neither nests another MediatR request. Public fields, lifecycle/locale semantics, +whole-theme/null behavior and attribution remain unchanged. The account query is +explicitly Off, with no query intent or audit row. Module documentation names +the unrouted boundary and adds no permission key. + +An immutable exact-Type declaration lives in SharedKernel beside transaction +mode. Tenancy's shared site-read registration supplies the sole AccountSite +literal; API and Seeder call it. The existing TransactionBehavior freezes the +Type set and retains the unchanged framework/public fallback. This placement +preserves module dependency rules without introducing a core-to-module edge or +a general mode selector. The shared registration also supplies Seeder's public +configuration reader. Existing physical mode/announcement ownership is unchanged. + +The existing module-independent transaction architecture rule now closes the +declaration, immutable snapshot, exact type lookup and registration callers. +An initial detector falsely classified the legitimate Enumerable projection as +registration; its correction permits only the exact projection and registration +signatures/owners, with duplicate/acquisition/substitution controls inside those +owners as well as outside them. No new architecture Fact or canonical rule is +invented, and implemented catalogue counts stay unchanged. + +Validation passes: zero-warning warnings-as-errors Release solution build; +2,521 unit cases, 210 Docker-free integration cases, 119 focused PostgreSQL +cases and 89 affected architecture cases, all with zero failures or skips. +The PostgreSQL set includes 14 new actual-account cases plus existing public +reads, transaction, provisioning and unit-of-work regression cases. Actual +`learnstack_app` checks prove non-superuser/non-BYPASSRLS execution, contrasting +stored tenant data, mapped-organization lifecycle, empty/disabled configuration, +foreign provenance refusal before reads, zero query audit delta, real SQL/EF +`25006` refusals with writable positive controls and writable-outer mixed-mode +refusal. Branding remains tenant-wide; no organization theme is fabricated. + +Scoped formatting, whitespace and carrier link/prose checks pass. Complete +backend/Docker/architecture unions and hosted qualification remain Step 5; +this receipt claims the named affected populations. No production HTTP route, +authentication activation, schema or grant change is introduced by Step 2. + +##### Step 2 independent review round 1 + +Two fresh xhigh reviewers independently inspected security/transaction behavior +and module/composition/census boundaries at `e67c3299..a736edbb`. Both approve +with zero verified code findings. Each independently reran 73 focused unit cases +and the extended transaction-composition architecture case; the security reviewer +also reran all 14 actual AccountSite PostgreSQL cases. All pass with zero skips. +The source review confirmed actual app-role SQL/EF refusals and writable controls, +future hostless-context refusal, audit Off and unchanged shared projection. +A stale Standards 11 implementation pointer is reconciled before round 2. + +##### Step 2 independent review round 2 and closeout + +Two different fresh xhigh reviewers independently rechecked security/correctness +and module/composition/census boundaries at `e67c3299..e36d47ca`. Both approve +with zero actionable findings. Each independently passed 73 focused unit cases +and the extended transaction-composition architecture case; the security reviewer +also passed all 14 real AccountSite PostgreSQL cases. Zero failures or skips. +They inspected current source and controls rather than treating round 1 as proof. +Neither repeated the complete solution or hosted suites; the implementation +validation above and final Step 5 obligations retain their stated scope. + +Implementation is `a736edbb`; `e36d47ca` reconciles the mutable standard and records +round 1. Both review rounds are complete. Step 3 now implements attributed +reconciliation, no-tenant diagnostics and subject admission. Production scheme, +ordered middleware and route activation remain Step 4. + +#### P02b-5 Step 3 — attributed reconciliation and subject admission (2026-10-19) + +**Complete after both independent review rounds.** Entry is `8f9ecff2`. +Only the immutable validated identity supplies HTTP claim/actor signals. Raw +principals cannot establish tenant authority. The resolver still calls the pure +factory once and restores the prior accessor; no context is installed to attribute +a refusal. Rows 8/11/12 and authenticated header disagreements use the shared +`tenant_mismatch` Problem Details shape. Membership and anonymous refusals keep +masked `not_found`; malformed assertions retain their existing 400. + +The existing recorder now carries closed source, typed actor, captured request +correlation and trusted organization. JWT refusals defend the host tenant; +organization provenance stays in metadata while durable rows remain tenant-wide. +Row 7 writes one rejection, row 10 none. Row 14 synchronously counts/diagnoses +without a tenant/asserted-value field or store I/O. Existing operation keys, +anonymous burst accounting and failure-preserving Critical/health behavior remain. +Claimless identities keep their actor under HostOnly and emit one fixed Debug +event after subject admission; the account component refuses that ceiling. + +The additional singleton limiter keys only validated issuer/subject, with the +actual 600/min fixed window and no queue. Token/actor/tenant selection cannot +reset it. Retirement inspects at most 128 entries per callback and reclaims only +full-quota partitions idle for a whole window. Snapshot leases retain no child +ownership; sync/async shutdown closes admission and joins the timer before +remaining child disposal. Request-local outcome replay does not debit twice. +The earlier visitor/peer limits still apply to all credentials. + +Credential-result admission rejects present invalid credentials even for public +reads. The account surface component requires a validated actor and independent +host-backed authority; the application query retains its own guard. These +components remain isolated from Program: production authentication services, +middleware/authorization result handling and the route activate together in +Step 4. The exact production endpoint/dispatch census closes in Steps 4–5. + +Validation passes: zero-warning warnings-as-errors Release solution build; +2,536 unit cases, all 229 Docker-free integration cases, 31 focused PostgreSQL +cases and 55 affected architecture cases, with zero failures or skips. Nineteen +new component-chain cases use real signed tokens and the stock handler through +unchanged early admission, actual host classification, credential/subject gates, +resolver and assertions. Reduced subject budgets prove independence behind the +same peer, rotation resistance and stopping recorder work; separate default and +early-floor controls retain the actual limits. The six new PostgreSQL cases +exercise resolver-to-real-store rows/omissions and unavailable-store behavior; +three recorder cases prove captured fields and tenant-wide/foreign visibility. +Every database assertion runs as verified non-superuser/non-BYPASSRLS +`learnstack_app`; only fixture cleanup uses the administrator role. + +An initial harness correction enabled the exact Debug category and buffered +response JSON before repeated normalization. A stock limiter test now observes +actual full-quota idle state rather than treating TryReplenish's supported-mode +return as proof of replenishment. The corrected complete named populations pass. +Scoped formatting and carrier/whitespace checks pass. No production scheme, +HTTP route, realm, membership reader, schema or grant is activated by this slice. +Complete backend/Docker/architecture unions and hosted proof remain Step 5. + +##### Step 3 independent review round 1 + +Two fresh xhigh reviewers independently inspected `8f9ecff2..c0909708` across +quota concurrency/lifetime and reconciliation/recorder trust boundaries. Both +approve with zero actionable findings. The quota reviewer independently passed +10 limiter and 19 component HTTP cases; the reconciliation reviewer passed +39 focused unit, 19 component HTTP and nine app-role PostgreSQL cases. Zero +failures or skips. They checked current source and positive/negative controls, +including no-tenant omission, captured attribution and full-idle-only retirement. +Production activation and exact endpoint census remain the named later steps. + +##### Step 3 independent review round 2 and closeout + +Two different fresh xhigh reviewers independently inspected +`8f9ecff2..90724a54`. Both found no Blocker/Major or additional runtime defect; +both confirmed one Minor: the new actor log properties exported Vogen wrappers +instead of underlying UUIDs. Standards 02's emission rule applies. The recorder +now exports Guid/nullable Guid values, and captured-log tests require those +primitives; durable typed attribution and policy remain unchanged. Independent +reruns passed the named 10 limiter/19 component cases and 39 focused unit/19 +component/nine app-role PostgreSQL cases respectively, with zero skips. + +A narrow coverage suggestion was verified too: shortening only the stock +factory's default window escaped the original real-600 assertion. The shared +Window constant already had a literal-60 middleware control; that broader gap +was not present. The actual-default assertion now independently requires one +minute. A temporary one-second factory mutant passed the old assertion and failed +the strengthened assertion; production source was restored before final build. +This changes no production quota policy. + +After correction, the warnings-as-errors solution build passes with zero warnings +or errors, followed by 39 affected unit and 28 integration cases (19 component, +nine PostgreSQL), zero failures/skips. Scoped formatting, whitespace and carrier +checks pass. Implementation is `c0909708`; `90724a54` records round 1. Both review +rounds and verified corrections are complete. Step 4 now owns atomic production +activation, the real route, response policy and typed contract. + +#### P02b-5 Step 4 — atomic HTTP activation and contracts (2026-10-19) + +**Complete after both independent review rounds.** Entry is `6686d018`. The +production root installs the strict scheme, authorization, +credential-result gate, subject quota and independent surface admission together. +Their explicit order retains earlier visitor/peer/body precedence, classifies +hosts before authentication and reconciles claims before header assertions. +The only new action is authorized `GET /api/v1/account/site`, dispatching the +already-qualified exact Off/ReadOnly query. A scoped authorization result handler +masks missing credentials without changing infrastructure/internal challenges. +The outer response owner reasserts no-store and removes validators on account +successes and early errors, including errors before tenant resolution. + +Development config supplies only its canonical loopback realm issuer. Every other +deployment mode requires explicit HTTPS configuration; startup validates its form +without connecting to the issuer. The local launcher carries an explicit issuer +only to the API child, rejects conflicting file/ambient configuration and keeps +it out of the public web environment. No realm export, mapper or client secret +changes in this step. + +The served OpenAPI document separates AccountSite bearer security from anonymous +operations, preserves the shared public projection and describes bounded refusal +headers/shapes. The SDK is regenerated from that actual document. Exact disjoint +public/authenticated GET ownership remains exhaustive; the authenticated package +exports a typed contract without adding session or bearer transport. P02b-7 owns +that transport. Production route/helper censuses and actual-host/PostgreSQL proofs +are part of this slice. + +Validation passes on the current Release binaries: warnings-as-errors solution +build with zero warnings/errors; 2,536 unit, five contract, 294 integration +(241 Docker-free plus 53 application-role PostgreSQL) and 96 affected architecture +cases, all with zero failures/skips. The PostgreSQL set includes the 20 real +AccountSite HTTP cases and two actual-chain quota cases. The full frontend lint, +typecheck and guarded workspace run pass 1,629 cases with zero skips/todos. The +snapshot is exported from the real production Program in its ordinary contract +fixture and compared with the served document; SDK generation uses that snapshot. +Scoped formatting, whitespace and carrier link/prose checks pass. + +The complete route detector and planted controls use actual production metadata; +its helper traversal distinguishes inherited base members from acquired abstract +services without losing concrete-service traversal. The older job-manifest route +multiset now names the one newly approved AccountSite GET; extra/dashboard routes +still fail. The order proof combines real-host precedence with reordered, missing +and duplicated registrations from actual Program source. Initial fixture-only +corrections retain lazy recorder construction and stock metadata refresh behavior. +No production fallback was weakened to satisfy a test. + +Complete backend/hosted unions and final catalogue promotion remain Step 5. +This receipt claims only the named local populations; both fresh independent +Step 4 review rounds remain pending. + +##### Step 4 independent review round 1 + +Two fresh independent xhigh reviewers inspected `6686d018..0be26abc` across +runtime security/isolation and contract/census/confinement, including correctness, +performance, ownership, refactoring and standards. Neither found a Blocker/Major; +both verified one Minor: actual AccountSite GET can return the early body-bound +`413 payload_too_large`, but the served contract and generated SDK omitted it. +The runtime itself already refuses before host/authentication work. Independent +reruns passed 52 architecture/contract/actual-host/configuration cases in one +review, and 113 HTTP/census/PostgreSQL/contract/SDK cases in the other, zero skips. + +The verified correction adds that response to account and public contracts using +the shared Problem Details/no-store owner; public HEAD remains bodyless. The +response census and missing-413 controls now require it. The strengthened census +first failed against the unchanged runtime, then passed after adding the response. +The snapshot is re-exported from the actual host and SDK regenerated, with an +explicit generated 413 type assertion. This changes no admission/runtime outcome. + +After correction, the warnings-as-errors Release solution build, five contract +and 34 actual-host/PostgreSQL/quota cases pass with zero warnings/failures/skips. +Frontend typecheck, SDK lint and the complete guarded 1,629-case suite pass with +zero skips/todos. Carrier and whitespace checks pass. The second fresh independent +review round remains pending. + +##### Step 4 independent review round 2 and closeout + +Two different fresh xhigh reviewers independently inspected the complete +`6686d018..746c0cd2` slice, including the round-1 correction. Neither found a +verified actionable finding. Their checks covered security/correctness, +performance, ownership, refactoring, complete route/helper/nested-dispatch census, +actual-host error precedence, API-only issuer configuration and public/authenticated +contracts. The security reviewer independently passed 34 HTTP/PostgreSQL/quota, +12 census and five contract cases. The quality reviewer independently passed +12 actual-host, 12 census, five contract, one production-manifest and 62 guarded +SDK cases plus SDK typecheck. All have zero failures/skips/todos. No actual +Keycloak, session, native Linux or full hosted qualification is inferred. + +Implementation is `0be26abc`; `746c0cd2` records the verified 413 correction and +round 1. Both independent review rounds and their verified correction are closed. +Step 4 is complete. Step 5 now owns the remaining authority census, final carrier +reconciliation and complete local/hosted packet qualification before PR handoff. + +#### P02b-5 Step 5 — production enforcement and closeout (2026-10-19) + +> **Historical Step 5 entry.** The in-progress and pending receipts below precede +> the [local implementation/review closeout](#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) +> and subsequent correction records. They are not current packet status. + +**In progress; no PR or hosted qualification is claimed.** Steps 1–4 and both +fresh independent review rounds per step are complete at `a7c9d5a3`. + +The final authority census loads every discovered production assembly and scans +actual IL, including generated state machines. Raw principal/claim/role reads, +role authorization metadata, extra typed-identity constructors, clones, mutations +and direct feature writes are refused. The existing factory/events and direct +actor/scope/subject accessor consumers form explicit nonempty caller sets. +Compiled dirty/clean probes, weakened raw-reader predicates and mutations of the +actual identity shape, factory call, same-owner write count and backing field +exercise the same detector. This is structural enforcement, not a general +reflection/taint-analysis claim. + +Architecture 09/14/28/33, Standards 02/05/09/20 and Phase 03/06/11 now describe +the implemented API boundary and each next consumer. The seven authentication +catalogue obligations have actual local test owners and are Implemented: 260 +architecture methods, 229 Implemented rules, 133 in that assembly and 96 elsewhere. +Runtime proof remains with the actual signed-token, physical ReadOnly, quota, +recorder, served-contract and SDK controls delivered in Steps 1–4. + +**Local validation at entry.** The warnings-as-errors Release solution build +passes. All 2,536 unit, five contract and 241 Docker-free HTTP cases pass with +zero failures/skips. Twenty focused Release authority/surface/corpus cases pass; +subsequent interface-access and typed-property negative controls pass eight +focused Debug authority/corpus cases with zero build warnings/errors or skips. +The complete Release architecture and ordinary PostgreSQL populations are still +running. One earlier job terminal-query plan assertion failed in the latter. +A disposable migrated-database experiment reproduced 12,000 obsolete bitmap +index entries after the guarded synthetic seed and zero after VACUUM, with the +same runtime SQL; bitmap forcing is confined to that diagnostic experiment. +The fixture now explicitly VACUUMs/analyzes before EXPLAIN. Normal production +planning, the clean `<256` visit bound and the volatile-cutoff dirty `>=6,000` +control remain unchanged. Its isolated original rerun passed; that rerun does +not close the failed complete run. Native Linux, +full hosted execution, both Step 5 review rounds and packet closeout remain +pending. No population, assertion, grant or production SQL is waived. + +##### Step 5 independent review round 1 and verified corrections + +Two fresh independent xhigh reviewers inspected `a7c9d5a3..d4639529` across +security/authority and corpus/test falsifiability. They verified two Major +structural-enforcement gaps, with no current production authority misuse: +interface `IAuthorizeData.Roles` assignment escaped the concrete-role predicate, +and generated-record `Deconstruct` exposed subject/scope without external getter +calls. Both used compiled probes against the actual detector and real production +graph; the interface metadata also produced a real framework role requirement. + +The root reproduced each independently with new compiled negative controls: +the unchanged scanner first failed the interface control; fixing that predicate +then exposed the deconstruction control as a second failing test. Interface +role getter/setter calls and identity deconstruction are now refused by the same +production detector. Existing clean, predicate-mutation, missing-subject, +factory, immutable-shape and same-owner additional-write controls remain. +The suggested extra-constructor concern was not a verified finding: an ordinary +additional constructor on this positional record delegates to the primary +constructor and adds an already rejected caller. + +Verified Minor corrections reconcile the catalogue's stale Registered/runtime +pending header and ADR-0064 derivations in Standards 02/05/09/20. README now +separates active API authentication from future browser sign-in and documents +mandatory issuer configuration without a startup network dependency. + +The complete Release architecture run also caught the older job-manifest census +still expecting only two public controllers. Its exact inventory now adds only +AccountController/GetSite, keeps every production controller/action in the scan +and plants an extra AccountSite action into the same detector. It does not add +an operator route or dashboard exception. Nine focused Debug authority/corpus/ +manifest cases pass, zero failures/skips. The maintained terminal-plan case also +passes separately in Debug with unchanged normal-planner and dirty/clean bounds. +Seven ADR parser controls and the carrier/whitespace checks pass. + +The original broad local architecture/PostgreSQL runs and the first hosted run +retain their actual results; focused correction proof is not a claim that those +runs passed. The complete hosted run is +[39318063296](https://github.com/HodeTech/LearnStack/actions/runs/39318063296) +at `d46395299f46428bc175b82745392505b1779a86`; it is still in progress at this +receipt. Both independent review opinions and verified corrections close round +1. Round 2 uses two different fresh reviewers on the corrected slice; complete +current-source hosted qualification and packet closeout remain pending. + +##### Step 5 independent review round 2 and verified corrections + +Two different fresh independent xhigh reviewers inspected +`a7c9d5a3..1942662d`. They verified three further Major structural-enforcement +gaps, with no current runtime authority misuse: generated record formatting +exports subject through object/generic APIs; IdentityModel token/payload APIs +escape a Claims/Principal-only predicate; and a derived authorization attribute +with Roles escapes both concrete-only metadata censuses. + +The root reproduced the vendor accessor and object-formatting failures in +sequence with compiled negative controls. A real compiled derived attribute and +its named Roles metadata then failed both authority and HTTP detectors when +planted on actual AccountController/GetSite. Synthetic test-helper loading errors +were corrected before those two red results; they are not counted as proof. + +The corrected detector closes identity/feature acquisition, holders, signature, +local, field, method and generic forwarding to the existing enumerated logical +owners. It covers object/generic formatting without pretending that the target +is an identity-declared method. Raw modern/legacy IdentityModel APIs are refused. +Authorization metadata follows the actual production inheritance/interface graph; +new custom authorization-data types cannot silently add another policy. Both +censuses use the compiled derived-attribute control and fail their weakened +concrete-only predicate. Typed actor use and the real unmodified graph remain +clean. This is a bounded static census, not general reflection/taint analysis. + +Verified Minor corrections remove the stale memberships-array risk from +Architecture 13 and replace Standards 11's obsolete missing-authentication +explanation with row 7's actual deny-all membership barrier, owned by Phase 03. +No production runtime, route, role, grant, retry or quota changes accompany these +corrections. Twelve focused cases pass in Debug and Release with zero failures/ +skips; the current Release architecture build has zero warnings/errors. +Both independent reviewers then reran their original bypass probes against the +corrected binaries: object/interpolated formatting, all four vendor-token probes +and derived role metadata are refused, while baseline/restored production graphs +remain clean. Their focused reruns pass three and twelve Debug cases respectively, +zero skips, and both approve the targeted corrections. Round 2 and its verified +corrections are closed; complete current-source hosted qualification remains +pending. + +**First complete hosted receipt.** +[39318063296](https://github.com/HodeTech/LearnStack/actions/runs/39318063296) +at `d46395299f46428bc175b82745392505b1779a86` is complete and failed honestly: +architecture shard 4 has 149 passes and one failure for the old two-controller +job-manifest inventory; the backend aggregate refuses it. The other five +architecture shards pass. All twelve ordinary shards, the 31-case native lane +and integration aggregate pass, with 2,486 exact Docker/native case results and +variant A retained. Native receipts confirm natural owned completion/cleanup and +zero refusals/skips. Base, frontend, OpenAPI comparison, meta and secret scan +pass. The public-demo receipt binds the same source and confirms nine URLs, +27 reports and completed process/Compose/private-file cleanup. The old local +complete architecture run likewise records 415 passes and that one failure out +of 416, zero skips. Neither failed run is relabelled green after its correction. + +The corrected `1942662d` hosted run +[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) +is still in progress at this receipt; the new round-2 controls require a later +source qualification too. No filtered subset, retry or skipped case substitutes +for final complete ownership and all seven required checks. + +#### P02b-5 Step 5 — local implementation and review closeout (2026-10-19) + +Review vehicle: [PR #33](https://github.com/HodeTech/LearnStack/pull/33), +`development` into `main`. Its live checks and PR delivery receipt own final-head +CI status; this local receipt does not claim merge. + +**Locally complete; unmerged.** All five implementation steps and both fresh +independent review rounds per step are complete. The accepted decision precedes +runtime; the final implementation/correction head is `e20b6071`. Step 5's +`d4639529`, `1942662d` and `e20b6071` implement the census and record both +rounds with their verified corrections and independent targeted rechecks. +The earlier receipts retain their actual failed/pending state. + +The final warnings-as-errors Release solution build passes with zero warnings/ +errors. Twelve current Release authority/HTTP/corpus/manifest cases and the +current Release terminal-plan case pass, zero failures/skips. The complete local +base population passed 2,536 unit, five contract and 241 Docker-free HTTP cases. +The initial complete local architecture and ordinary populations report +415/416 and 2,454/2,455 respectively; each has the one explicitly corrected +census/fixture failure above, not a skip or hidden rerun. Corrected current +subjects pass independently and the complete hosted populations retain their +own source-bound receipts. + +The first complete hosted receipt above proves all 2,486 Docker/native cases, +frontend, OpenAPI, meta, secret scan and nine-page/27-report public demo, while +honestly failing the stale job-manifest census. The corrected +[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) +at `1942662df0e4321163f99b678805bec5a69c314a` is still running at this local +receipt. Later source changes only strengthen tests and reconcile documentation; +production/API/SDK/launcher/CI runtime files are unchanged from that source. +This is not a claim of complete final-head CI: the live PR checks must qualify +the final source with all seven required contexts, exact case unions, zero skips, +owned cleanup and the unchanged finite plan/budgets. PR CI status is recorded in +the PR delivery receipt before handoff; merge remains a maintainer action. + +The packet delivers only the API half: strict bearer validation, immutable typed +identity, attributed host/claim reconciliation, stable subject admission, the +physically read-only AccountSite query/route and generated authenticated contract. +Current realm imports do not issue this profile; no browser sign-in/session or +live membership/permission service is claimed. The next packet is **P02b-6**, whose +decision pass re-verifies G12's realm/reconciler boundary and G13's issuance TTL +authority before changing Keycloak or seed users. P02b-7 then owns BFF sessions +and bearer transport; P02b-8 owns remaining enforcement/erasure/phase-exit work. +No next packet starts in this closeout. + +#### Work deliberately retained by its first consumer + +- **P02b-6:** real Keycloak issuance, fresh/warm realm reconciliation, user-profile + edit protection, actual seed identity/UUID agreement and issuance TTL. +- **P02b-7:** BFF code exchange, session custody/refresh/CSRF/logout, native auth + admission, guarded page and authenticated SDK bearer transport. +- **P02b-8:** LS0002, retained-store erasure inventory and final phase-exit census. +- **Phase 03:** users/memberships/permissions, durable subject-to-actor mapping, + tenant switching through new tokens, privileged and operator routes. +- **Phase 06 / 11:** full browser OIDC journey / production identity and distributed + infrastructure qualification respectively. + +These are the already staged first consumers, not cleanup debt from P02b-5. +The authenticated site endpoint grants no protected lesson/enrollment access. + + + +### P02b-5 external review remediation (2026-10-20) + +**Implementation and local proofs delivered on development.** The five original +implementation steps and both +review rounds per step remain completed historical deliveries. This follow-up +verifies later review claims against `afa84815`, corrects independently reproduced +issues under ADR-0064, and implements the separately Accepted ADR-0065 policy. +PR #33 remains unmerged. Temporary review inputs are not delivery authorities. + +#### Decision boundary + +[ADR-0065](../decisions/0065-bounded-tenant-assertion-diagnostics.md) is **Accepted — +2026-10-20**. The maintainer authorizes acceptance after verified review corrections +and subsequent implementation without another approval gate. Acceptance and dated +ADR-0036/0064 disclosures precede dependent policy code. The scoped recorder now +consults a process-local singleton target-tenant allowance: 600 attempts per +monotonic minute, no independent tenant-registry cap, shared across actors. The +named MUST admission exception, suppression signals, unbounded warning cost and +native HTTP/DNS destination-dimension loss are explicit. Acceptance alone does +not claim the new runtime or proofs are delivered. + +#### Verified corrections and dispositions + +Identifiers below preserve the review's finding identity, not its severity. +Reproduction and source determine each disposition; a suggestion is not presumed +to be a runtime defect. + +| Items | Disposition and evidence owner | +|---|---| +| B-1 | Strengthen the real-handler rotation proof: only a token request causes stock manager refresh, an issuer-owned response gate and actual update callback witness the update, and the subsequent rotated-token request must be 200. No test polling of `GetConfigurationAsync` can fetch the key. Stock background refresh may first return 401; that response is not counted as successful refresh. | +| B-2 | Correct the three structural endpoint censuses to follow actual stack arguments and reject computed/variable/decoy paths and alternate endpoint composition. Blinding the literal guard produces three expected red owners; restoring gives 13 green cases. The prior job manifest already had an exact runtime route union; new authenticated runtime cases strengthen it with all 15 endpoints and observed request dispatch in Development/Production. | +| B-3, M-10 | Enforce exact identity/feature members and full constructor/caller signatures, raw Tokens API reads, approved-owner generic/object exports and generic constraints, external authorization metadata resolution, and exact read-mode argument/branch/freeze flow. Extra owner overloads and malformed declarations no longer inherit authority by name. Planted controls independently fail. | +| M-1 | Mask only absent-identity challenges on the classified AccountSite surface. Forbid retains the stock 403. The Forbid and unrelated challenge controls use separate request scopes, matching the authentication handler's actual per-request ownership. | +| M-2, M-4, M-5 | Implemented under Accepted ADR-0065. A singleton shares 600 write attempts per defended tenant across scopes; failed writes consume allowance and suppression retains one Warning plus its own closed-label counter. No independent tenant-registry cap exists. Real OTLP controls distinguish destination-free metrics from preserved ordinary traces. Audit amplification and tenant-series growth are real Accepted-contract risks. Native destination loss is also real and process-wide, already implemented before this correction; it is not described as metadata-only or dependency attribution. | +| M-3 | Bound subject partitions to 4096. Refuse new keys before allocating a limiter; preserve existing spent quota and reclaim only fully idle partitions. A high-cardinality control proves cap refusal, no allocation/eviction and safe retirement reuse. | +| M-6 | Independently test actor, tenant, organization, origin and malformed identity/context refusals. Effective organization must equal the validated claim organization or host default; a context cannot invent an organization when both are absent. | +| M-7 | Validate discovery issuer equality without replacing the stock BaseConfigurationManager contract. Discovery/JWKS retrieval stays under the configured issuer origin and realm path. Disable trying all signing keys; signed unknown/withdrawn kid and wrong-discovery controls refuse. | +| M-8 | Reconcile live authentication, rows 7/10/14, deny-all membership and current implementation comments. The actual Keycloak export still lacks the approved issuance profile; P02b-6 owns its implementation and proof. | +| M-9 | The prior implementation receipt at `5676c754` remains historical. The doc-sync head `afa84815e0e9dfc3a215e8ebb38f8840e3ec2254` passed [39325575543](https://github.com/HodeTech/LearnStack/actions/runs/39325575543), and CodeRabbit passed. These observations do not qualify subsequent correction code. PR #33 owns the current head/check receipt. The earlier dated “still running” statement is retained as its as-of observation. | +| M-11, m-33 | Resolve issuer conflicts across `.env`, `.env.local` and ambient inputs only when the API launcher opts in. Projection-only values are accepted explicitly; web startup neither consumes nor gates on the API issuer. | +| m-1, m-2 | Document required 503 Retry-After and route-specific 405 Allow; extend served-contract deletion controls and regenerate snapshot/SDK together. | +| m-3, m-4 | Reconcile the SDK root's typed authenticated contract and nine-operation/five-GET contract inventory, preserving four public wrappers. | +| m-5 | No change: the generic settings accessor also serves writable commands and is not a public-site-only seam. The public projection first passes the physical read-only/provenance configuration reader; independently forbidding writable generic reads would break its intended owner. | +| m-6 | Recheck every resolved organization lifecycle in the public configuration reader, including claim-selected row 7 scope. Positive/restored and suspended/archived/deleted real-PostgreSQL controls distinguish it from the host-only check. | +| m-7, m-8 | Freeze declarations once in singleton ExplicitReadOnlyRequestCatalog and make the sole exact-type declaration registration idempotent. Actual repeated registration and cross-scope identity controls accompany the structural flow guard. | +| m-9 | No change: invalid optional theme already intentionally projects null; the generic setting reader returns a typed validation failure. A new warning is an optional diagnostic choice, not a changed successful-response contract. | +| m-10 | Document the existing Kestrel wire/framing backstop residual in 413 descriptions: server-level refusal can precede the application body/header policy. No all-wire Problem Details/no-store guarantee is invented. | +| m-11 | PublicResponsePolicy already uses the shared account path predicate; the OpenAPI transformer now uses the same live v1 constant. No v2 exists to qualify; a new major remains an explicit surface change. | +| m-12 | Suppress only the exact vendor ILogger category while preserving unrelated provider/category thresholds and rule order. Sibling-category positive and threshold controls prevent prefix suppression or accidental threshold widening. | +| m-13 | No change: explicit default-port text is deliberately noncanonical and rejected rather than silently normalized to a different configured issuer string. An explicit refusal case documents that existing policy. | +| m-14 | Refuse duplicate path slashes in issuer configuration; canonical transport remains strict. | +| m-15, m-17 | No speculative decompression, connection-pool or lock-sharding refactor. No correctness failure or measured contention was demonstrated. Finite I/O/document and subject registry bounds remain independently tested. | +| m-16 | Remove unused credential presence state. Preserve the already tested single closed authentication outcome; do not delete a distinct useful signal merely because a report calls it duplicate. | +| m-18 | No change: typed assertion headers intentionally retain Guid.TryParse compatibility. They never select scope and their accepted spelling is not the stricter token identity grammar. | +| m-19 | No new metric: row 10 already emits the fixed resolver refusal diagnostic and deliberately writes no audit row. A new membership-dimension instrument would be an additional observability contract. | +| m-20, m-21 | Define claimless principal, AccountSite and assertion source; narrow audit-matrix per-occurrence wording to a defended host tenant and explicitly exclude row 14. | +| m-22 | No Accepted body rewrite: the relationship table already names the two read-mode scope extensions and the row-14 audit replacement separately. The broad status summary does not replace those exact instruments. | +| m-23 | Refuse no-tenant signal calls outside the fixed jwt-claim/Tenant pair before emitting a label. | +| m-24, m-25 | Refuse nil/sentinel defended audit tenants before signal/store work; standalone store backstops also reject unassigned ids. Unassigned trusted organization becomes null metadata, never a dereference. | +| m-26, m-27 | Validate every supplied typed identifier and principal coherence before no-tenant shortcut/context construction. Factory positive rows remain; malformed values cannot mint a partially trustworthy context. | +| m-28 | Extend the account path fallback across methods while preserving actual matched-action admission and the existing valid-credential 405 controls. No additional routed method is introduced. | +| m-29 | Derive the immutable projection from the cryptographically validated security token, never a second read of a potentially changed Authorization header. | +| m-30 | Positive pure-factory rows 7/10/14 already existed. Keep them; add claim-selected organization lifecycle controls rather than inventing a second live membership implementation before Phase 03. | +| m-31 | Strengthen actual unsigned/public-route invalid-profile and precise projection-clock skew controls, plus Forbid and app-role assertion. Existing actual 600/whole-chain reduced-budget, anonymous warning and no-credential/no-audit evidence remains; do not relabel a reduced-budget test as end-to-end 600 throughput. | +| m-32 | Dispose unit-owned metric providers; isolate real database cleanup/reads by fixture correlation. The diagnostic collector's AllPayloads already includes Metrics, so an alleged missing full metric canary sweep is not reproduced. | +| m-34 | Recheck normalized URL pathname and reject any normalization change before adding private public-hop headers. A substituted SDK transport control rejects dot segments, encoded traversal, fragments and foreign origins, with a real positive public request. | +| m-35, m-36 | Require kid-selected trusted keys and reject whitespace-only opaque subject/kid values; explicit signed negative controls accompany them. | +| m-37 | No duplicate handler validation: the real GetAccountSiteQueryValidator rejects HasUnexpectedQuery at canonical pipeline step 2 before any reader. Directly calling a handler outside its owner does not establish an HTTP bypass. | +| m-38 | JWKS documents cannot redirect trust to another origin/realm path. Do not ban private IdP networks: SaaS, Dedicated and Self-Hosted can legitimately configure private identity providers. An operator allowlist/DNS-rebinding policy would be a separate deployment decision. | + +#### Correction validation + +Runtime corrections are committed as `8a3892d9`, following acceptance commit +`d335f2bf`. Local qualification covers the working tree committed there; formatting +changes no behavior. Release solution compilation with warnings as errors passes. +The completed local populations are: + +| Population | Passed | Failed / skipped | +|---|---:|---:| +| Full Unit | 2,581 | 0 / 0 | +| Changed authentication, endpoint, tenancy, read-mode and corpus Architecture owners | 80 | 0 / 0 | +| Full Integration `Requires!=Docker` | 257 | 0 / 0 | +| Focused real PostgreSQL AccountSite, read-only, assertion/audit and invalid-store-target owners | 58 | 0 / 0 | +| Full Contract | 5 | 0 / 0 | +| Full frontend (web + SDK) | 1,630 | 0 skips / todos | + +Frontend lint and typecheck pass. Seven ADR-parser controls pass. Changed-doc +relative files and fragments are checked independently. The structural controls +also retain the real same-subject dirty/clean evidence: blinding the endpoint +literal guard gives three failing owners; the original independent opaque-object +export repro now gives one offender while its clean control gives none. A +scoped audit-budget mutation fails both actual DI identity and 601-scope +pre-I/O accounting proofs. More than 4096 live host tenants remain independent. + +The expanded run found a missing budget registration in the deliberately minimal +reconciliation test host; its singleton is now installed and all 58 PostgreSQL +cases pass. It also reproduced an OTLP test-lifetime race: the real suppression +Warning was emitted, but the host exited before the asynchronous log batch was +observed. The test now awaits the actual correlated export within eight seconds +while its owner is alive. Counter/label/no-I/O assertions are unchanged; the full +257-case non-Docker population passes after that correction. + +An accidentally broad local Integration selection was cancelled and is excluded +from receipts; its processes and Testcontainers exited. The correct Docker +exclusion is `Requires!=Docker`. An expensive full local Architecture run was +also stopped without a complete receipt. Neither is described as a passing +population. Complete Architecture, ordinary Docker and native populations remain +mandatory in the unchanged CI shards, with exact union verification by both +aggregates. The source-bound current head/check receipt belongs to +[PR #33](https://github.com/HodeTech/LearnStack/pull/33); earlier successful runs +are historical and do not qualify the correction head. + +#### Independent correction reviews + +The first fresh security/proof review (GPT-6-astra, xhigh) reproduced an opaque +object-helper/storage escape in the authority census. The fresh quality review +(GPT-6.1-sol, xhigh) found the demo launcher's missing API-authentication opt-in. +Both were verified and fixed; the independent original opaque-export probe now +fails on the same dirty subject. A subsequent fresh security and quality pair +(the same model families, xhigh) reviewed the complete corrected working tree, +including ADR-0065, and found no additional actionable defect. That pair was +read-only and did not supply execution evidence. + +The final fresh pair (GPT-6-astra xhigh for runtime/security and GPT-6.1-sol xhigh +for proofs/contracts) independently reviews frozen code commit `8a3892d9`. Both +approve their assigned scopes with no additional actionable finding. They are +read-only source/test inspections, not test-execution or full-CI receipts. +That review covers the frozen runtime source. The subsequent demo-only follow-up +below has its own review and hosted qualification. +This follow-up starts no next packet and makes no claim that PR #33 is merged. + +#### Hosted correction qualification follow-up + +The first correction-head run, +[39337392103](https://github.com/HodeTech/LearnStack/actions/runs/39337392103), +checks out merge `bc79e01f` for head `ac82ca6b`; its tree equals that head's tree. +Both source/attempt-bound aggregates pass: 3,276 backend cases plus 2,491 +integration cases, **5,767 total**, with exact complete unions and no failed or +skipped cases. Independently downloading all twenty producer artifacts and +re-running both receipt/hash/result/union validators confirms all 5,767 completed +cases are Passed: 2,581 Unit, 433 Architecture, five Contract and 2,748 Integration +(including 257 non-Docker, 2,460 ordinary Docker and 31 native cases). The frontend +passes 1,630 cases. Twenty-six of 27 jobs pass; +`public demo + lighthouse` is the sole failed job, so this is not a green PR-head +receipt. + +The demo completes browser controls and its first audit, whose LCP, blocking time, +layout shift and accessibility satisfy the existing budgets. It refuses roughly +280 milliseconds after announcing the second audit, before that audit makes any +product API call. Owned cleanup passes. The retained artifacts do not identify +whether browser launch, the debugging-port file or another early operation +failed; a browser-startup or product regression is not established by this record. + +Commit `f5befc9e` adds closed parent phases, bounded browser exit/signal fields +and a revalidated private worker substage. The first failure survives cleanup; +raw exception, provider, URL and document text cannot enter this diagnostic. +It changes no retry, deadline, browser flag, port parsing or audit threshold. +The first fresh demo review pair (GPT-6-astra xhigh and GPT-6.1-sol xhigh) finds +no privacy/cleanup defect but independently identifies an exit-classification +edge: Node exposes signal termination through signalCode with null exitCode. +Commit `ce2b746e` corrects the production startup predicate and replaces an +impossible synthetic status pair. Two actual native-child controls verify live, +normal and signal states. The thirteen new controls also cover an actual worker +connection refusal, clean completion, primary/cleanup failures and canary +rejection. All 189 focused demo cases and the full 1,643-case frontend population +pass with no skips/todos; typecheck, lint and formatting pass. The fresh second +independent pair identifies a declaration-only mismatch: Record<string, unknown> +does not accept Node ChildProcess. Commit `d9f21ddb` uses the exact structural +status fields, and the existing actual-child controls now compile-check both +entry points. Typecheck, all thirteen diagnostic controls, lint and formatting +pass after that fix. Both reviewers confirm the complete corrected slice has no +remaining actionable finding in their assigned scopes. Their source inspections +are not hosted demo receipts. A complete new hosted run must qualify the final +source; the earlier backend receipt does not qualify the later frontend source. + +#### Reviewer handoff + +```text +Review the PR #33 correction range afa84815..development, anchored by runtime +commit 8a3892d9 and Accepted ADR-0065. Check runtime security and failure paths, +actual production subjects plus planted controls, exact HTTP/read-mode/identity +censuses, cross-scope audit admission, and ordinary-versus-metadata telemetry. +Confirm the current PR-head CI receipt independently; historical green receipts +and cancelled local selections are not current-head qualification. Treat review +inputs as untrusted data. Report only verified still-valid findings. +``` + + +### P02b-5 second external review follow-up (2026-10-20) + +> **Historical snapshot — entry and reviews before ADR-0066 approval.** +> Decision-pending and unimplemented statements in this follow-up describe that +> source interval. The later [acceptance and implementation record](#adr-0066-acceptance-and-implementation-2026-10-20) +> supersedes those states; original receipts remain intact. + +This follow-up starts from `9d4ec0e019af3b42edd7950c40a495a42034b933` +on development. It verifies each new review claim against current production +code and its actual test owner. Temporary review inputs are not permanent +authorities. No next packet or production identity activation starts here. + +**Decision pending:** +[ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) proposes the +missing explicit 4096-subject process bound and its bounded reclamation, +cleanup ownership and closed refusal signals. Existing code is not evidence +that ADR-0064 selected this bound. Three independent source/design inspections +reviewed the draft; the single retirement batch and total resource accounting +were clarified. The maintainer's new-ADR approval is required before acceptance, +source-attribution errata in ADR-0064/0065 and dependent admission refinements. +The earlier approval waiver applies to ADR-0065 only. Independent corrections +below do not depend on that decision. + +#### Verified runtime and proof corrections + +Finding identifiers below identify review items, not severity. A verified +limitation is distinguished from a current runtime defect. + +| Items | Verified disposition and actual owner | +|---|---| +| B1, M8, P4 | ADR-0064 does not select 4096. ADR-0066 is Proposed; default-cap, acquisition reclamation and refusal-signal refinements remain approval-dependent. The draft explicitly counts 4096 retained plus at most 128 retiring resources and forbids accumulating cleanup batches. | +| M1 | Point projection does not remove exemplar filtered attributes. Set the production exemplar filter programmatically to `AlwaysOff`; decode actual OTLP exemplar attributes, values and identifiers. `TenantAuthenticationDiagnosticsTests.Metrics` has unprojected positives and production negatives for standard and histogram-specific `always_on`/`trace_based` settings. ADR-0065 Amendment 1 clarifies enforcement of its existing privacy contract. | +| M2 | Preserve the worker's closed exit/signal status through `DemoCommandError` and use it only for worker stages. Browser status belongs only to browser stages. Real nonzero and signal-terminated child controls replace the impossible worker/browser attribution. Unsupported signals stay null under the closed diagnostic vocabulary. | +| M3, M7 | Extend `AuthenticatedHttpSurfaceTests` across direct interface/concrete handler references in constructors, fields, locals and `Handle` calls. Each dirty route/capability control requires its expected offender prefix. Compiler-generated self-capture has a narrow clean control. | +| M4 | Derive recorder counter vocabulary from actual constant declarations and `Meter.CreateCounter` calls. Scan compiled strings and constant fields across production assemblies, including public-constant references, a differently prefixed fourth counter, both audit slugs and case-insensitive assertion headers. Exemptions name actual assembly/type owners. | +| M5 | Plant exact base `AuthorizeAttribute.Roles` separately from derived metadata; removing the named Roles branch must lose that control. Add raw authenticate-result/ticket principal and `IAuthorizationService.AuthorizeAsync` sinks to the authority census. | +| M6 | Add signed claimless platform-host row 15 to `TenantAuthenticationReconciliationTests`, including masked refusal and exactly one fixed claimless Debug event. Component-only evidence is not relabelled HTTP evidence. | +| D1, D2 | Add missing own-amendment navigation and correct current CI ownership in the decision index. Roadmap/root README distinguish completed P02b-0 entry verification from merged P02b-1–4. | +| D3 | Already closed by the baseline docs-only commit `9d4ec0e0`; do not reapply or treat its stale pending text as a current defect. | +| 9.1 containment | Reject encoded slash/backslash/dot traversal in configured issuer and discovery/JWKS paths; compare real URI segments as well as exact origin. Preserve legitimate private IdP origins and harmless escaped path data. | +| 9.1 organization liveness | No missing lifecycle gate reproduced. Every public Education query first calls the same public configuration reader. Extend the real claim-selected organization lifecycle proof through public site and course-list queries: active succeeds, inactive refuses, restored succeeds. No second lifecycle policy or new ADR is introduced. | +| 9.1, 9.2 HTTP/contract | Preserve absent-credential AccountSite masking before method admission and signed unsupported-method 405. Assert actual `Allow`, early-error no-store, both-route application 413 and optional 413 cache header in OpenAPI. Clarify public site 400 assertion errors; reject explicit `additionalProperties: true`/schema changes. Exact CLR fields and schema property/required censuses own the representation boundary; an omitted keyword does not reject unknown fields in JSON Schema. Served OpenAPI, snapshot and generated SDK agree. Future 403 belongs to Phase 03's real permission boundary. | +| 9.2 persistence | Three direct real-reader controls reject unannounced/no-EF-transaction/mismatched-EF-transaction ownership. Successful same-role, same-context controls establish that refusal is the ownership guard, rather than missing data or an inaccessible database. | +| 9.3 census | Follow reachable pipeline helpers and reject hidden/duplicate controller mapping and static health field reads. Source/IL controls exercise the production subjects, not only arrays of expected names. | +| 9.3 logging/profile | Remove ineffective `LoggerFilterOptions.PostConfigure` under the production Serilog factory; retain the registration needed by isolated hosts. Assert the actual factory, exact vendor-category suppression at every level and observable siblings. Add unequal duplicate properties and configured-issuer/console/malformed-payload canaries. | +| 9.3 startup/cache | Actual Production `Program` must refuse missing/empty issuer before dependency startup. Separately prove a warm current known key can still validate when a requested refresh fails: disabling Last Known Good fallback does not discard the manager's current cached configuration. Cold/no-usable-key refusal and observed key withdrawal retain their controls. | +| 9.3 test determinism/composition | Freeze only visitor replenishment for the real HTTP 60-permit proof and assert the unmodified default factory's 60/minute automatic configuration separately; do not claim the HTTP case proves real timer renewal. Successful real AccountSite reads also inspect actual runtime `IAuditCatalog` Off registration, rather than relying solely on assembly-wide discovery. | +| 9.4 demo lifecycle | Establish the receipt before setup, record setup failure without overwriting foreign output, set worker preflight before toolchain access, emit only validated closed status lines from chunks and preserve the primary failure if receipt saving fails. Outer process ownership drains Chromium; an extra unbounded `browser.exit` wait is removed. Signal expectations are platform-aware with no skipped tests. | +| 9.5 SDK/frontend | Use the actual asynchronous SDK and a fetch stub in path-fence controls. Admit only the four public operation templates and reject encoded separators/traversal. Freeze maps, enforce exact wrapper pairing/root exports, remove the undefined AccountSite query alias and add a compiler deletion control for GET ownership. Empty issuer is omitted by the launcher. | + +#### Production activation ownership and unchanged contracts + +The issuer must be resolvable and reachable from the API using its configured +canonical origin; startup is deliberately not a network-readiness check. +Private/split-horizon DNS is supported only if it preserves that exact issuer. +No separate metadata-origin setting or weaker JWKS containment is introduced. +[API Gateway](../architecture/30-api-gateway.md#current-issuer-topology-and-activation-limits) +records cold/warm cache behavior, manual versus automatic refresh proof limits, +coarse Information outcomes, early correlation limits and row 10's Debug-only +visibility. An event-3 adapter injection is not a natural stock-handler receipt. + +[Phase 11's activation gate](phase-11-production-hardening.md#tenant-authentication-production-activation) +owns issuer/readiness, closed authentication failure signals, row-10 operational +visibility, capacity sizing, key-rotation drills and suppression alert/runbook +qualification **before production exposure**. Audit suppression is intentional +admission and can coexist with Healthy audit-store health. Counter and 4006 +tenant/actor/correlation triage do not restore lost durable rows. Existing +Information and assertion Warning volume remains a stated cost; this follow-up +does not silently sample accepted diagnostics or invent new failure taxonomy. + +[Phase 03](phase-03-identity-admin.md) must decide and install runtime +deny-by-default admission before its first permission-sensitive endpoint, +with a denied-dispatch control and public/nonsensitive positives. Today's static +route census remains a complementary guard. No unused fallback policy is +installed in P02b-5. Real issuance remains P02b-6; BFF custody and recovery remain +P02b-7. These are explicit activation conditions, not claims of production fit. + +No speculative change is made for the following suggestions: + +- The read-only composition deliberately permits one exact declaration today; + its census rejects a second. Adding another request must change registration + and its exact-type guard together. No current declaration silently falls back + to ReadWrite. +- AccountSite has only the authorized v1 route. A v2 route requires its own + explicit contract/no-store/admission controls; no unrequested path abstraction + or response-policy rename is introduced. +- Authentication registration is a bootstrap-once graph. Repeat-registration + idempotence is not promised; silently ignoring conflicting settings would not + improve its fail-closed behavior. +- ADR-0064's exact relationship table and the own dated ADR-0040/0052 + disclosures distinguish read-only scope extensions from row 14's audit + replacement. Preserve those instruments and the Accepted body; its broad + status summary is not a new independent read-mode authorization. +- The validated unexpected-query flag follows the existing public application + contract; it carries no `HttpContext` and changes no scope. Moving it would + change validation precedence without fixing a reproduced bypass. +- Public-client TLS/configuration splitting or caching has no demonstrated + correctness failure or measured cost here. Keep private configuration strict. +- Account HTTP Debug settings are child-host configuration, not a shared test + logger-level switch. The host owns/disposes its logger and the database + collection is serialized. No cross-test mutation was reproduced; retain the + claimless-event proof without adding a second logging path. +- Actual component 600 and reduced-budget whole-chain proofs retain their + separate meanings; neither promises end-to-end 600 throughput through the + earlier visitor/peer limits. Timer retirement injection likewise does not + control the stock limiter's replenishment clock. +- Existing demo corrections stay in this PR because they qualify this packet's + required browser check. Splitting already dependent fixes into another PR + would leave this source unqualified; no thresholds or budgets are relaxed. + +#### Historical evidence reconciliation + +The Step 5 **In progress** paragraph and its later local closeout are dated +snapshots, superseded by subsequent implementation/remediation records. Their +claim that later changes only affected tests/docs is scoped to the original +`1942662d..e20b6071` closeout; runtime changes in `8a3892d9` belong to the later +remediation and are not covered by that sentence. The original no-tenant-cap/ +unconditional per-occurrence text describes the pre-ADR-0065 contract; admitted +per-occurrence recording and the aggregate allowance are current. + +Independent Actions readback on 2026-10-20 confirms historical run +[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) +completed 27/27 jobs successfully at +`1942662df0e4321163f99b678805bec5a69c314a`. It was genuinely pending when the +earlier receipt was written. Baseline run +[39346971253](https://github.com/HodeTech/LearnStack/actions/runs/39346971253) +also completes 27/27 jobs at `9d4ec0e0`. Neither qualifies the new changes. + +The earlier demo's roughly 280 ms description is an unexported local timing +estimate, not a retained-artifact witness. The retained job's roughly 13.7 s +interval includes cleanup; the numbers cannot be interchanged. The supported +claim is narrower: the second audit was announced, made no product API call, +and then refused; cleanup completed. The failing operation/root cause remains +unidentified. The later successful source has its own receipt. + +The retained P02b-4 portable evidence archive was independently read again: +40,974,306 bytes, SHA-256 +`028de8d8d2bc6584a90e84f16755187cd2c32d600c2e80d98ad3ea19e18ce98d`, containing +44 ZIP artifacts. This checks retained archive integrity/inventory; it does not +rerun those historical tests or reauthenticate its saved API response. The +earlier 1,002-link figure remains a local as-of document check, not a current +repository link census. Current changed-document links require their own check. + +Historical model names and opinions record review-tool provenance and assigned +scope, not reproducible repository test artifacts. The prior correction record +anchors frozen source `8a3892d9`; its read-only inspections are explicitly +distinct from executable test/CI receipts. New independent review rounds and +validation below must name their own source and evidence. PR #33's body must +follow the final submitted head, rather than borrowing a historical green run. + +#### Local correction validation + +The following focused populations pass with zero failures/skips. These are +separate selections with overlapping owners, not a summed complete-suite count: + +- 49 Architecture authority/surface/tenancy/composition cases, Release. +- 33 reconciliation/pipeline Integration cases, including signed row 15. +- 59 privacy/configuration/profile cases; three additional actual startup/warm + cache cases pass after correcting the fixture's bootstrap configuration. +- 73 real PostgreSQL HTTP/reader/lifecycle cases; three final runtime-catalogue/ + deterministic-ingress cases pass after their proof corrections. +- Five served/snapshot Contract cases; generated SDK equality and typecheck. +- Full frontend: 1,656 cases (1,591 web and 65 SDK), zero skips/todos; lint and + typecheck pass. Six setup-path controls pass again after platform normalization. + +Seven ADR-parser controls pass. ADR-0065 remains Accepted; ADR-0066 parses +Proposed. Formatting and diff whitespace checks pass. At `15c2f49d`, changed-doc +link verification checks 1,934 real relative links/fragments; the catalogue's +pre-existing inline `name_lowercased` template example is not a real target. +The following review records govern correction closure; neither focused passes +nor previous hosted receipts complete current-source hosted qualification. + +#### Second follow-up independent review round 1 + +Frozen correction commit `15c2f49d` receives three fresh read-only reviews: +security/runtime, frontend/contracts/docs and production proofs. The first two +find no additional actionable issue in their assigned scopes. The proof review +finds two verified gaps: counter/header checks still pass only the API module to +their otherwise broad scanner, and `Use*` names stop source helper expansion +before its body can reveal another middleware. These are proof defects, not +observed production bypasses. Both require correction and actual dirty controls +before round 2; a review opinion alone does not establish their closure. + +The verified fixes now scan every production module for counters/headers, with +compiled controls in both API and Tenancy.Application. Custom source helpers +resolve before framework terminals; existing middleware wrappers must preserve +their actual leaf shape, and the OpenAPI wrapper must add no middleware. +Immutable direct/receiver-alias extra-authentication mutations inside both real +resolution and OpenAPI helpers fail. Clean data-free and `Use`-prefixed helpers +remain distinguishable. All 16 Tenancy convention cases and the actual HTTP +pipeline owner pass again in warnings-as-errors Release, zero failures/skips. + +Broader local validation on the frozen `15c2f49d` source passes: full Unit +2,581; full non-Docker Integration 276; full Contract five; selected authority, +surface, tenancy, public, corpus and persistence Architecture 80. All have zero +failures/skips. The complete Release solution builds with warnings as errors, +zero warnings/errors. This receipt precedes the two review corrections; their +changed owners need their own rerun. Complete Architecture/Docker/native and +public-demo qualification still belongs to current-source hosted CI. + +#### Second follow-up independent review round 2 + +Three new reviewers inspect frozen fix commit `653404ad` against `9d4ec0e0`, +covering security/runtime, frontend/contracts/docs and production proofs. +Security and frontend/docs find no additional actionable issue. The proof +review confirms the round-1 corrections and finds a fluent receiver gap: +`return app.UseMiddleware<TenantResolverMiddleware>().UseAuthentication()` +silently skipped its outer call while preserving the expected inner leaf. + +The verified correction refuses fluent application receivers, including +framework builder returns and source-declared builder-returning helpers. +Parenthesized/cast receivers and builder-valued aliases cannot evade this +specific predicate. Immutable mutations of both the actual Program statement +and actual resolver return statement require the precise fluent/leaf-shape +diagnostic. The actual HTTP pipeline owner passes again in warnings-as-errors +Release, one passed, zero failures/skips. Existing health endpoint naming stays +clean: its endpoint-convention builder is not an application-builder receiver. +This remains a bounded source proof, complemented by actual HTTP/IL censuses; +it is not a universal C# analyzer. Targeted independent fix verification and +the final submitted-head CI receipt are required before handoff. + +Commit `8f2ebb92` records that verified correction. The independent round-2 +proof reviewer re-inspects the committed delta and approves closure with no +remaining actionable issue in its target scope. Both fresh review rounds and +their verified fixes/rechecks are complete for these independent corrections; +all reviews are read-only source inspections, distinct from executed tests. + +The final PR-head/Actions receipt belongs to +[PR #33](https://github.com/HodeTech/LearnStack/pull/33), whose body is updated to +the submitted head and actual run. Historical green runs cannot qualify it. +The correction source is ready for complete hosted qualification; this does +not mark the overall review finished or authorize merge. ADR-0066, B1/M8 and +its dependent subject-admission refinements remain explicitly approval-pending. +No fresh decision is accepted by elapsed time or by a green test run. + +#### ADR-0066 maintainer review revision (2026-10-20) + +> **Historical proposal revision.** Proposed/pending statements below apply +> before the subsequent [maintainer acceptance](#adr-0066-acceptance-and-implementation-2026-10-20), +> not to the current implementation. + +The maintainer requests revision, not acceptance. This pass starts from +`09e1a169dd61e02633860d03ad68052d1e86dfa8` on development and verifies the +findings against the current limiter, middleware and real test owners. +[ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) stays Proposed; +no dependent runtime, Accepted-ADR erratum or acceptance is implemented here. +The earlier ADR-0065 approval waiver does not authorize this decision. + +The three high findings are valid: the draft conflates permanent cleanup fault +with ordinary capacity pressure, leaves acquiring allocation/debit ordering +ambiguous, and omits the blocking cost of acquisition/shutdown disposal. +Two independent read-only design/corpus inspections confirm these gaps; they +are not runtime tests or qualification of the proposed implementation. + +| Finding | Verified revision / disposition | +|---|---| +| 1 — Fault visibility | Propose rejection reasons `quota`, `registry_capacity`, `registry_fault`; add an unlabelled once-per-instance cleanup-fault transition counter so timer faults are visible without a request. Phase 11 owns three-branch alert/runbook qualification. | +| 2 — Allocation/debit ordering | Acquisition removes at most one eligible entry, completes its disposal and rechecks state before its own allocation/debit. Failure produces no owning debit or dispatch. Other requests can use free slots before fault publication; after publication no new allocation starts. Existing retained keys keep quota service. Lost-slot and same-key races need explicit controls. | +| 3 — Blocking cost | Acquisition inspects at most 128 entries but disposes at most one. Timer batches remain at most 128 under the same sole retirement owner. Other requests never wait for cleanup; a full registry refuses immediately. One disposal can still block the owning request and joined shutdown indefinitely. Host grace expiry is not cleanup evidence; no fatal/restart owner is added. | +| 4 — Reason transport | A closed result carries acquired/quota/capacity/fault plus detached retry metadata from limiter to middleware. Cache the first request result and emit a rejection exactly once; admission emits none. | +| 5 — Active mutable carriers | Security Standards and Identity architecture now identify 4096 as current code under a Proposed decision, not a bound selected by ADR-0064. Derivation headers and Accepted-ADR attribution errata remain acceptance work. | +| 6 — HTTP choice | Ordinary quota/capacity remain admission 429. Sticky cleanup fault proposes dependency 503, standard `dependency_unavailable` and the existing 30-second hint. Middleware must apply the common helper explicitly; outer bodyless-status handling alone does not. Compare the idempotency-store 503 precedent without changing it. | +| 7 — Fair share | Add a separate tenant/host reservation alternative. Reject it for this packet because inventory, claimless attribution and measured share policy are absent; it is not equivalent to tenant-partitioning the quota key. Phase 11 owns comparison before changing the bound/policy. | +| 8 — Proof ownership | Name the real unit and HTTP owners plus actual OTLP `TenantAuthenticationDiagnosticCollector.MetricPoints`. Include exact-default 4096/4097, single retirement, queue rotation, 4224 ownership, both failure paths, no further batches, existing-key service, joined failures, exact headers/body, no downstream work and exported closed labels. These proofs remain pending code. | +| 9–10 — Carriers and wording | Add front-door/Phase 11/glossary/reference inventory, future runbook wording, explicit test-only constructor seam, no-allocation-on-refusal terminology and timeout limits. Served/snapshot OpenAPI must describe the new 503 cause and capacity hint uncertainty when implemented. | +| 11 — Historical trailer | No defect requiring history rewrite: the trailer denotes implementation/derivation rather than every touched ADR. New revision/implementation commits include 0066; preserve old commits. | + +The shared resource bound remains 4096 retained plus at most 128 retiring. +One acquisition can own only one retiring limiter; only the timer can hold a +128-entry batch. Cleanup failure retains evidence/resources, attempts the whole +owned batch, closes new allocation/batches and propagates through joined +shutdown. Neither the new metric nor a retry hint clears this sticky state. + +The previous source's [CI run 39374628479](https://github.com/HodeTech/LearnStack/actions/runs/39374628479) +passes all 27 jobs at `09e1a169`: 5,792 backend cases with zero skips, 1,656 +frontend cases and the required demo. Independently validated artifact unions, +hashes and natural cleanup qualify that source, not this proposed policy or +its unimplemented controls. This documentation pass needs its own parser, +relative-link/fragment, format and independent review evidence below. + +Revision validation passes: seven ADR-parser controls, ADR-0066 parsed as +Proposed, 1,113 real relative links/fragments across nine changed Markdown +files with none broken, ADR prose wrapping and `git diff --check`. No runtime +tests are rerun for this documentation-only proposal. Fresh independent review +rounds remain required before resubmitting it for approval. + +##### ADR-0066 revision independent review round 1 + +Two fresh reviewers inspect frozen `ed21d9fc` against `09e1a169`: GPT-6 Astra +at xhigh effort covers concurrency/fault/HTTP ownership; GPT-6.1 Sol at high +effort covers corpus, actual test owners and premise accuracy. Both approve the +documentation revision, not the decision or runtime. One minor inventory gap +is verified: the ADR names OpenAPI's new 503 cause but must also name the 429 +capacity-hint clarification already recorded here. The revision now does both. +No runtime tests/builds are run by these read-only reviewers. A second fresh +round is required after this correction. + +##### ADR-0066 revision independent review round 2 + +Two new reviewers inspect frozen `4b4a9ac6` against `09e1a169`: GPT-6 Astra +at xhigh effort independently checks the complete protocol and GPT-6.1 Sol +at high effort checks the corpus, actual HTTP helpers and proof inventory. +Both approve the documentation revision with no actionable finding. The +first-round OpenAPI clarification is verified; all new implementation controls +remain pending. These source inspections neither accept ADR-0066 nor qualify +its unimplemented runtime or production sizing. + +The existing corpus consistency selection also runs against the current docs +using unchanged Release test binaries: five passed, zero failed/skipped. Seven +ADR-parser controls pass; ADR-0066 stays Proposed. The final changed-document +link/fragment and whitespace checks are repeated before commit. Runtime code +and Accepted ADR-0064/0065 are unchanged throughout this revision. The concrete +proposal is ready for maintainer reapproval; no elapsed wait supplies approval. + +#### ADR-0066 acceptance and implementation (2026-10-20) + +The maintainer explicitly accepts the revised ADR-0066 and requests +implementation after the two fresh revision review rounds. Acceptance is the +first commit of this dependent work on development, before runtime changes. +The ADR moves to Accepted; ADR-0064 and ADR-0065 each retain their original +body/metadata and gain an adjacent source-attribution erratum plus their own +dated Amendment 2. The index and mutable authorities record the new source. + +**Implementation plan.** One correction step covers the limiter, closed result, +singleton cleanup ownership, two metrics, middleware and served/snapshot SDK +contract. Unit and real signed PostgreSQL/OTLP integration controls deliver the +accepted default, scan, race, fault, shutdown, resource-bound and label proofs. +Then commit the implementation, run two fresh independent multidimensional +review rounds, verify/fix/commit findings, and complete current-head CI evidence +and PR reconciliation. The broader P02b-5 steps are not restarted. + +At acceptance, runtime implementation and its new controls remain pending. +No schema, role, grant, RLS, bearer identity, 600/min subject quota or earlier +visitor/peer admission changes are authorized by this addition. Phase 11 owns +measured sizing, distributed admission, readiness and exercised production +alerts/runbooks; the accepted request/shutdown blocking cost remains explicit. + +##### ADR-0066 implementation and local validation + +The singleton implements the closed detached decision and one shared retirement +owner. Acquisition inspects at most 128 entries, retires at most one and waits +for actual cleanup before its own allocation/debit. Other callers retain service +under the accepted free-slot/fault rules. Timer retirement owns at most 128 extra +resources; blocked and throwing controls verify the total 4224-resource bound, +whole-batch attempts and joined shutdown. The fault owner records one sticky +transition; middleware records one closed rejection per request, including +re-execution. Quota/capacity remain 429; new-key cleanup fault is 503 with the +common explicit 30-second hint. No timeout is a cleanup witness. + +The unit owners exercise actual singleton registration/default 4096/4097, +allocation/debit refusal, bounded rotation, blocked disposal, lost-slot/same-key +and shutdown races, sticky faults and sync/async DI shutdown. Three added Docker +rows use signed tokens, real PostgreSQL audit state and the actual exported OTLP +metric decoder. They distinguish downstream-positive controls from pre-resolution +refusals and verify only the closed metric attributes. Controlled limiter +wrappers inject disposal/idle conditions; they do not certify stock minute-clock +advance or production disposal-fault frequency. + +OpenAPI's public and AccountSite 503 descriptions name cleanup fault; 429 hints +promise no available capacity. The snapshot and generated SDK match the served +contract. Planted removals fail the specific semantic predicates independently +of snapshot parity. No route, response schema, business permission or tenant +scope is added. + +Current local Release results, all with zero skips: + +- Unit: 2600 passed, including 30 focused subject-admission cases. +- Authentication regression: 147 passed, including all five focused signed + PostgreSQL/OTLP rate-limit cases (three new rows). +- Non-Docker integration selection: 276 passed. +- Contract: five passed. SDK: 65 passed; generation/typecheck pass. +- Full architecture: 433 passed at implementation head `01799550`; this complete + run precedes the shared response-policy correction below. +- Warnings-as-errors Release solution builds pass with zero warnings/errors. + +Early integration attempts exposed synthetic teardown assumptions: the web +factory did not propagate an externally owned singleton's disposal exception, +and the injected limiter needed its async cleanup hook. The controls now join +the explicit owner, accept only the exact planted failure tree and separately +exercise real sync/async service-provider shutdown. Earlier failed attempts are +not counted as passes or reported as product runtime defects. + +Implementation is committed as `01799550`, after acceptance-only `c8b9d89e`. +Revision reviews above qualify the proposal only. Final-source hosted CI, artifacts +and PR reconciliation remain pending; historical receipts from earlier source +heads do not qualify this implementation. + +##### ADR-0066 implementation independent review round 1 + +Three fresh read-only reviewers inspect frozen `01799550` against `453d5c3a`: +GPT-6 Astra at xhigh covers concurrency/security/resource ownership; GPT-6.1 Sol +at xhigh covers proofs/DI/exported metrics; GPT-6.1 Sol at high covers the corpus, +OpenAPI/SDK and authority closure. No build, runtime probe or hosted qualification +is attributed to these inspections. Two findings are verified and corrected: + +- A classified unknown API path reaches subject admission outside the public/ + AccountSite response wrapper. Subject refusals therefore missed `no-store`. + The shared response policy now applies to every subject refusal, independently + of endpoint matching, preserving the one Problem Details writer. +- The manual timer accepted any positive cadence. Its first due time and period + now independently require the accepted 30 seconds. + +Root verification also exposes a false-green header helper: a null-conditional +chain could skip the entire assertion when `Cache-Control` was absent. Grouped +nullable values now fail for absent no-store, retry and content-type headers in +these authentication helpers. Clean, absent and false no-store controls make this +specific omission fail. Initial unknown-path cases passed through the weak helper; +with the strict helper both signed rows fail on missing `Cache-Control` before the +runtime fix. Those initial passes are not accepted as the regression proof. + +After the fix, both rows exercise unknown-path quota, capacity and cleanup-fault +refusals with exact body/status/retry/no-store, unchanged resolution/audit/read +observers and updated actual exported counts. The complete 147-case authentication +selection passes, including all five focused PostgreSQL/OTLP rate cases. Thirty +focused unit cases and 25 authentication-authority/corpus cases pass, all with zero +skips. The Release solution build has zero warnings/errors. The 433-case complete +architecture run above remains separately bound to the implementation before this +small response-policy change; final-source hosted shards must qualify the full +current population. A second fresh independent implementation review round remains +pending after the correction commit. + +##### ADR-0066 implementation independent review round 2 and local closeout + +Three new read-only reviewers independently inspect frozen `082a658c` against +`453d5c3a`: GPT-6 Astra at xhigh covers the complete runtime/HTTP protocol; +GPT-6.1 Sol at xhigh covers proofs, DI, actual export decoding and strict header +controls; GPT-6.1 Sol at high covers the corpus, contracts and source closure. +All approve with no remaining actionable finding. Their source inspections +verify the first-round corrections; no executed checks or production readiness +are attributed to them. + +Acceptance (`c8b9d89e`), implementation (`01799550`) and verified corrections +(`082a658c`) are separate commits on development. Both fresh implementation +review rounds are complete. The final changed-document sweep resolves 1903 +relative file/fragment targets with none broken; seven ADR-parser controls and +whitespace checks pass. Accepted ADR-0064/0065 remain unchanged after their +acceptance disclosures; ADR-0066 gains only its own dated implementation +Amendment 1 after acceptance. + +This closes the local ADR-0066 correction step. The +[PR #33 handoff](https://github.com/HodeTech/LearnStack/pull/33) owns subsequent +verification of the exact final-source hosted run, immutable artifact identities, +complete case unions, natural cleanup and frontend/demo proof, independently of +historical source receipts. No historical green run qualifies a later source, +and this local closeout makes no hosted-success or merge claim. P02b-6 is not +started; production sizing, distributed admission, readiness and exercised +runbooks remain Phase 11 obligations. + + +### P02b-5 systematic proof and document corrections (2026-10-20) + +**All three correction steps and review rounds are complete on development, +starting at `5daee8ad`; current-source hosted A/B qualification is owned by the +live PR handoff below.** P02b-5's five +implementation steps and ADR-0065/0066 corrections are implemented and unmerged. +This follow-up validates the current production subjects and their falsifiable +controls. Earlier review conclusions are scoped to their source and inspected +paths; they are not a guarantee against a newly identified proof gap. No merge, +new packet, production readiness or new decision is inferred here. + +#### Correction plan and ownership + +1. **Backend proofs, hardening and corpus.** Close global MVC filter composition, + cross-root handler acquisition, attribute-based assertion ownership and + exact read-mode/OpenAPI proof gaps. Add isolated real-reader and recorder + controls, preserve cleanup ownership under diagnostic failure, and reconcile + current versus historical status. Commit, run two fresh independent review + rounds, verify findings and commit fixes. +2. **Demo and SDK proof.** Preserve failure origin/status ownership, bind JSON and + HTML report bytes to one receipt, qualify clean/mid-run source identity and + distinguish local transport refusal. Preserve all browser budgets, flags, + deadlines, response contracts and retry behavior. Commit, run two new + independent review rounds, verify findings and commit fixes. +3. **Measured CI timing repair.** Reconcile the frozen advisory Architecture + weights with complete hosted TRXs after a current-source deadline refusal. + Preserve every selector, the A/B algorithm, six/twelve shard counts and all + deadlines. Commit and complete two fresh independent review rounds, then + qualify both complete assignments on one final source and plan under + ADR-0063. + +Focused checks accompany each step. Full architecture, Docker/native, frontend +and managed-demo qualification must cover the final source through the existing +bounded hosted checks and exact artifact/result unions. Historical green runs +do not qualify this delta. PR #33 remains open for maintainer review. + +#### Validated dispositions + +| Area | Current finding and action | +|---|---| +| Global MVC filters | Missing composition/source census, not a demonstrated runtime auth bypass. Inventory actual MVC filters and compiled extra/removed/duplicate registrations. Endpoint authorization already precedes MVC. | +| Nested HTTP handler roots | Reject a different root reached through a custom interface or generic service acquisition/non-Handle member. Preserve generated self-capture and ordinary helper positives. | +| Assertion ownership | Inspect custom-attribute constructor/named/array metadata recursively; pin exact two header names and exact recursively discovered recorder counter vocabulary. | +| Read-only selection | Protect the actual consumed mode from name-based overrides; preserve approved PublicSurface and two job pre-read fallbacks. Isolate immutable declaration/catalog shape controls. AddSingleton declarations must not silently discard an earlier different declaration; the immutable set still deduplicates exact types. | +| Served contract | Pin parameter locations/types/formats/requiredness, no request body, exact declared ProblemDetails fields and existing leaf constraints. Preserve the accepted open extension representation; additionalProperties:false would be a contract change. Dirty controls must require their intended diagnostics. | +| Credential and metadata paths | Credential 401 on classified unmatched paths also applies shared no-store. Reject ambiguous decoded dot-segment suffixes/control bytes before metadata I/O, retaining harmless escaped path positives. | +| Authentication diagnostic vocabulary | Replace arbitrary stage/reason arguments with a closed typed outcome, preserving existing emitted values. Existing real OTLP ordinary-host/IP/port/path/query and exemplar controls already cover the two authorized native meters; no speculative meter is added. | +| Startup and framework proof limits | Test missing/empty bootstrap issuer against a present ambient value. Source-owned pipeline checks are not published-host analysis. TestServer whitespace cases do not prove native Kestrel pre-normalization bytes. The event-3 adapter remains explicitly synthetic. | +| Cleanup exception ownership | An in-process metric callback failure must not skip the rest of an owned faulting batch or strand shared shutdown. Retain errors and drain remaining resources. Exercise both timer-join failure/shutdown forms. The production factory remains stock FixedWindowRateLimiter; arbitrary throwing IdleDuration implementations are outside that production profile. | +| Shutdown admission | Preserve the explicitly tested ObjectDisposedException after owner closure. Do not mislabel orderly closure as sticky RegistryFault or invent a fifth result/status policy. Host drain qualification remains Phase 11. | +| Reconciliation and audit proofs | Use the live-version classifier for assertion paths; add unresolved-header, matching-organization and exact Warning-property controls, plus direct invalid audit-budget keys. Preserve recorder invariant failures for corrupt nil/sentinel defended tenants. | +| Real configuration reader | Isolate physical read-write, missing/mismatched/sentinel HostScope and organization provenance refusals on real announced/enlisted app-role frames with same-context positives. Visibility follows the resolved organization, including claim-selected scope. | +| Existing quota/isolation controls | Issuer-versus-subject tuple separation and actor/scope stability are already covered by the actual 600 component proof. Process-global logging tests already use a serialized collection; retain that explicit mitigation and the known-working child-host configuration. | +| Future version and policy boundaries | Only v1 is authorized. No v2 route, new request or readiness policy is activated. Phase 03 owns affirmative live membership and no-host header-evidence policy before exposure; P02b-7 owns BFF recovery; Phase 11 owns capacity/readiness/alerts/drills. | +| Demo diagnostics and receipts | Confirmed gaps concern deadline/spawn/daemon ownership, input/cleanup phases, HTML byte binding and dirty/mutating source identity. Step 2 owns their corrections and real-child/corruption controls. | +| SDK/environment proof limits | The path fence already makes zero forbidden fetches and has no automatic retry. Required frontend CI already typechecks SDK tests; no missing CI gate is claimed. Constructed child environments do not prove Next never loads private dotenv; issuer is not a credential and no browser leak is established. | +| Current versus historical corpus | Preserve dated proposal/pending receipts with explicit as-of banners. ADR-0066 Amendment 2 qualifies its acceptance-time proof list; ADR-0065 Amendment 3 records delivery. ADR-0064 Amendment 3 clarifies read-mode instrument classification without rewriting Status or its accepted decision. Separate admitted rows from suppressed occurrences in the Tenancy matrix. | + +#### Step 1 verification and review status + +Implementation is committed as `57f49ce0`. Warnings-as-errors +Release builds with zero warnings/errors. Complete Unit passes 2,616; all five +Contract cases pass; the 46-case architecture selection covers surface, mode, +manifest, tenancy, authentication authority and corpus owners. The PostgreSQL +selection passes all 54 AccountSite/subject-admission cases. The earlier focused +non-Docker HTTP selection passes 121, including startup with an ambient issuer. +The complete non-Docker Integration population passes all 282 cases. All +recorded tests have zero skips. + +Initial new-control failures were fixture errors, not waived runtime failures: +unclassified paths need an explicitly empty collection assertion; a failed +ReadWrite owner permanently poisons its unit, so the ReadOnly positive takes a +fresh scope. Optional per-category Debug configuration produced an invalid +Serilog scalar/section combination and was reverted; the existing serialized +logging collection remains authoritative. The corrected owners pass. + +The changed-document sweep resolves 2,216 relative file/fragment targets with +none broken; seven ADR-parser controls and whitespace checks pass. The first fresh +independent implementation review round is recorded below; complete +architecture/Docker/native and managed demo qualification still belongs to +final-source hosted CI. + +##### Step 1 independent review round 1 + +Three new read-only reviewers inspect `5daee8ad..57f49ce0`: GPT-6 Astra at +xhigh covers runtime/security/resource lifetime; GPT-6.1 Sol at xhigh covers +proof correctness and cost; another GPT-6.1 Sol at xhigh covers tenancy, real +reader controls and corpus governance. Runtime and tenancy/corpus find no +actionable issue. The proof review verifies two additional P2 coverage gaps: + +- A DI-registered `IFilterProvider` can replace effective executable filters + through `FilterItem.Filter` without changing `MvcOptions.Filters`. Pin the + actual provider inventory and bound production provider capability/registration, + with compiled dirty/restored controls. +- A custom attribute implementing `IAllowAnonymous` is not the concrete + `AllowAnonymousAttribute`. Match inherited/implemented anonymous metadata, + preserve exactly the approved public attribute, and check actual endpoint + authorization metadata too. + +Neither finding demonstrates a production authentication bypass; no such +provider/attribute is present, and the independent AccountSite gate remains. +The verified fixes add the actual framework provider/ordering inventory and a +real dirty DI provider that changes effective filter output while the options +list remains unchanged. Compiled implementation/registration controls fail the +provider diagnostic. Direct and inherited custom anonymous attributes fail the +same authorization predicate; public actions still require the exact standard +attribute. Actual endpoint metadata is checked independently. + +Release builds with zero warnings/errors and whitespace verification passes. +Focused surface/authority architecture passes all 23 cases; actual runtime +controls pass both Development/Production cases, with zero skips. These reviews are +source inspections, not executed tests. The second fresh independent review +round inspects the committed correction below. + +##### Step 1 independent review round 2 + +Three fresh read-only reviewers inspect `5daee8ad..6380fccc`: GPT-6 Astra at +xhigh covers proof closure; GPT-6.1 Sol at xhigh covers runtime, cleanup and +effective authorization; GPT-6.1 Sol at high covers corpus governance and +tenancy proofs. Corpus and the runtime corrections have no actionable finding. +The two proof findings concern supported MVC composition channels: + +- Attached/inherited action or controller filters can change effective + `ControllerActionDescriptor.FilterDescriptors` while the global options and + provider inventories remain unchanged. Inventory effective descriptors and + exercise attached filters/factories with dirty/restored controls. +- Explicit `AuthorizationPolicy` or `IAuthorizationRequirementData` endpoint + metadata is consumed separately from `IAuthorizeData`/`IAllowAnonymous`. + Reject these additional channels on the approved endpoints and exercise a + real convention-injected policy as well as compiled metadata/conventions. + +Neither finding identifies a current production bypass. The runtime correction +pins all six effective per-action descriptors, including framework factories, +the inherited API marker, exact declared response type, scope, order, reuse and +factory arguments. Added/removed/changed descriptors fail the same assertion. +Three real attached-filter convention controls preserve global options/provider +inventories while changing the effective descriptors. Two real endpoint +conventions separately inject an explicit policy and requirement metadata; +removing only that metadata restores the authorization assertion. All seven +runtime cases pass with zero skips. Compiled direct/inherited attributes cover +both filter and requirement interfaces; type/service factories and inherited +controller metadata fail their intended diagnostics. The shared endpoint +capability census covers the ordinary authorization/metadata conventions and +their supported direct mutation APIs, with an unchanged display-name convention +as the clean control. A getter alone is not treated as a metadata write: the +existing idempotency OpenAPI transformer only reads metadata. No owner allowlist +was added. Release builds with zero warnings/errors; all 53 focused +surface/authority, public-surface, tenancy, job-manifest and corpus architecture +cases pass with zero skips. Both findings are corrected in `09dcb111`. Their +original round-2 reviewers independently inspect that committed delta and confirm +their findings closed, with no remaining actionable issue in the targeted fixes. +These are source inspections, not additional executed test runs. Step 1's two +independent rounds and verified correction cycle are complete; Step 2 proceeds +under the plan above. Final-source hosted qualification remains outstanding. + +#### Step 2 implementation and verification + +**Initial implementation at `8f433a73`, before independent reviews.** The SDK's +fixed, parameterless `PublicRequestRefusalError` is +available only from its server entry. Exact typed transport refusals become the +existing local `invalid-request`; cancellation still takes precedence, provider +text/lookalikes remain transport failures, and response-body failures are not +reclassified. The configured public path fence uses that port before any fetch. +Negative calls send zero requests; the restored public call returns a real +validated success. There is no automatic retry or HTTP response-policy change. +All 72 SDK cases and the 105 public-client/middleware cases pass. + +Demo command failures retain a closed reason and command/daemon origin. Only +observed spontaneous exits supply native status; deadline, spawn, output, +cancellation and cleanup do not borrow a later stop signal. The actual worker +marks missing/malformed input before CDP connection. Process/profile cleanup +preserves the first failure and never attributes its intentional stop status. +A confirmed failed daemon spawn owns no process and does not masquerade as an +output-cleanup fault. + +The CI lifecycle captures clean owned-root Git commit/tree before restore/build, +rechecks it entering proof and before success, and refuses ambient Git redirects +or changed tracked/staged/nonignored source. Real temporary repositories exercise +dirt, unchanged-tree commits, in-checkpoint mutation, root anchoring and finite +command bounds. A copied actual launcher proves the CI check precedes restore; +local-mode source remains usable while dirty. These observations do not attest +ignored inputs or edits restored between checkpoints. Both JSON and HTML byte +digests bind the admitted report pair; corrupt, missing and substituted members +refuse. The child-environment test now describes only constructed values, without +claiming that Next never loads private dotenv files. + +The six-file demo selection passes all 224 cases. The complete guarded frontend +run passes 1,688 cases (1,616 web and 72 SDK), zero skips/todos; lint, typecheck and +production build pass. Import-order and test-only environment typing failures +were corrected without changing the runtime contract. The document sweep resolves +2,275 relative links/fragments with zero broken; seven ADR-parser controls and +whitespace checks pass. Neither independent Step 2 review round had started at +that implementation point. +Actual full-stack browser/audit and final-source backend qualification remain +with the existing hosted checks. + +##### Step 2 independent review round 1 + +Three fresh read-only reviewers inspect `09fdf8a2..8f433a73`: GPT-6 Astra at +xhigh covers process lifetime and diagnostic ownership; GPT-6.1 Sol at xhigh +covers source/report proof; GPT-6.1 Sol at high covers SDK, declarations and +corpus consistency. Source/report and SDK/corpus approve their scopes. The +process review verifies three P2 diagnostic/first-failure gaps: + +- Native cancellation from coordinator timers or its positive HTTP observer + can bypass the command owner's typed path and be recorded as `unknown`. +- An observed output refusal is stored before physical child closure, but the + command race omits that refusal. A later shorter deadline can replace it while + an owned signal-resistant child awaits bounded escalation. +- A second daemon exit replaces the activity check's stored failure while the + public failure promise still retains the first daemon's error. + +These findings concern diagnostic correctness and ownership; no budget or +authentication bypass is demonstrated. Regression controls first reproduce all +three against `8f433a73`. Trusted coordinator cancellation now classifies raw +timer/HTTP aborts using only its owned signal, retaining typed first faults and +excluding cleanup. Spawn/output refusal is published immediately and raced +separately from physical closure; the same existing bounded stop is still joined. +The daemon owner latches one error for both its public promise and active checks. +Real signal-resistant children prove output beats the later deadline and that +daemon refusal precedes physical closure; two daemon exits preserve the original +17 outcome after the later 23 outcome. The daemon publication control compares +event order without a narrow scheduling-time assertion. Native waits exercise +the two distinct startup/proof classification contexts; the HTTP abort is real. + +All six distinct regression cases pass within the complete guarded frontend run: +1,694 passed (1,622 web and 72 SDK), zero skips/todos. Lint and typecheck pass. +Review conclusions above are source inspections; they do not independently rerun +the recorded local tests. The corrected commit proceeds to a second review round +with new independent reviewers. + +##### Step 2 independent review round 2 + +Three new read-only reviewers inspect `09fdf8a2..9d08070e`: GPT-6 Astra at +xhigh covers process lifetime, diagnostics and cleanup; GPT-6.1 Sol at xhigh +covers source checkpoints and report integrity; another GPT-6.1 Sol at high +covers SDK, declarations, consumers and corpus. The source/report and SDK/corpus +reviews find no actionable issue. Source capture precedes the shared launcher's +own restoration/build work; workflow browser-tool bootstrap precedes that +checkpoint and ignored dependencies remain outside its attestation. + +The runtime review verifies one further P2: waiting for ChildProcess `close` to +publish a failing native exit can let a later deadline, or another daemon's +prompt closure, replace the earlier native failure while inherited output pipes +remain open. The correction must publish failing `exit` status immediately while +retaining successful output completion and bounded physical cleanup/stream drain. +The existing exit-before-close lifecycle control makes this a supported process +shape rather than an assumed provider behavior. Fix verification follows below. + +The four new real-child controls first show three failures and one existing +successful-output positive. The fix publishes only failing native `exit` +outcomes early; zero-exit commands still await `close` and complete captured +output. Nonzero and signal failures beat a later deadline despite paused output; +the first daemon leader's failure survives the second daemon's prompt closure. +Physical group shutdown and separate bounded stream drainage remain owned. +All four controls then pass. The complete guarded frontend population passes +1,698 (1,626 web and 72 SDK), with zero skips/todos; lint and typecheck pass. +Five final corpus controls, seven ADR-parser controls and the changed-document +sweep (2,275 relative file/fragment targets, none broken) pass. The runtime fix +receives targeted independent reinspection before correction closeout. + +Targeted reinspection of `9b6794da` finds the same ordering gap for a daemon's +unexpected zero exit: ordinary command success correctly waits for `close`, but +daemon success is itself a failure and must publish immediately too. The added +zero-then-23 control fails before the follow-up fix. A distinct all-native-exit +observation now serves daemon ownership, while ordinary successful capture still +waits for `close`. Both zero-then-23 and 17-then-23 retain the first daemon fault. +All five ownership controls pass; the complete guarded frontend population passes +1,699 (1,627 web and 72 SDK), zero skips/todos, with clean lint and typecheck. + +Both independent runtime and proof reviewers reinspect `49c2c431` and confirm +the ordering finding closed, with no remaining actionable issue in the fix. +These are source inspections, distinct from the locally executed controls. + +#### Correction closeout and current-source PR qualification + +Both correction steps complete implementation, commits and two fresh independent +review rounds. Verified findings from each round are fixed and committed; the +targeted follow-up inspections close the final native-exit variant. No test +population, timeout, required check, browser flag or audit threshold is relaxed. +No new decision, schema, role, grant or deployment policy is introduced. + +The [live PR #33 handoff](https://github.com/HodeTech/LearnStack/pull/33) owns +qualification of the exact current head and checkout merge: all hosted workers +and required checks, API-bound immutable artifact identities, complete case +unions, naturally completed cleanup and the frontend/browser/report proof. +Local passing checks and earlier green runs do not qualify a later source. This +record closes correction implementation/review, makes no merge or production +readiness claim, and requires that current-source evidence before merge. +P02b-6 remains unstarted. Phase 03 membership/authorization, P02b-7 BFF recovery +and the named Phase 11 production-activation obligations retain their owners. + +#### Step 3 — Measured CI timing repair + +The two implementation correction steps close at `00a7877e`. Hosted +[run 39417319998](https://github.com/HodeTech/LearnStack/actions/runs/39417319998) +does not qualify that source: attempt 1 completes 25 successful jobs but refuses +`ordinary-9` before tests on `docker_census_unreadable`; its integration aggregate +fails closed. A full second attempt, without source or policy changes, completes +that Docker job and 25 successful jobs overall, but `architecture-3` reaches +`deadline_exhausted`; its backend aggregate fails closed. No successful sibling +from one attempt substitutes for another attempt's missing result. + +The second attempt's failed Architecture artifact retains 26 of 27 completed +case IDs, all passed, with owned cleanup complete and no forced cleanup. The +remaining selector is +`Background_job_authority_census_detects_extra_activation_and_removed_live_guards`. +Three expensive selectors from the same `JobAuthorityMutationTests` class share +that bin and execute serially. The separate local selector control passes in +203.11 seconds of process wall time; this establishes neither hosted duration +nor whole-shard fit. The detector and all clean/dirty/restored mutations remain +unchanged. + +Under [ADR-0063's reviewed timing-plan revision](../decisions/0063-complete-bounded-ci-test-shards.md#versioned-plan-and-independence), +refresh only weights observed in the five complete Architecture TRXs from +attempt 2 (`architecture-0`, `1`, `2`, `4`, `5`). Their 406 passed case rows +belong to 242 exact assembly/selector groups. Sum each group's observed case +durations, round upward to milliseconds and retain a minimum of one millisecond. +The failed bin's 21 selector estimates and provenance remain unchanged; the +uncompleted selector's old 371-second estimate is not relabelled as a current +measurement. Each new source names its API ZIP digest, artifact ID, run/attempt, +owner, PR head and actual merge checkout. The closed `hosted_trx` kind describes +this evidence without mislabelling it as local or rounded console data. + +These advisory weights influence ownership only. Method/theory grouping, exact +case unions, default costs, fixed-cost unknowns, plan salt, assignment algorithm, +six Architecture/twelve ordinary workers, the twenty-minute execution ceiling and +five-minute aggregates remain unchanged. Offline A/B replay is not a runtime +guarantee. A plan change requires fresh independent review and two genuinely +different complete hosted assignments on the same final source, plan, toolchain +and case population. Earlier frontend/demo successes remain source-bound +historical receipts and cannot qualify that later head. + +The refreshed plan digest is +`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. +Replay reconstructs the original actual B assignment and validates exact old/new +A/B unions, whole-selector grouping, different co-membership and unchanged +ordinary/base/native owners. All 52 shard controls, 16 result controls and the +existing workflow topology validation pass. Review closure follows below; +offline replay alone does not satisfy the required complete hosted A/B +qualification. + +##### Step 3 independent review rounds and local closeout + +The implementation is committed at `9014ec66`. Round 1 uses two fresh read-only +reviewers: GPT-6 Astra at xhigh independently reconstructs raw provenance and +assignment arithmetic; GPT-6.1 Sol at high reviews contract, parser and corpus. +Both approve with no actionable finding. Round 2 uses two new GPT-6.1 Sol +reviewers, at xhigh for raw evidence and high for contract/corpus. Both approve +with no actionable finding. The second raw-evidence review independently checks +all five ZIP digests, archive/extracted-byte equality, result file hashes, +406 TRX rows, exact tick arithmetic and all 5,847 case IDs across old/new A/B. +These are read-only calculations and inspections, not independently rerun test +suites or hosted-fit claims. + +Testing 06 also repeats ADR-0063's exact qualification boundary: rollout and plan, +algorithm or fixture-lifetime changes require both complete layouts; normal +future pushes run one complete assignment. No new authority or decision is +introduced. All three correction steps now complete implementation, commits and +both independent review rounds. The live PR handoff must verify two fresh full +A/B attempts for this timing revision on one final source, plan, toolchain and +population, preserving current-attempt evidence and exact required checks. +Neither failed historical attempt nor the offline replay qualifies that head. + +##### Step 3 provenance guard follow-up + +Source `b3abbce6` completes both full attempts of hosted run `39424514759`: +A and B each pass all 27 jobs, 5,847 backend cases including 31 native cases, +1,699 frontend cases and 27 JSON/HTML demo pairs. Independent API/archive/result +validation verifies equal complete case populations, actual different method +co-membership, matching toolchain identities and naturally completed cleanup. +The live PR retains both attempt-specific receipts and their limits. + +A subsequent inspection confirms a Minor parser gap: the new `hosted_trx` kind +accepted a null source or run identity, despite requiring identified hosted +timing evidence. All five committed hosted sources already have both values; +neither their measured provenance nor the successful receipts are defective. +The guard now requires both identities for this kind. Its actual-owner control +fails in all three null combinations before the fix and passes afterwards; +complete hosted records and the disclosed nullable local/console shapes remain +accepted. The existing field-format and unknown-kind refusals still apply. + +The plan bytes, weights, assignment algorithm and fixture lifetime do not +change. Its digest remains +`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. +This is source-shape validation, not API attestation of an arbitrary timing +record. Implementation `dbb2e9fd` completes two fresh independent follow-up review +rounds, each with two GPT-6.1 Sol reviewers at high effort. All four approve with +no actionable finding. Round 1 independently exercises 270 kind/identity +combinations; Round 2 exercises separate 507- and 297-combination controls. Both +rounds reproduce the three missing-identity failures against the preceding +parser. These are local/source proofs, not independent hosted attestation. +All 52 combined plan/result controls, 16 separate result controls and topology +validation pass; 2,276 relative links/fragments remain valid. + +ADR-0063 requires one complete current-source assignment for this normal push; +the earlier A/B receipts qualify the unchanged plan on their named source, not +the subsequent guard commit. The live PR owns final-head qualification. + +### P02b-5 merge and closeout (2026-10-20) + +**P02b-5 is complete and merged.** The maintainer merges +[PR #33](https://github.com/HodeTech/LearnStack/pull/33) at +`2026-10-20T20:18:42Z`. The verified final PR head is +`419e456260dc2023f3e6d538a46ede8b1d7e8f20`; the squash merge is +`24705a7a81ddfb7e0f5f5349370a53a55ca9e4eb`, whose parent is +`b81006c7af7d38f1587ecb3bf93dbcca16f353e0`. The PR head, tested merge checkout +`be8417c3a289d26e9062bd40bf163d51987d3e11` and actual squash merge all have tree +`7adeacfe81a15cc5e36a77cf79006da201f01e26`; their tracked contents are identical. + +| Step | Delivered scope | Review status | +|---|---|---| +| 1 | Isolated strict token foundation, bounded metadata and private diagnostics | Both independent rounds complete | +| 2 | Host-backed AccountSite query, exact physical read-only ownership and audit Off | Both independent rounds complete | +| 3 | Attributed host/claim reconciliation and stable validated-subject admission | Both independent rounds complete | +| 4 | Atomic HTTP activation, masked refusal contracts and authenticated SDK contract | Both independent rounds complete | +| 5 | Production authority census, real negative controls and corpus reconciliation | Both independent rounds complete | + +The subsequent ADR-0065 audit-budget/telemetry and ADR-0066 retained-subject/ +cleanup refinements are delivered with their recorded independent reviews. +The [systematic corrections](#p02b-5-systematic-proof-and-document-corrections-2026-10-20) +close backend proof boundaries, SDK/demo failure ownership, paired report/source +identity and measured CI weights. All three correction steps and the final +hosted-source identity guard complete two fresh independent review rounds. +Earlier delivery records remain source-bound history, including their original +unmerged, running and failed observations. + +#### Final-source qualification + +[Run 39431896517, attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39431896517/attempts/1) +passes **27/27 jobs** on the final PR head. The independently downloaded, +API-bound archives verify job/artifact identities, ZIP and exported-file hashes, +complete actual case-ID unions and both aggregate results: + +- **5,847 backend cases**, zero failures/skips: 2,616 Unit, 433 Architecture, + five Contract, 287 non-Docker Integration, 2,475 ordinary Docker and 31 native. + The backend and integration aggregates count 3,341 and 2,506 respectively. + All 20 execution owners complete with joined cleanup and no forced cleanup; + native refusal evidence is empty. +- **1,699 frontend cases** across web/SDK, zero skips/todos; typecheck, lint, + production build and the ingress/cleanup proof pass. OpenAPI, secret scan + and meta pass. +- **27 JSON/HTML report pairs** verify both byte digests and source/tree/build/ + invocation/configuration identities. All 134 API completions are HTTP 200. + Nine navigations, 24 visibility controls, two TLS refusals and the timeout + control pass. The proof takes 651.490 seconds and cleanup 12.839 seconds; + all owned processes, Compose, private files, environment and lock are removed. + Hard JS/CLS/accessibility budgets pass; eight URL groups retain nonblocking + timing warnings. Browser flags and thresholds are unchanged. + +The unchanged timing plan separately qualifies both complete assignments in +[run 39424514759, A](https://github.com/HodeTech/LearnStack/actions/runs/39424514759/attempts/1) +and [B](https://github.com/HodeTech/LearnStack/actions/runs/39424514759/attempts/2) +at `b3abbce65ba60ae4165b1eb09bd44d8644e7843d`: each passes all 27 jobs with the +same complete 5,847-case population and observed toolchain, but different actual +Architecture/ordinary/SharedSchema co-membership. Their plan digest is +`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. +The later guard changes no plan bytes, weights, assignment algorithm or fixture +lifetime; ADR-0063 requires the separate complete normal-push assignment above. +Historical A/B results are not reused as final-head results. The earlier failed +run `39417319998` remains failed evidence, not a partial passing receipt. + +Read-only protection verification retains all seven required context names, +their GitHub Actions app bindings and strict checking. No protection setting, +test population, timeout, audit threshold or browser budget is relaxed by this +closeout. The separate post-merge push +[run 39490885612](https://github.com/HodeTech/LearnStack/actions/runs/39490885612) +is queued at initial merge verification; it is not counted as completed +post-merge execution. The final PR-source qualification and identical-tree +comparison above are the merge evidence. + +#### Remaining work and next packet + +**Next: P02b-6 realm/TTL decision pass.** Re-verify the remaining G12 realm/ +reconciler choices and G13 access-token lifetime authority before changing +Keycloak or seed users. Deliver the shared client scope and protocol mappers, +admin-only UUID user-profile attributes, exact seed identity agreement, +idempotent fresh/warm realm reconciliation and real Keycloak token/TTL proofs. +The already Accepted BFF-client choice remains the baseline; this closeout +accepts no new gate or ADR. + +P02b-7 retains BFF code exchange, token/session custody, refresh serialization, +CSRF/logout, guarded pages and SDK bearer transport. P02b-8 retains LS0002, +the retained-store erasure inventory, remaining carrier reconciliation and the +Phase 02b exit. No browser sign-in or live membership/permission service is +claimed by the merged API boundary. Phase 03 owns membership/authorization, +Phase 06 the full browser OIDC journey, and Phase 11 production identity, +readiness, distributed capacity and operational qualification. +P02b-6–8 remain unstarted; Phase 02b remains in progress. + +**Documentation-only closeout validation.** Five Release corpus consistency +cases and seven ADR lifecycle/parser controls pass, with zero failures/skips. +All 1,440 relative links/fragments in the ten changed Markdown files resolve. +Prose wrapping, whitespace and private-reference checks pass. Accepted ADRs +and the dated P02b-5 decision/delivery/review records are byte-preserved against +the final PR head. The local run covers these status/navigation edits; the +runtime, Docker/native and browser qualification remains source-bound to the +completed hosted receipts above. This closeout starts no next packet. + +## P02b-6 — Realm and seed + +### P02b-6 decision package (2026-10-20) + +**Status: Accepted — 2026-10-21.** The maintainer approved the decision package +at `6d75e532` and the four-step implementation plan on `development`. Acceptance +closes G12's realm/reconciliation/callback choices and G13's issuance-TTL part. +P02b-7's session portion of G13 stays Open independently. This acceptance record +and the two Registered catalogue obligations precede runtime implementation; +no realm, seed identity, runtime or CI implementation is delivered by acceptance. +The decision pass originally inspected `b4945705` after the P02b-5 merge; dated +inspection and review receipts below retain their as-of proposal status. + +#### Problem, scope and decision vehicle + +P02b-5 validates the strict API profile, but the committed development realm does +not issue it. P02b-6 makes actual Keycloak issuance agree with that profile on +both fresh and existing development databases. It supplies protected identity +attributes, one repeatable development reconciliation path and real token/API +proofs, while preserving existing accounts and the separate operator realm. + +G12 explicitly selects a phase-document vehicle unless reconciliation becomes +ADR-0004's runtime `IIdentityProvider`. This package keeps a bounded Node.js +Admin REST client in development tooling; no application port, runtime provider +SDK, endpoint, database role/grant or schema is introduced. G13 delegates the +issuance-lifetime answer to this record and the reconciled Security standard. +A new ADR is therefore not proposed. Any implementation requiring a different +provider/runtime boundary reopens this pass before code; approval of this +package does not authorize that change. + +**Issuance-carrier follow-up — 2026-10-21.** The no-ADR statement above records +the original package's vehicle. A dedicated issuance carrier now exists as +[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md), Proposed +pending separate maintainer acceptance. The earlier 900s phase approval remains +valid; G12's development-tooling vehicle and G13's Open session portion remain +unchanged. + +**Issuance-carrier acceptance — 2026-10-21.** The maintainer separately approved +the revised ADR-0067 after its correction reviews. It now supplies the dedicated +issuance decision authority; Security 11 retains the ongoing rule. The earlier +phase approval and Proposed-state follow-up above retain their original +chronology. G12's vehicle and G13's Open session portion are unchanged. + +The existing decisions remain authoritative: +[ADR-0004](../decisions/0004-authentication-strategy.md), +[ADR-0036](../decisions/0036-tenant-resolution-trusted-inputs.md) and +[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md). +No Accepted ADR body or acceptance metadata is rewritten. This package adds no +supersession of their authentication, tenant authority or audit contracts. + +#### Reviewed premises and necessary document actions + +| Current source | Verified premise | Required disposition | +|---|---|---| +| `infra/keycloak/realms/learnstack.json` | Public `learnstack-web`, no custom client scope/mappers, slug-valued tenant attributes and no stable actor attributes | Configure the already Accepted confidential PKCE profile and real seed UUIDs; do not loosen the API to accept the old export. | +| `scripts/seed.sh`, `scripts/wait-compose.mjs` | Seed checks both realm issuers, then invokes the application Seeder; no Admin REST reconciliation | Add the shared bounded tooling call after readiness and application seed convergence; preserve the selected Compose/env identity. | +| `scripts/demo.mjs` | Demo invokes the .NET Seeder directly, then CI stops its Keycloak | Invoke the same reconciler before that stop. A seed-script-only change cannot converge this entry point. | +| `SeedData.cs`, `DemoIdentities.cs`, Seeder `Program.cs` | Tenant/org/host identities already have typed, read-only tooling projections; no identity-user declaration | Add stable actor/seed-user declarations and a credential-free projection without a new application identity table or production Seeder reference. | +| Realm `accessTokenLifespan`, API client override, Keycloak README, Security 11 | Realm/API override are 1800s; README recommends 900s for production; API permits at most one hour | Select one development issuance value, remove conflicting client overrides and distinguish issuance from API acceptance/session lifetimes. | +| This phase's former identity completion criterion: `exp - iat` equals the configured lifetime | Pinned Keycloak reads the issuance and expiration clocks separately; a second rollover can make that difference 901 for a 900s setting | Replaced at acceptance with exact realm/no-override checks and bounded observed-issuance evidence below; independent drift controls remain required. | +| Keycloak 26.6.2 profile/import source | Profile configuration is a declarative-user-profile component; runtime Admin REST uses `users/profile`. Declaring a custom `clientScopes` list can suppress automatic built-in creation | Use the supported component/config representation; include/verify actual `basic` and its `sub` mapper, not merely a scope name in a client list. | +| Keycloak account REST and profile source | Account permission is checked before attribute-edit policy; profile PUT and user-attribute PUT can replace supplied configuration/maps | Pair self-service refusals with a successful ordinary profile edit, merge unrelated definitions/attributes and verify retained state. A generic 403 proves neither protection nor preservation. | +| Standards 06, integration skills and runner instructions | Container guidance still describes Postgres as the only current integration dependency | Add the named Keycloak fixture and Docker-trait/source controls with its first tests; preserve the real app-role PostgreSQL requirement for API/database assertions. | +| Standards 21 provider-SDK backfill row and this phase's enforcement scope | The reconciler introduces no runtime provider SDK subject | Resolve the row's owning-phase handoff explicitly at acceptance, as specified below; do not claim this script implements that structural rule. | + +The review includes the full identity architecture, realm README/exports, +P02b-5 accepted profile and handoff, G12/G13, current completion/risk clauses, +Security/Testing/Infrastructure/Documentation standards, authentication and +SDK-boundary catalogue entries, Phase 03/11 ownership, seed/demo orchestration +and their existing environment/process boundaries. Historical dated delivery +receipts retain their original words; mutable current descriptions are corrected +with their actual implementing slice. + +#### Accepted G12/G13 answers + +**Alternatives.** Startup-import-only cannot update an existing realm. A realm +overwrite/database reset violates preserved-account upgrade requirements. General +declarative realm-management tools remain viable for Phase 11 production +provisioning; this small development-only operation instead owns an explicit +Admin REST field allowlist and its preservation tests without introducing a +second configuration-state tool. This is a maintenance responsibility, not a +claim that those tools cannot preserve unrelated state or are more expensive. + +For issuance, keeping the existing 1800s development value reduces refresh churn +but leaves a longer stale-scope window. The accepted 900s follows the existing +Keycloak README's production target while reducing that window for new tokens. +It is a selected development default, not a measured production capacity claim. +The API's 3600s rejection ceiling is not an issuance recommendation; BFF session +lifetimes are a different decision. + +| Gate part | Accepted answer | What acceptance does not close | +|---|---|---| +| G12: realm and reconciliation | One owned development Admin REST reconciler, reused by `make seed` and `make demo`, with the exact profile, identity/preservation and failure rules below | No production realm provisioning, runtime identity-provider port, membership service or browser session | +| G12: callbacks | Exact HTTPS Auth.js Keycloak callback on each existing seed host at port 3000; exact same-host root post-logout URI | No callback implementation, login transaction/session cookie, return-URL/CSRF policy or production domain registration | +| G13: access-token issuance lifetime | Security 11 owns the rule: the tenant development realm's configured access-token lifespan is 900s; `learnstack.json` owns its executable value and reconciliation enforces it without a conflicting client override. Actual timestamps follow the provider semantics below | BFF idle/absolute session life, refresh custody/serialization, CSRF and logout remain P02b-7; API's one-hour acceptance ceiling and 30s skew remain unchanged | + +**G13 authority follow-up — 2026-10-21.** Separately Accepted +[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) records +the issuance decision above, including inherited ID-token expiration and session +clamping. Security 11 remains the ongoing-rule owner. This adds no BFF session +lifetime or change to API acceptance. + +**Client and claim configuration.** Preserve the Accepted `learnstack-web` +confidential client with S256, `azp=learnstack-web` and `learnstack-api` resource +audience. Keep standard code flow; disable implicit flow, direct access grants +and service accounts on that client. The resource client's legacy service +account is not converted into a tenant user; its tokens still fail ADR-0064's +user profile. Disable the resource client's browser code flow and remove its +old localhost callback list; it does not act as a second login client. Preserve +its existing service credential. The API receives no client secret. + +Use one named default client scope, `learnstack-tenant-api`, attached to both +named clients. Its three scalar String user-attribute mappers emit `user_id`, +`tenant_id` and optional `organization_id` in access/ID tokens, without placing +those attributes in the user-info response. Its explicit audience mapper adds +`learnstack-api` to access tokens only. Preserve/declare actual built-in scopes, +especially `basic` and its `sub` mapper; do not replace all existing default or +optional scope assignments with a partial list. Reject another effective mapper +that can contradict the protected identity claims, rather than deleting an +unrecognized administrator customization. The API audience need not be exclusive; +standard account audiences do not grant application permission. + +Declare all three identity attributes single-valued, with admin-only view/edit, +including `organization_id`. Missing tenant/org attributes remain optional; +self-registration is not an actor-provisioning mechanism. Leave unrelated +profile attributes/groups and the existing unmanaged-attribute policy intact. +The disabled unmanaged policy is omitted/null in 26.6.2, not a `DISABLED` enum. +Legacy tenant roles and assignments remain inert authentication metadata; +P02b-5's complete role-authority census still forbids application permission from +them. No new application role, membership or implicit administrator is seeded. + +For each `SeedData` host the exact redirect is +`https://<seed-host>:3000/api/auth/callback/keycloak`; its post-logout URI is +`https://<seed-host>:3000/`. No localhost HTTP/wildcard callback, alternate host +or browser client secret is accepted for this BFF. Encode the two post-logout +values with Keycloak's supported multivalue representation. Retain manual hosts, +leaf certificate and trust setup. These registrations reserve P02b-7's callback +contract without claiming a browser login exists. + +**Identity preservation.** `SeedData` owns four stable, distinct, nonreserved +actor UUIDs and their tenant/org references. Keep the two existing English demo +usernames; add `demo-admin@tenant-b.test` and `demo-learner@tenant-b.test` for +Yoga with its existing default organization. These are development personas, +not application permission grants; their credentials use the existing +create-only development password convention. +The declaration/projection owns their exact usernames and UUIDs; the realm +export must agree with it. Do not derive actor identity from email, username or +Keycloak `sub`, or generate one on each reconciliation/login. + +- Preserve the Keycloak ID/`sub` of every existing account, including seed users. +- Create a missing named demo account with its declared development credential. + Never reset an existing password, credential, MFA factor, required action, + enabled state, email/name or role assignment to make a proof pass. +- On the two legacy English accounts only, accept the known old `tenant-a` + attribute as a named migration to their declared tenant UUID. Missing identity + values may be installed; semantically matching UUIDs are retained. Conflicting + nonempty actor/tenant/org values refuse, including an unexpected organization + on a tenant-wide English identity. No reassignment of a real UUID is guessed. +- Preserve unrelated user attributes through a read/merge/write operation. + Do not send only the three attributes: that can delete the others. +- Do not update nonmanifest accounts. Their missing actor/scope is not filled by + invention: the API continues to refuse an incomplete profile until Phase 03 + owns its durable mapping. Never modify `learnstack-hub` or master users/roles. + +**Client-secret continuity.** Add one private development source, +`KEYCLOAK_WEB_CLIENT_SECRET`, documented in `.env.example`. Fresh import and the +reconciler must agree with the selected value. Converting the old public client +installs that selected BFF secret once; any unused generated public-client +secret is not a previously consumed confidential contract. An already +confidential client's secret is verified and preserved; a mismatch fails without +rotation. A missing key in an older private environment is reported with setup +instructions, never silently filled or printed. P02b-7 receives only this BFF +credential, never the admin credential. Production secrets remain Phase 11's +provisioning responsibility. + +**TTL semantics.** Remove the named clients' `access.token.lifespan` overrides; +they inherit the realm's configured 900s value. Keycloak 26.6.2 sets `iat` and +calculates expiration from separate clock reads: crossing a second boundary can +yield `exp - iat == 901`, and a scheduling pause can widen it further. Do not +assert exact subtraction equality or substitute a fixed 901s ceiling. + +Check the exact realm value and absence of either client override independently. +For a fresh code exchange, record UTC and monotonic bounds around the request, +with its finite HTTP deadline, and require the signed expiration to lie within +that observed interval plus the configured lifespan. Any qualified fixture/ +provider clock tolerance is explicit, at most the existing 30s API clock skew; +an indeterminate clock/window fails the proof rather than widening the tolerance. +The measurement bound is test evidence, not a new production token-acceptance +rule. Separate session-clamping coverage permits shorter late-session issuance. +Exact configuration/override controls and independent wrong-expiration mutants +prevent timing tolerance from hiding a different configured lifespan. + +Changing the realm does not invalidate earlier +1800s tokens; they remain subject to the API acceptance bound. The reduced TTL +reduces the ordinary stale-scope window; 900s is the configured lifespan, not a +hard `exp - iat` guarantee. It does not implement immediate revocation, live +membership checks or refresh-token rotation. The latter's existing Phase 11 +owner is unchanged. + +#### Reconciler ownership, failure and security boundaries + +The implementation is a closed tooling client under `scripts/`, using Node's +HTTP support rather than a new Keycloak SDK/application service. Both entry +points await it after successful application seed convergence and before API/web +launch or CI-owned Keycloak stop. Direct .NET Seeder remains application-data +only. The read-only identity projection never opens a data source. + +- Validate selected Compose project/service and pinned-image identity, loopback + development endpoint, exact realm discovery issuer and private source agreement + before admin authentication. Verify authenticated server version before writes. + Do not accept arbitrary realm, + URL, command, import file or destructive-reset CLI arguments. Test transport + injection stays internal and cannot widen the production CLI. +- Read the selected environment as data; inherited aliases cannot silently point + reconciliation at a different instance. Admin credentials, access tokens and + BFF secret stay in memory and the specifically owned tooling environment, + never argv, URLs, temp JSON, stdout/stderr, receipts or the API/public renderer + environment. The .NET Seeder keeps its existing credential allowlist. +- Use one local lock owner per selected target for both entry points; refuse a + second invocation rather than interleave. Hold through actual HTTP/child + cleanup. A stale lock is not removed merely because time elapsed. This is a + local tooling boundary, not a distributed lock against another checkout or + Admin Console. Concurrent external administration is unsupported: operators + run reconciliation while this development realm is otherwise quiescent. +- Read and validate the complete bounded change plan before the first write. + Detect conflicting users, scope/mappers, secret and unsupported configuration + up front. Apply only named owned fields/resources, merge unrelated data and + perform independent post-write readback. Never replay a full realm import, + drop a database, recreate a realm or delete existing accounts/scopes/roles. + + **Bounded replacement — 2026-10-22:** [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) + permits one qualified metadata preparation before a fresh full plan, after all + identity-independent prechecks. Every other Admin REST write remains ordinary + and requires that complete plan. Its implementation/proof remains pending. +- Bound each HTTP wait to 5s, ordinary decoded responses and every outbound body + to 256 KiB, and the complete reconciliation to 120s. Only the fixed authenticated + successful `GET /admin/serverinfo` read has the + [accepted 512 KiB allowance](#server-information-response-budget--proposal-2026-10-21). + Reject redirects on discovery, authentication and Admin + REST alike. No automatic token-request or mutation retry loop. + Creation conflicts permit one exact fresh-state check, not blind overwrite. + Abort/close the owned request and await cleanup before dropping the lock; + elapsed time is not evidence that a remote write failed. +- A partial/uncertain run exits nonzero. Previously completed mutations stay + durable; the next explicit run reads current state and resumes missing acts. + No cross-Keycloak/application transaction or automatic rollback is promised. + A completed third run performs zero mutating Admin REST calls. +- Errors emit a fixed stage/reason, never an upstream body/exception or arbitrary + claim/mapper/user values. Exercise credential/token/URL canaries and positive + closed diagnostics. No LearnStack audit row is added for development setup; + Keycloak retains its own administrative event mechanism. + +These choices deliberately trade broad realm-management convenience for safe +local convergence. A customized incompatible identity or confidential secret +requires explicit operator reconciliation. Existing nonmanifest users are +preserved but may lack the strict API profile. Admin credentials remain powerful +local setup credentials, never production runtime authority. A deadline can +leave a remotely committed partial update; a later run must verify it. + +#### Test ownership and required controls + +Acceptance registers the following two canonical behavioural obligations in +Standards 21, with actual owners and **Registered** status until shipped. Their +sources are ADR-0004/0064, Security 11 and this accepted package, not a new +architecture decision. Counts/status assertions change with the same registry +edit; no new Implemented rule is claimed by approval. + +**Test-source follow-up — 2026-10-21.** ADR-0067's separate acceptance adds its +dedicated issuance authority to the existing issuance obligation's sources. +It introduces no new canonical obligation or test owner. The later Step 4 +delivery retains the two existing obligations' Implemented status; the original +registration paragraph above remains an acceptance-time receipt. + +| Canonical obligation | Owner/level | Required evidence | +|---|---|---| +| [`Tenant_Realm_Issuance_Matches_The_Api_Profile`](../standards/21-architecture-tests-catalogue.md#tenant_realm_issuance_matches_the_api_profile) | `TenantRealmIssuanceTests` and `TenantRealmProfileProtectionTests`, backend Integration with Docker | Import committed JSON into pinned Keycloak, exercise real code/S256 issuance, validate through real API handler/AccountSite and app-role PostgreSQL; protect profile attributes with a working account-edit positive control. | +| [`Development_Realm_Reconciliation_Preserves_Accounts`](../standards/21-architecture-tests-catalogue.md#development_realm_reconciliation_preserves_accounts) | `TenantRealmReconciliationTests`, backend Integration with Docker; Node tooling controls for bounded transport/process/CLI | Execute the actual shared reconciler against a pre-mapper warm realm; preserve users/credentials/IDs/unrelated data/Hub, converge protected mappers/attributes/TTL, and prove a third run has zero mutations. | + +Required controls include: + +- All four seed identities: real `sub`, fixed actor, expected tenant and Yoga org, + correct scalar JSON types, API audience/`azp`, RS256/purpose, exact configured + 900s lifespan and bounded fresh-issuance evidence under the TTL semantics above. + Compare export and issued values to typed `SeedData`, not duplicated test IDs. +- Exact registered callbacks on both seed hosts, missing/wrong secret, missing + challenge, plain challenge and missing/wrong verifier refusals; unregistered + redirect rejection, direct grant + still disabled, and ID tokens without API audience. The fixture consumes the + code callback without requiring the unimplemented BFF; it does not launch a + browser or bypass TLS validation to claim a browser cookie proof. +- Actual AccountSite 200 on both host classes with their real tokens, cross-tenant + and cross-organization refusal, claimless protected refusal, Hub-issuer refusal, + and the unchanged absent-token/public-IdP-down path. API/database reads stay + `learnstack_app`; Keycloak uses its own separate fixture database. +- Through the built-in account-console code/S256 flow for the same seed user, + prove an ordinary profile edit succeeds. Then try each protected attribute and + read it independently as admin: no user write or deletion succeeds. Admin-only + profile/account attribute visibility and registration attempts need their own + controls; deliberate token claims are not profile visibility. A + user-editable variant must make the protection proof fail. +- Removed/misattached identity/audience/basic mappers, duplicate/conflicting + identity mappers, wrong scalar types/UUIDs, writable profile attributes, ID-token + audience, client override and TTL drift all have planted dirty/clean controls. +- Warm legacy migration plus additional unrelated users/attributes/profile groups, + changed passwords, required actions, client scopes/roles, confidential secret + and Hub account state; exact snapshots remain preserved. Also cover an + incompatible managed identity, duplicate lookup, partial-write interruption, + failed readback, uncertain HTTP result, a race and zero-write completed rerun. +- Shared `make seed`/`make demo` wiring, target/env mismatch before writes, + secret leakage across child environments, timeout/cancellation/cleanup and + lock ownership; errors never turn into success or erase another owner's lock. + +The new fixture uses Keycloak 26.6.2 with its separate PostgreSQL database and +actual committed import. No ROPC shortcut or test-only mapper/client weakening +is made in the production realm. Every consuming class carries the Docker trait; +the source sweep must detect fixture references outside `Database/` too, with a +planted missing-trait control. Offline Node controls run in the existing meta +job; real provider cases enter ordinary Docker shards through normal discovery. +Preserve the seven required names, complete assignment and existing time ceilings. +Measure fixture/hosted costs; tune only within ADR-0063's accepted plan envelope. + +`Provider_SDK_Types_NotImportedOutsideInfrastructure` remains unimplemented: the +script introduces no runtime SDK type. Acceptance moves its owning-phase cell +from Phase 02b to Phase 03's first runtime identity-provider adapter, with actual +SDK introduction as the trigger. Phase 03 re-verifies that subject before its +first writer; a direct-HTTP implementation cannot be reported as SDK coverage. +The existing SDK exception rule remains enforced. This is the explicit handoff +required by this phase's enforcement scope, not missing P02b-6 work. + +#### Four implementation steps after acceptance + +Each step ends in a clean local commit, then two fresh independent review-agent +rounds. Reviewers first run standards-check, then the security, correctness, +operation/lifecycle, testing and corpus lenses. Confirmed findings are reproduced, +fixed and committed before the next round/step. Fresh focused review verifies a +material correction after round two. Routine progress automatically proceeds; +a new architectural choice returns for maintainer approval. + +| Step | Deliverable | Validation before review/commit closure | +|---|---|---| +| 1 — executable realm and identity declaration | Register accepted gates/rules and current carriers; typed seed identity projection, complete import/profile/scopes/mapper/client configuration, private secret source and drift controls | JSON/schema/source and SeedData agreement; real fresh import/code-token smoke; unsafe mapper/profile/basic/TTL variants fail. No warm overwrite or BFF session claimed. | +| 2 — owned warm-realm reconciliation | Closed Admin REST tooling, explicit owned-field diff/merge/readback, preflight, secrets, locking and deadlines; actual fresh/warm/partial/no-op integration tests | Real pre-mapper PostgreSQL-backed Keycloak retains identities, passwords, unrelated state and Hub; conflict/timeout/uncertainty/race/canary controls; zero writes on completed third pass. | +| 3 — unified seed/demo lifecycle | Both existing entries call the same implementation after application seed; preserve exact configuration/credential/process ownership and CI's stopped-Keycloak public proof | Real fresh/warm `make seed` and repeated convergence; demo lifecycle wiring/proof, no foreign cleanup, private environments and bounded cancellation. Preserve public routes, API authentication and generated contract. | +| 4 — real identity/security qualification and closeout | Full production-token API/profile protection/mutation proofs, Docker fixture census, measured ordinary CI assignment, remaining mutable carriers and packet status | All relevant backend/frontend/meta suites; complete hosted PR qualification and unchanged required checks, public production demo regression. Account/registration positive and dirty controls prove the tests can fail. | + +Do not start the next feature packet as part of this work. P02b-7 retains Auth.js +session/callback implementation, custody/refresh/CSRF/logout and SDK bearer +transport. Phase 03 retains `User`/membership/permission/provisioning/mapping and +tenant switching; Phase 06 retains the full browser OIDC journey; Phase 11 retains +production realm provisioning, rotation and deployment identity hardening. + +#### Acceptance carriers and implementation handoff + +The 2026-10-21 acceptance closes G12's realm/reconciliation/callback choices and +G13's issuance-TTL part with this anchor; G13's session portion stays Open. +The acceptance and Registered catalogue owners form the first commit before +runtime changes. Security 11 owns the issuance rule and points to the executable +value; target sketches link to that authority. Dated old observations retain +their as-of state. The implementation carriers below remain owned by their steps. + +**Issuance handoff follow-up — 2026-10-21.** Separately Accepted ADR-0067 is the +dedicated decision carrier for the issuance choice; Security 11's authority +header and the existing issuance obligation now cite it. This documentation +acceptance introduces no runtime work or change to the earlier approval, +G12's reconciler/callback boundary, or P02b-7's session ownership. + +| Carrier | Action and implementing owner | +|---|---| +| This phase, `CLAUDE.md`, roadmap README | Decision status, steps, source-bound evidence and the exact-equality TTL completion-criterion correction above; completed only after implementation/reviews/qualification. | +| `docs/standards/11-security.md`, architecture 13 | Distinguish issuance/acceptance/session TTL, scalar identity controls and current real-issuance boundary; Steps 1/4. | +| Standards 06/12/21 and integration/run-test skills | Keycloak container/trait, tooling secret/CLI boundaries, two named rules and explicit provider-SDK handoff; Steps 1/4. | +| `infra/keycloak/README.md`, Compose README and root README | Exact local client/callback/secret/migration and non-destructive warm setup; remove the database wipe as the upgrade recipe; Steps 1/3/4. | +| Realm JSON, `.env.example`, seed/demo and source/fixture controls | Apply only after acceptance; Steps 1–4. No Hub-realm edit. | +| Phase 03/11, architecture 14/30 and glossary | Explicit identity-provider handoff, consumer/production boundaries and updated terminology/status; Steps 1/4. | + +The maintainer explicitly approved the package as a whole on 2026-10-21: +900s development issuance, four stable seed identities/legacy migration, exact +callbacks, secret continuity/refusal, the bounded development-only reconciler +and the four implementation steps. The independent review and mechanical +validation receipts below qualify the reviewed proposal; they do not claim +runtime delivery or final-source hosted qualification. + +#### Decision-pass inspection and review evidence + +Two independent read-only inspections used GPT-6.1 Sol at xhigh effort: one +covered the identity/profile/upstream boundary, the other covered reconciliation, +seed/demo and credential/lifecycle ownership. Their findings informed the +premise/action inventory above, including the demo bypass, real `basic` scope, +protected organization attribute and account-edit positive control. + +Isolated pinned-26.6.2 development-container feasibility probes confirmed the +profile component import, protected definitions, merged unrelated account data +and credential preservation, generated-once/retained client secrets and actual +`basic` attachment. A custom-scope-only variant lost built-in `basic`; the +corrected explicit definition restored its attachment. Form-based authorization +experiments did not complete successfully: no code-flow, token or TTL success +is claimed. Both owned containers and temporary imports were removed and their +absence independently checked. These experiments support the design, not a +committed regression suite or PostgreSQL/production qualification. + +**Review round 1.** Two new independent reviewers used GPT-6.1 Sol at xhigh +(security/correctness) and high (corpus/ownership) effort. Both approved the +current proposal for maintainer decision without a verified actionable finding. +They checked Accepted decision compatibility, G12/G13 vehicle and split, +Keycloak update/profile/scope/TTL source semantics, real protection controls, +client-secret continuity, bounded HTTP/lifecycle and the provider-SDK handoff. +This is document approval, not maintainer acceptance or implementation proof. + +**Review round 2 correction.** Fresh reviewers used GPT-6 Astra at xhigh +(boundary/security) and GPT-6.1 Sol at high (delivery/corpus) effort. The latter +approved; the boundary reviewer found the exact TTL assertion incompatible with +the pinned provider's separate clock reads. Independent source inspection +confirmed the counterexample: `iat` sampled at 1,000,999ms is 1000; expiration +sampled at 1,001,000ms plus 900s is 1901. This is a source-level control, not a +runtime reproduction. The gate, TTL contract, proof obligations and acceptance +carrier inventory now distinguish configured lifespan from measured issuance. +The old equality completion criterion is explicitly replaced at acceptance. +The original boundary reviewer and a fresh GPT-6.1 Sol xhigh reviewer independently +verified the correction and approved without another actionable finding. + +**Local document validation.** Five Release corpus-consistency cases and seven +ADR parser/lifecycle controls pass with zero failures/skips. All 757 relative +links/fragments in the five changed Markdown files resolve. Added prose wrapping, +whitespace and private-reference checks pass. Accepted ADRs and the complete +dated P02b-5 decision/delivery record remain unchanged. Runtime, real-token, +PostgreSQL, frontend and hosted qualification are not claimed by these checks. + +#### Source references + +- [Keycloak import semantics](https://www.keycloak.org/server/importExport), + [Auth.js Keycloak callback/client guidance](https://authjs.dev/getting-started/providers/keycloak). +- Keycloak 26.6.2: + [default/basic scopes](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java), + [token issuance/expiration](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java), + [issuance timestamp](https://github.com/keycloak/keycloak/blob/26.6.2/core/src/main/java/org/keycloak/representations/JsonWebToken.java#L140), + [clock reads](https://github.com/keycloak/keycloak/blob/26.6.2/common/src/main/java/org/keycloak/common/util/Time.java#L31), + [profile resource](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/UserProfileResource.java), + [user updates](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java), + [account REST](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java), + [built-in account client](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/managers/RealmManager.java). + +**Source-pointer correction — 2026-10-21.** The timestamp and clock links above +targeted the wrong raw-source lines. The actual pinned assignments are +[`JsonWebToken.java` lines 150–151](https://github.com/keycloak/keycloak/blob/26.6.2/core/src/main/java/org/keycloak/representations/JsonWebToken.java#L150-L151) +and [`Time.java` lines 33–34](https://github.com/keycloak/keycloak/blob/26.6.2/common/src/main/java/org/keycloak/common/util/Time.java#L33-L34). +The provider-semantics conclusion is unchanged; ADR-0067 carries the corrected +issuance/expiration and ID-token-expiration references. + +### P02b-6 Step 1 — executable realm and identity declaration (2026-10-21) + +**Status: complete locally; both independent review rounds and fix review pass.** +Acceptance is committed at `285db56b`; implementation stays on `development`. +This record claims no warm-realm reconciliation, BFF session or final-source CI +qualification. Both independent review rounds and their verified corrections +are complete. Step 2 starts next; final-source hosted qualification stays Step 4. + +- `SeedData.IdentityUsers` owns four fixed actor identities and their tenant/host + association. The read-only `--identity-manifest` mode projects scalar facts, + including the host's organization and the narrowly recognized legacy value, + without credentials, persistence access or membership creation. +- The tenant export defines the shared scalar-identity/access-only-audience scope, + actual pinned built-ins including `basic/sub`, protected admin-only profile + attributes, confidential code/S256 client, exact HTTPS callbacks and configured + 900s realm lifespan without named-client overrides. Hub export is unchanged. +- `.env.example` and Compose expose the selected server-only BFF secret source. + Existing confidential-secret verification and the refusal for an older private + file missing the key remain Step 2–3 work, before either entry invokes it. +- `TenantRealmExportTests` compares the committed artifact to typed SeedData and + initially rejects 24 planted mapper, profile, client, scope, identity and TTL + variants; round 1 extends this to 43 as recorded below. + The Docker fixture imports the actual JSON into pinned Keycloak with a separate + PostgreSQL database and owned HTTPS/custom-root trust, with hostname validation + retained. No host certificate store is changed. Real code/S256 issuance passes + for all four declared identities; complete API/profile protection stays Step 4. +- The existing Docker source census now covers `KeycloakFixture` and + `SharedKeycloakRealm` references outside `Database/`, with clean and missing-trait + controls. Existing catalogue counts are unchanged; both P02b-6 behavioural rules + stay Registered until their complete owners ship. + +**Current local validation.** Release solution build passes with zero warnings +and errors. Two export cases, seven corpus/Docker-census cases and seven ADR +parser controls and the existing demo-manifest case pass with zero skips. The +guarded frontend run passes all 1,699 cases across both packages with zero +skips/todos. Eleven actual Keycloak/PostgreSQL cases pass: all four signed token +profiles, live TTL and scope/client configuration, both exact callbacks, +missing/wrong secret and verifier, missing/plain challenge, unregistered redirect, +disabled password grant and correct/wrong/correct CA controls. Fresh expiration +uses the observed UTC/monotonic window with the explicit 2s fixture clock +tolerance; exact realm configuration is independently checked. Owned containers +and network are independently confirmed absent after the run. + +The fixture corrections retain normal provider behavior. Both realm imports use +the unambiguous byte-array/file mapping: the pinned Testcontainers string/string +overload interprets its target as a directory. Owned HTTPS resolves the pinned +provider's Secure loopback cookie behavior without a cookie-forwarding workaround +or changes to the production realm. Sources: +[Testcontainers 4.15.0 mapping](https://github.com/testcontainers/testcontainers-dotnet/blob/4.15.0/src/Testcontainers/Builders/ContainerBuilder%603.cs#L208-L223), +[Keycloak 26.6.2 secure context](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/utils/SecureContextResolver.java#L32-L55). + +**Review round 1.** Two fresh GPT-6.1 Sol reviewers used xhigh effort for +security/correctness and high effort for proof/lifecycle/corpus. The latter +found the new `identity-username` vocabulary kind absent from the existing G20 +completeness allowlist. The existing architecture case was independently run +and failed on that exact discrepancy. The correction includes every declared +username/actor in the completeness assertion and the decoded-literal controls. +It also removes stale PostgreSQL-only skill input descriptions and reconciles +the testing standard's population count. + +The security reviewer reproduced a separate offline export-predicate gap: +optional `sub`, `aud` and dotted identity destinations passed the previous +collision check. The committed realm is clean; no live provider vulnerability +was claimed. The correction checks decoded top-level claim roots, reserved token +setters, known implicit subject/audience writers and unknown effective mapper +types across direct, default and optional sources. Forty-three dirty variants and +an escaped-dot healthy control qualify the extended predicate. Pinned semantics: +[claim setters](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java#L295-L324), +[escaped claim paths](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/utils/JsonUtils.java#L35-L58). +**Round 1 fix validation.** Release solution/integration builds pass with zero +warnings/errors. The complete domain-genericity class plus corpus/Docker-census +controls pass 14 cases; export/manifest proofs pass three cases, including all +43 dirty variants and the escaped-dot healthy control. All have zero skips. +All 1,329 relative links/fragments in the twelve changed Markdown files resolve; +whitespace checks pass. + +**Review round 2.** Fresh GPT-6 Astra/xhigh and GPT-6.1 Sol/high reviewers +approved with four Minor corrections. The boundary reviewer independently +reproduced an offline drift gap: client-role `${client_id}` interpolation could +select an identity/reserved top-level destination. The guard now refuses a +dynamic claim root while preserving the fixed `resource_access` built-in shape. +Three dirty cases extend the total to 46; a healthy prefixed interpolation +control distinguishes the intended boundary from a blanket mapper refusal. +The current committed export was clean throughout; no live mutant consequence +is claimed. Source: +[pinned role mapper](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java#L72-L106). + +The delivery reviewer identified stale Docker prerequisites, first-import client/ +persona inventory and live-phase status. Those descriptions now match the +delivered slice; the destructive warm-upgrade recipe is removed. A fresh +GPT-6.1 Sol/high focused review approves all corrections without another finding. +The two offline export cases pass with zero skips and a clean Release build; +all 1,344 links/fragments in thirteen changed Markdown files resolve before this +closeout addition. Whitespace checks pass. Existing eleven-case provider and +1,699-case frontend receipts above remain source-applicable; the second-round +correction changes only offline proof/docs, not provider configuration or code. + +### P02b-6 Step 2 — owned warm-realm reconciliation (2026-10-21) + +**Status: complete locally; both independent review rounds and fix review pass.** +Step 1 is closed at `95d0a0c8`. The shared development-only client, owned target/ +transport/lock boundaries and field planner are implemented locally. The first +actual complete-core provider run refused before writes at `version/body_limit`; +the accepted allowance and complete-core receipt below resolve that conflict. +The review/correction receipts below close Step 2. Entry-point activation +and final-source hosted qualification remain Steps 3–4. + +#### Server-information response budget — proposal (2026-10-21) + +**Status: Accepted — 2026-10-21.** The maintainer approved the named 512 KiB +exception after the additional investigation below, recorded at `fbd9e7dd`. +The acceptance receipt below precedes dependent implementation. +This is a bounded adjustment to G12's accepted phase-package HTTP envelope, using +its existing decision vehicle. It changes no Accepted ADR, runtime identity +provider, credential, realm authority, mutation policy or application surface. + +**Observed conflict.** The original package requires an authenticated version check +before writes and caps every decoded HTTP response at 256 KiB. Pinned Keycloak's +`GET /admin/serverinfo` returns the full provider/mapper inventory along with the +version; its resource exposes no projection/filter parameter. The actual pinned +PostgreSQL-backed HTTPS fixture returns **292,707 decoded bytes** on each of two +authenticated reads, version `26.6.2`, identity encoding. The current production +client correctly refuses this response at the accepted cap. Source: +[pinned server information resource](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java#L120-L169). + +**Accepted delta.** Only the fixed, authenticated, read-only +`GET /admin/serverinfo` exchange may consume at most **512 KiB decoded bytes**. +Every other response and every outbound body retains **256 KiB**. The 5s exchange +and 120s whole-pass deadlines, redirect/compression refusals, full JSON parsing, +exact version check and request/response cleanup remain unchanged. No caller, +configuration or CLI option can widen this budget or choose another endpoint. +Wrong version, malformed JSON, overflow or uncertainty still refuses before +the first mutation. The extra retained response allowance is at most 256 KiB for +one sequential read; it is not a general transport-limit increase. + +**Alternatives.** Keeping the universal cap with the current server-information +probe leaves this implementation unusable. The authenticated partial-export +alternative examined below can preserve that cap with a broader realm read. +Skipping version validation would weaken the selected target contract. +Parsing only a prefix and treating an aborted/truncated JSON response as success +would not independently validate the complete version document. A general 512 KiB +limit expands every exchange unnecessarily. A provider extension solely for a +version projection adds a custom deployment surface. The named read exception +preserves the stock provider and the other bounds. + +**Qualification.** The two measurement reads use a temporary, explicitly +measurement-only 1 MiB cap, owned HTTPS CA/hostname verification, 5s wait and no +redirects. Only byte count, exact version and encoding leave the probe. Its +temporary source is removed; this is feasibility evidence, not a committed +regression or authorization to change the client. Approval must precede the +dependent bound change. Committed controls must accept the actual document and +an exact 512 KiB document, reject a 512 KiB + 1 overflow, malformed/truncated JSON +and a wrong version before writes. Wrong method/path, unauthenticated/unsuccessful +reads and ordinary exchanges retain the 256 KiB refusal boundary independently. +The complete actual-core provider suite must pass after that implementation. + +**Proposal reviews.** Two fresh independent read-only reviewers, GPT-6 Astra at +xhigh effort and GPT-6.1 Sol at high effort, approve this proposal for maintainer +decision without a verified actionable finding. They confirm the endpoint's +authenticated inventory/no-projection source and G12's decision vehicle. The +security review also inspects 240 pinned resource/runtime source files without +finding a narrower authenticated version route. Neither reviewer reruns the +measurement or claims implementation/hosted qualification. The response-byte +allowance does not bound peak heap: retained chunks, concatenation, UTF-8 text +and parsed JSON add memory overhead. Acceptance was pending at that checkpoint. + +**Independent progress.** Sixty-five offline transport/target/lock controls pass +with zero skips in 10.162s. They cover actual HTTP deadline/body/redirect/abort +behavior, closed canary diagnostics, selected private-source agreement and local +exclusive ownership. They establish local request/response/socket cleanup before +settlement and separately bounded peer closure; neither claims remote rollback. +Actual field-planner diagnostics at this checkpoint remain separate from the +later complete-core receipt below. + +**Independent transport foundation.** The unused-by-entrypoints transport and +target/lock primitives are committed separately from the incomplete planner/core +and the proposed larger read. All their exchanges still enforce 256 KiB. A later +loopback refinement pins `localhost` lookup to IPv4 loopback while preserving the +issuer, HTTP Host and normal TLS hostname checks. Its actual HTTP control poisons +system DNS, observes the supplied lookup and socket address, and verifies the +unchanged localhost Host. The twenty transport cases pass in 10.141s with zero +skips; the unchanged forty-six target/lock controls above remain applicable. +This is an implementation checkpoint, not Step 2 review/qualification closure. + +#### Additional version-source investigation (2026-10-21) + +The maintainer requested further research before accepting the proposed budget +change. At this research checkpoint the proposal remained unaccepted and code +still used the universal 256 KiB cap. These read-only experiments run against isolated +pinned PostgreSQL-backed HTTPS Keycloak, with owned CA/hostname validation and +no redirects. They do not qualify the unfinished whole reconciler. + +| Fixed version-source probe | HTTP result | Decoded bytes | Live version available | +|---|---|---:|---| +| `GET /admin/serverinfo` | 200 | 292,705 | `26.6.2` | +| Same GET with `fields=systemInfo.version` | 200 | 292,705 | `26.6.2`; no projection | +| Same GET with `briefRepresentation=true` | 200 | 292,704 | `26.6.2`; no projection | +| Same GET with `Range: bytes=0-262143` | 200, no Content-Range | 292,705 | `26.6.2`; range ignored | +| `HEAD /admin/serverinfo` | 200, no qualified version header | 0 | No | +| `POST /admin/realms/learnstack/partial-export?exportClients=false&exportGroupsAndRoles=false` | 200 | 44,655 | `26.6.2` | + +The four complete server-information documents use identity encoding and parse +successfully; their one-byte variation is consistent with dynamic scalar fields. +Earlier independent reads measured 292,707 bytes. Parsing takes 0.565–0.769ms in +this small sample. The partial export parses in 0.245ms. These are diagnostic +samples, not a latency comparison, capacity result or production percentile. +Only the oversized measurement reads use the temporary 1 MiB measurement cap; +the partial export succeeds through the unchanged 256 KiB client. + +**A genuine existing-budget alternative.** The fixed partial export is an +authenticated read: its route/export implementation has no configuration-write +or admin-event call, and it assigns `keycloakVersion` from the running JVM's +`Version.VERSION`, not imported realm metadata. Independent tenant realm/user/ +client/profile/credential and Hub snapshots remain identical after the actual +request. POST alone is not evidence of a mutation. Sources: +[route](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java#L1356-L1398), +[live version assignment](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java#L84-L96), +[export and secret stripping](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java#L175-L183). + +False/false excludes users, client objects, role/group collections and service +accounts. It still returns realm authentication/configuration data: the measured +fixture contains 15 client scopes, 21 authentication flows, four authenticator +configurations, 14 required actions and 15 component entries. The export source +masks known secrets; this experiment has no positive credential-masking control +and does not claim the complete document is nonsensitive. Its aggregate size +depends on unrelated realm customization, which can exceed the existing cap. +Scope/mapper and client-policy growth are not wholly new dependencies: the +planner's existing scope-list read already includes all scopes and protocol +mappers, and its realm GET includes client policies. Additional export coupling +includes authentication flows/configurations, required actions, component trees, +localization, IdPs/mappers and scope-role mappings, aggregated into one bounded +document. Sources: +[scope-list projection](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java#L95-L100), +[scope and mapper projection](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java#L828-L841), +[shared realm/client-policy projection](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java#L658-L674). +Using it would require a fixed semantic read classification in the zero-write +proofs; the current method-only test counter would misclassify that POST. + +**Other options.** `kcadm --fields` is client-side output filtering: the complete +HTTP body is copied and parsed before filtering, so it does not solve this +decoded-response limit. Source: +[pinned CLI filtering](https://github.com/keycloak/keycloak/blob/26.6.2/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java#L364-L384). +The Admin Console's resource-version value is not the live release-version +contract. Container `kc.sh --version` is supported but starts another JVM and +reports installed code, rather than an authenticated response from the running +HTTP process. Sources: +[console resource version](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java#L318-L353), +[resource-version reassignment](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java#L119-L143), +[CLI version option](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java#L57-L86), +[JVM launcher](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/dist/src/main/content/bin/kc.sh#L82-L162). +Prefix acceptance weakens complete-document validation; streaming the complete +body or compressing it does not reduce total decoded bytes. + +**Recommendation, not acceptance.** Prefer the fixed 512 KiB server-information +read because version qualification then remains independent of unrelated realm +authentication/configuration growth and avoids exporting that configuration for +a version check. The partial-export route is a viable alternative if retaining +256 KiB universally takes priority. No technical minimum requires 512 KiB: +320 KiB also fits the measured document, with approximately 34 KiB headroom; +512 KiB leaves approximately 226 KiB. This is a bounded headroom choice, not an +automatic expansion rule or a peak-memory guarantee. All other bounds and the +proposed falsifiable controls above remain unchanged. Server-information size +can itself grow with provider inventory; exceeding 512 KiB would still refuse +before writes and require a new explicit decision, not a larger automatic limit. + +All temporary source/scenarios/output and compiled diagnostic classes are +removed. Release integration builds pass with zero warnings/errors. Concrete +owned provider/database/Ryuk containers and networks are independently confirmed +absent. No configuration mutation, bound change or dependent activation is +performed by this investigation. + +#### Server-information allowance acceptance (2026-10-21) + +The maintainer explicitly selects the named 512 KiB server-information exception, +after considering the viable 256 KiB partial-export alternative. Only a fixed +authenticated successful `GET /admin/serverinfo`, without query parameters or a +request body, can use it. All other responses and every outbound body remain at +256 KiB; the 5s/120s deadlines and existing failure/ownership boundaries remain. +There is no configurable limit, automatic fallback or partial-export activation. + +The acceptance commit updates this package and the current navigation carriers +before dependent code. At that checkpoint it claims no completed Step 2, +implemented exception or new provider/hosted proof. The exact-boundary, +negative-purpose and full provider +controls above remain mandatory; the approved two-review-round loop is unchanged. + +#### Shared implementation and pre-review verification (2026-10-21) + +The shared core, field planner and closed launcher are implemented under +`scripts/`. Seed/demo activation remains Step 3; neither entry point invokes +this implementation yet. Step 2's two independent review rounds remain open at +this checkpoint; the local complete-provider receipt follows below. + +The launcher verifies the selected local Compose service, private-source +agreement and exact issuer before admin authentication, then verifies the live +version before planning. Its compiled Seeder identity projection receives only +the existing public tooling environment. A target-specific exclusive file lock +is held through actual owned HTTP/child cleanup; uncertain cleanup retains it. +The accepted response allowance above is implemented without a caller-selected +limit or broader transport change. + +The planner reads the complete bounded plan before applying owned field changes. +Missing named users use one fixed single-user `partialImport`, with +`ifResourceExists: FAIL`, their create-only credential and declared inert role. +It never replays a realm import or assigns a role/password to an existing user. +Independent readback covers preserved state as well as desired values; a fresh +post-apply plan must be empty. + +Actual-provider investigation and pinned-source inspection corrected these +preservation details before review: + +- A profile can project email into username. Census and exact username lookup + must agree on the declared name and provider ID before treating a user as + present or missing. The conflicting imported case refuses before any write. +- Client attributes merge on PUT. Removing the token-lifespan override requires + an explicit null tombstone, rather than omission. Other attributes are retained. +- Client PUT can derive origins, disable authorization services or change service + accounts. Requests explicitly retain the declared origin list and existing + authorization state while omitting unchanged service-account flags. Incompatible + service-account transitions/cleanup refuse before writes; scope assignments + receive exact merged-state readback. +- A needed client PUT refuses existing expiry/rotated-secret metadata that the + provider would discard. Ordinary secret creation time is preserved. Existing + credentials are not rotated to force convergence. + +The offline provider double now models these pinned merge/default/cleanup +semantics. Dirty omission/tombstone controls must fail independent readback; +successful repetitions are not a substitute for the first pass's verification. +The five Node control files pass **122 cases, zero failures/skips**, in 10.210s. +They cover exact response boundaries and negative purposes, real HTTP cleanup/ +deadlines, credential canaries, target/source/lock refusals, complete preflight, +preservation, 409 checks, partial progress and the closed production CLI. +Syntax and whitespace checks pass. No final-source hosted proof is claimed here. + +**Complete actual-core provider receipt.** All four +`TenantRealmReconciliationTests` cases pass with zero failures/skips in 1.7384min +against isolated PostgreSQL-backed HTTPS Keycloak 26.6.2. The actual shared +transport/core uses the accepted allowance without a version projection, cap +override or diagnostic code. The TRX SHA-256 is +`02ffba155dcf5662ed7a7db6e15a849cd9f631f1c63830a93f3973189cc08b77`. + +The controlled warm import preserves provider IDs, changed passwords, MFA, +disabled state, required actions, role assignments, nonmanifest accounts, +unrelated profile/client data, the API service credential/resource-server +settings and the Hub realm. A deliberately removed service-account scope stays +removed; both clients retain empty web origins. Actual code/S256 logins witness +old/new credential continuity and strict signed identity claims. Second/third +completed passes perform zero mutating Admin REST calls. + +The acknowledgement-loss control injects refusal after one real successful +response closes; it does not claim packet loss or remote rollback. Cancellation +and failed readback require explicit verified reruns. Planted identity, mapper, +secret, duplicate and username-projection conflicts refuse before any write even +with a legitimate TTL change pending. Local lock/HTTP race/deadline boundaries +are established by the separate actual-resource Node controls above. + +Account preservation compares exact full stored-account details resolved through +their provider IDs. The intentionally changed global user-profile metadata is +verified separately; including it in an account's preservation baseline would +mistake the owned profile change for a stored-account mutation. All temporary +diagnostic source is removed before the passing complete run. Formal independent +Step 2 review rounds have not yet started. Destruction events and independent +post-run inventories confirm all five owned provider/database pairs, Ryuk and +five networks are gone; foreign resources are untouched. +Fourteen Release corpus, domain-genericity and Docker-trait controls pass with +zero failures/skips in 13s; the changed-file link/fragment audit has zero broken +targets. The scoped C# whitespace verification passes. + +##### Step 2 review round 1 — identity visibility and plan feasibility + +Two fresh independent reviewers inspected the complete committed Step 2 change +through `3776947e`, its callers, accepted contract and pinned provider source. +Both identified a blocking identity-preservation defect: Admin user reads are +profile projections. A missing definition with a disabled unmanaged policy can +hide a stored conflicting actor; the planner had treated it as absent. One +reviewer also reproduced projected inventory/body limits being exceeded only +after an earlier mutation had committed. These findings supersede the initial +local proof's coverage claim for those states; its warm fixture explicitly +enabled unmanaged attributes and did not exercise hidden stored values. + +The actual PostgreSQL-backed Keycloak reproduction performed six writes and +changed the hidden actor before refusing at readback. The corrected planner +qualifies protected attribute visibility before account reads or writes. Hidden, +defaulted, selected or otherwise unqualified identity projections refuse with +`plan/identity_conflict`; it does not write profile settings to reveal conflicts. +The duplicate-actor census also refuses external user-storage projections that +can override realm metadata. Safe explicit admin-readable policies remain +supported, and reconciliation retains the existing unmanaged policy. + +**Remedy follow-up — 2026-10-22:** The preceding no-profile-write result describes +that shipped correction. Accepted [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) +now authorizes the separately bounded preparation remedy after independent +preconditions, without widening unmanaged policy or rewriting this evidence. +Its automatic path remains pending implementation and proof. + +Every static mutation body is checked in the complete read-only plan against +the existing 256 KiB UTF-8 limit. Projected collection and account counts must +fit the same readers used during independent verification and a later run. +The additional byte-feasibility check covers growing response inventories too: +a small valid write must not knowingly make the next scope/user read too large. +Full user listings repeat profile metadata, and inserted accounts can move page +boundaries. Conservative byte accounting can refuse before a count ceiling; +the ceilings do not promise every combined configuration will fit. Transport +and independent readback checks remain backstops. Boundary controls prove +supported states still converge, while excess states refuse with zero writes +even when another legitimate change is pending. + +The identity correction's source-frozen actual-provider class passes **eight +cases, zero failures/skips**, in 2.8699min. Four new cases cover hidden unmanaged +identities, managed identities hidden from administrators, and explicit identity +defaults or selectors. Each refuses before the pending TTL write; an independently +captured snapshot is unchanged, and test-owned post-outcome visibility inspection +proves the stored actor was retained. Existing fresh/warm, credential, partial +progress and zero-write rerun proofs still pass. The TRX SHA-256 is +`1e7206d44e2dc4db21f0e78ef1d02dd2f8c6bd76dd7dbd6693a9b212f200b620`. +The five Node files passed **130 cases, zero failures/skips** at that checkpoint. +After the response-feasibility refinement they pass **133 cases, zero +failures/skips**, in 10.18s, including capped user/scope responses, repeated +profile metadata and a missing metadata-template control. A final-source provider +rerun remains required for Step 2 closeout. Scoped whitespace and diff checks +pass. Independent post-run inventories show no owned provider +containers or networks; the bounded Docker event history lacks one older +destruction event, so it is not claimed as a complete event receipt. Foreign +resources remain untouched. The second fresh independent review is still due +at this checkpoint. + +##### Step 2 review round 2 — derived metadata and inherited identity sources + +Two new independent reviewers inspected `95d0a0c8..29735c78`. Both independently +ran all 133 offline controls with zero failures/skips and identified a false +preservation refusal: intended profile changes alter the derived +`userProfileMetadata` in unrelated-account listings. The earlier warm test's +first two interrupted passes had already applied the profile change before its +successful resumed pass, masking uninterrupted convergence. Actual-provider +confirmation performed eleven writes, retained every independently inspected +account field/actor/credential/role, then falsely refused at readback; the next +explicit pass had zero pending writes. Account-field comparisons remain strict; +only this derived metadata is separated from them, with global profile +configuration still checked independently. + +One reviewer additionally proved that an existing protected mapper's +`aggregate.attrs=true` survived planning and independent verification. Actual +code/S256 exchanges confirmed both defects: aggregation produced the group's +actor instead of the stored actor, while the canonical nonaggregating mapper +inherited an unexpected organization when the user's field was absent. Both +unsafe reconciliations had incorrectly succeeded with zero writes. The token +signatures were independently validated; no credential or token value entered +diagnostics. + +The correction rejects protected aggregation instead of silently repairing the +administrator's setting. A bounded full ordinary-group inventory includes +nested groups and validates parent closure, count and protected attributes. +Each censused account's membership IDs are read without `search`, `first` or +`max`, following the mapper's no-argument group stream rather than selecting a +different paginated branch. Unknown/nonordinary memberships refuse before +writes. The first actual-provider run disproved an initial fixture assumption: +the pinned cached model filters out Keycloak Organization groups even after +the feature is disabled; an enabled organization-member API read confirms the +retained association independently. The corrected fixture must qualify actual +strict token identity, rather than claim an unobserved group fallback. A +separate same-fixture query control found that `search=` is injected as absent +and lists only the parent: two stored ordinary groups produced one result. A +nonempty encoded-space search selects the pinned all-group branch before its +trim, returning both parent and child with complete ancestry. Safe unrelated +groups and memberships remain unchanged. All existing HTTP/count/pass budgets remain +in force; no group, membership or feature-setting write is introduced. + +The fixed single-user import uses the pinned `addUser(false, false)` path and +does not inherit realm default roles or groups. Independent readback requires +each new account's membership set to be empty; unrelated default-group settings +remain preserved. This qualification concerns provider claim sources, not +LearnStack organization membership or application permission. + +**Correction qualification.** The final unchanged-source actual-provider class +passes **13/13 cases, zero failures/skips**, in 4.4234 test minutes (292s including +the owned build/lifecycle wrapper). This local run uses Debug; complete final +Release/hosted qualification remains Step 4. All 23 runtime/test input hashes +match before/after the run and independently match the current source. The TRX +SHA-256 is `ead5c9ed7fb89428afc223664b5bb5a68aabd309b4d6ffe0656d3b7443f97e29`. +Live lifecycle capture binds every one of 14 Keycloak/PostgreSQL pairs, Ryuk and +14 networks to creation/destruction; no owned resource remains, and the foreign +database is retained. The cached-organization control verifies a genuine +member and protected canaries through the enabled organization API, issues a +fresh signed token from a pre-existing code/S256 session while enabled, and +checks a fresh code/S256 token after disabling. Original identity is retained; +test-owned post-result visibility restoration verifies stored organization +attributes and membership unchanged. + +The root independently reruns **142 offline cases, zero failures/skips**, in +10.149s, including the faithful empty-search/descendant control. Scoped syntax, +whitespace/diff, seven ADR parser controls and 1,347 relative links/fragments +across thirteen changed Markdown files pass. The correction is committed at +`b94f6a24`. Two new independent reviewers, GPT-6 Astra and GPT-6.1 Sol at xhigh +effort, approve the bounded correction without a verified actionable finding. +Both independently rerun all 142 offline controls and verify the 13-case TRX and +23 source hashes against the commit. They inspect the real-source group/cache +branches and preservation controls; neither reruns .NET or Docker. Both formal +review rounds, their verified fixes and fresh correction verification are closed. +Step 3's shared seed/demo wiring starts next; Step 4 retains final qualification. + + + +#### Account-console self-service capability — proposal (2026-10-21) + +**Status: Accepted — 2026-10-21.** The maintainer explicitly approved the narrow +capability/mapper package after its two independent reviews and actual-provider +counterfactuals. The reviewed proposal is recorded at `2ef1e148`; subsequent +wrapping corrections do not change its policy. G12's existing phase-package +vehicle owns this bounded adjustment; it introduces no new application +authorization decision or ADR. Dependent implementation remains Step 4 work. +Steps 2–3 can close independently; Step 4's same-seed account-edit proof depends +on resolving this conflict. + +**Verified conflict.** The committed seed users have only their declared inert +realm role. The pinned importer calls `addUser(false, false)`, so it does not +assign Keycloak's default-role composite. An unchanged, PostgreSQL-backed fresh +import completes the built-in `account-console` code/S256 flow and token exchange +with HTTP 200, but authenticated Account REST GET and ordinary-profile POST both +return **401**. Independent effective-role readback finds zero `account` client +roles; `manage-account` and `view-profile` are absent. The built-in console has +zero default client scopes, so the measurement requests only `openid`; it changes +no client, mapper, profile or role. No successful account edit or profile +protection is claimed from these refusals. The temporary measurement is removed +from the committed regression source; its focused run passes three measured +cases with zero skips. TRX SHA-256: +`5ff77dff45f09941046d7e42b3cef57cc29bc5839d57aba5fb9ec457172601fb`. + +**Exact existing constraint.** The accepted Identity preservation clause says: + +> Never reset an existing password, credential, MFA factor, required action, +> enabled state, email/name or role assignment to make a proof pass. + +It also requires an ordinary account-console edit for the same seed user. The +current import cannot satisfy that positive control. A test-only role grant +would qualify a different setup and cannot substitute for delivered behavior. +The proposal changes only the role-assignment part of that constraint for the +named self-service capability below. All other preservation rules remain. + +**Accepted delta.** Declare the built-in `account` client's `manage-account` +role for exactly the four managed development personas. Fresh import and the +single-user create-only import include it. Warm reconciliation adds that exact +mapping only when the capability is missing; it never removes or replaces a +prior mapping. Before any mutation, qualify the built-in client/role identity +and its bounded composite closure: only the stock `manage-account-links` child, +with no realm role or foreign client role. Incompatible administrator +customization refuses rather than editing role definitions or composites. +Already effective capability needs no new mapping. Independent readback checks +both the capability and every original mapping; a completed rerun writes zero. + +The console also needs an account-role claim emitter. Its existing audience +resolver alone does not populate `resource_access.account.roles`; Account REST +checks that field even after its configured introspection fallback. Add one +supported stock client-role mapper directly to the built-in `account-console`, +with a fixed `account` client ID and fixed `resource_access.account.roles` claim. +It emits a String array only in access/introspection tokens, with no role prefix, +ID-token, user-info or lightweight-token emission. Do not attach the broader +`roles` scope or add a realm/all-client role emitter. Retain the console's stock +S256, audience resolver and `fullScopeAllowed=false` settings. + +Before writes, qualify the console's direct/default/optional scope role allowance +and expanded composite closure within the stock account set: `manage-account`, +`manage-account-links` and `view-groups`. The last role remains an allowed stock +scope mapping, not a new user grant. Refuse a wider/customized role allowance or +an effective conflicting emitter/role-transforming mapper, without changing it. +A compatible existing fixed-account emitter needs no duplicate. Preserve all +compatible prior client settings, callbacks, scopes and mapper IDs; independent +readback verifies the exact intended addition and unchanged baseline. + +**Bounded replacement — 2026-10-22:** [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) +permits only the three independently qualified stock-console assignment +detachments; customized graphs still refuse and compatible graphs retain priority. +This adds assignment-only DELETE authority, not deletion of global resources. +Implementation and automatic-path proof remain pending. + +No realm-wide default-role assignment, group inheritance, unrelated account-data +or grant change, Hub/master mutation, new application role or membership is +introduced. +The API continues to ignore all role claims for application authorization. +Existing disabled state, MFA, required actions, passwords and account IDs remain +unchanged; this capability does not make a disabled or action-blocked user able +to log in. The protected profile definitions and BFF callback/client boundaries +remain unchanged. The built-in account-console keeps its existing S256 and +audience machinery; the new mapper carries only its resolved account roles. + +**Cost and alternatives.** `manage-account` is Keycloak's standard owner +self-service capability, not a profile-field-only permission. It includes +credential management and, through its stock composite, linked-account +management for that user's own provider account. This explicitly increases the +four warm personas' provider capability and may add the standard account +audience/role claims to their tokens; it grants no LearnStack permission. The +console mapper belongs to a shared client: it can also restore account-console +access for nonmanifest users who already hold eligible account roles. Their +records and grants stay unchanged. The four-persona restriction bounds new role +grants, rather than every effect of the shared client configuration. +Preserving the current mappings without this addition leaves those personas +unable to use standard account self-service. Manual grants leave a nonconvergent +setup prerequisite. Granting the realm default composite can include unrelated +administrator additions; granting every account or changing role definitions +exceeds this narrow need. Replacing the required positive with a generic 401/403 +would leave attribute protection unproved. + +**Implementation and proof owner.** After acceptance, Step 4 updates the typed +identity declaration/export agreement, the planner's explicit role/client diff +and readback, create-only import, Keycloak README and catalogue assertions. Tests +cover unchanged-import refusal before the change, actual same-seed ordinary edit +after it, protected writes/deletions/visibility with independent admin readback, +fresh/warm exact capability and console mapper, original mappings retained, +shared-client behavior for an already eligible nonmanifest user without a new +grant, no unrelated account-data or Hub changes, zero-write reruns and unsafe +role/scope/mapper customization refusing before writes. The existing actual +warm-provider suite must pass against that final source. No fixture-only role +grant may provide the passing baseline. + +**Sources.** Pinned Keycloak 26.6.2 +[importer](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java#L978-L1035), +[default-role admission](https://github.com/keycloak/keycloak/blob/26.6.2/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java#L103-L133), +[built-in account/console setup](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/managers/RealmManager.java#L470-L535) +and [Account REST requirements](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java#L126-L156). + +**Proposal qualification.** Two independent source/corpus reviews correctly found +that the first role-only recipe omitted the console's role-claim carrier. The +revised fixed-account mapper is qualified by an isolated actual-provider +counterfactual: a fresh code/S256 exchange is HTTP 200 at each stage; the +unchanged user's Account GET/POST are 401, the role-only variant returns 403, +and the role-plus-mapper variant returns GET 200 and ordinary-edit POST 204. +Independent admin readback confirms the changed ordinary field. A combined +protected-attribute replacement returns 400; a deletion request returns 204 +while preserving both stored protected values and the absent organization +field. These are feasibility observations, not complete three-field/profile/ +registration proofs. Default and optional console scopes remain empty. A +whole-client JSON comparison includes the new mapper and is not evidence of +unchanged client settings; exact preservation remains an implementation +obligation. The temporary variant is removed and makes no production change. +The single-case TRX SHA-256 is +`b3d57aecb27543e3c97f6537c75e259fc6d554c858b6fb4844f4a99617424d09`. +The lifecycle receipt confirms the one owned Keycloak/PostgreSQL/Ryuk/network +set is removed and the foreign database retained. No fixture-only grant is a +production or protection baseline. The selected mapper uses Keycloak's supported +[fixed-client role mapper](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java) +and typed resource-access projection. The independent protection proofs remain +Step 4 obligations after any accepted implementation. + +Two independent reviewers, GPT-6 Astra and GPT-6.1 Sol at xhigh effort, approve +the revised package for maintainer decision without a remaining actionable +design finding. Their review verifies the recorded counterfactuals, bounded +capability/mapper ownership and disclosure; it grants no implementation approval. +They do not claim present-tree parity with the experiment while independent +Step 3 entry-point changes proceed. Scoped prose wrapping and link checks pass. + + +### P02b-6 Step 3 — shared seed/demo lifecycle (2026-10-21) + +**Status: complete locally after both independent review rounds, verified fixes +and fresh correction reviews.** Work stays on `development`. Step 2 +is closed at `b94f6a24`; the account-console adjustment above is Accepted and +retains Step 4 implementation ownership. + +- `seed.sh` checks selected/ambient database agreement and the application role, + then performs read-only private realm preflight before stack/migration work. + `seed.mjs` owns the confined Compose prerequisite, selected stack startup, + PostgreSQL readiness and migration, then full readiness, a fresh Release Seeder + build, its argument-free DLL with only the app credential, and the awaited + shared realm reconciliation. +- The demo performs old-private-file preflight before preparation or commands. + It awaits the same reconciler with the exact selected project/file/mode and + signal after application seed, before CI stops Keycloak or starts API/web. +- Build/setup children receive credential-free prerequisites. Migration keeps + only its own credential and explicit selected-stack metadata; API, public web + and Seeder environments do not receive private admin/BFF credentials. Fixed + diagnostics share the missing-secret setup instruction; no existing private + file is silently filled and no old-password promise is printed. +- Parent cancellation joins the shared operation and owned command cleanup. + Local data stays retained; CI's own teardown and stopped-Keycloak public proof + remain part of the shared lifecycle. + +**Local validation.** The three focused lifecycle/source files pass 142 cases +with zero failures/skips/todos; their actual JSON report passes the repository's +validator. The complete guarded frontend run passes **1,722 cases in two +packages, zero skips/todos**. Workspace typecheck/lint and 142 separate realm Node +controls pass. Seventeen relevant Release architecture/corpus/Seeder/Docker-trait +controls pass with zero skips; the Release build reports no compiler warning or +error. Syntax, Bash parsing and scoped diff checks pass. These checks establish +local wiring and source controls, not actual Compose convergence, product +browser behavior, final-source hosted CI or a BFF session. + +##### Step 3 review round one + +Two fresh independent reviewers inspected `2ef1e148..ce05931e` through the +standards, security/lifecycle and testing/corpus lenses: `gpt-6-astra` at `xhigh` +and `gpt-6.1-sol` at `xhigh`. No verified runtime, security or proof-correctness +finding remained. The testing/corpus reviewer identified five over-width prose +locations in the realm guide, catalogue, seed skill and root README. They are +wrapped without changing the contract. The security reviewer independently ran +all 142 realm Node controls with zero failures, cancellations, skips or todos. +The actual seed/demo owner remains separate from both reviewers; no offline +receipt substitutes for its pending lifecycle qualification. + +##### Step 3 review round two and credential correction + +Two new independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at `xhigh`, inspect +`2ef1e148..9b51a0bc`. The proofs/corpus reviewer independently passes all 142 +focused frontend cases with zero skips/todos and validates the actual report. +The security reviewer independently passes all 142 realm Node controls, then +reproduces a credential-confinement defect through an actual copied `make seed`: +the unchanged Makefile prerequisites run before the new Node owner, so matching +inherited Keycloak admin/BFF secrets reach migration restore, build and EF +children. Synthetic credentials and command stubs expose only presence flags; +no Docker or .NET process is required to falsify the confinement claim. + +The correction moves `dev`, PostgreSQL wait and `migrate` into the seed process +owner with selected project/file/mode and only the migration credential. The +Docker-version prerequisite is also owned and receives no private credential. +Compose child environments retain only fixed Docker process prerequisites, so +unrelated inherited application/BFF secrets cannot reach readiness or target +inspection. The existing general migration target and its explicit database +connection argument remain unchanged; the no-argument claim concerns the +application Seeder DLL, not every descendant of `make migrate`. +The actual Makefile regression passes and its planted old-prerequisite variant +fails the same confinement predicate. Selected Docker context/socket/config, +database credentials, private-source continuity and unchanged files are checked +independently across stack, migration and readiness. No real Docker or .NET +execution is claimed from these executable stubs. The two focused changed test +files pass 134 cases; the full guarded frontend run passes 1,728 cases in two +packages with zero skips/todos. Typecheck, targeted lint, 142 realm Node controls, +ADR parser and link checks pass. Fresh correction review and a corrected-source +actual seed run remain pending. Earlier actual seed evidence is bound to +`ce05931e` and requires that new run for this corrected entry path. + +##### Step 3 actual lifecycle evidence before the credential correction + +An isolated clone on `development` at `ce05931e` runs the actual entries without +reading the root checkout's private files or foreign working directories. +`make seed` completes a fresh import with zero realm writes. An owned warm-only +change sets TTL to 1800 and detaches the managed API scope from both named +clients; the next seed performs three writes and independently restores TTL 900 +and both scopes. The third pass performs zero writes. Four-user account-state, +client-ID and Hub digests remain identical. These are bounded drift controls, +not a substitute for Step 2's pre-mapper/profile upgrade proof. + +The clean-clone CI demo completes in 650.4 seconds with Keycloak stopped before +the public API/web proof: nine browser navigations, 24 visibility controls and +27 of 27 audits, with all 27 JSON/HTML report pairs and nine screenshots. All +reports share invocation, commit `ce05931e` and tree +`f446d80096bf3a8119553182df3c1629996b85b4`. All 134 API completions are HTTP 200, +with no malformed or pending output. TLS refusal and timeout controls pass. +Cleanup completes in 10.73 seconds; independent exact-project checks find zero +containers, networks or volumes. Private files, environment and lock are removed; +the unrelated database remains running and tracked clone source remains clean. +This receipt qualifies the named source, not the subsequent credential fix or +Step 4's final PR head. Final-source production demo/hosted qualification remains +Step 4 work. + +##### Step 3 correction review and single readiness owner + +Two fresh independent correction inspections, `gpt-6-astra` and `gpt-6.1-sol` at +`xhigh`, inspect the credential fix at `29bb18df`. Both independently reproduce +an additional cancellation defect: the nested `make wait-postgres` CLI creates +its own detached Docker command owner. Outer and inner two-second escalation +can race, killing the inner owner before it kills Docker. Synthetic Docker +commands continue heartbeating after the outer seed reports cancellation and +completed cleanup. Each probe cleans only its recorded owned groups. + +The correction keeps PostgreSQL readiness directly in the seed's existing +`DemoProcesses` owner: selected `make dev`, direct PostgreSQL readiness, selected +`make migrate`, then full readiness. Stack startup receives no migration +credential; only migration receives it. Increasing a teardown timeout or a +successful happy-path run does not substitute for that ownership change. +The proof reviewer also exposes the actual-Makefile regression's default +five-second test allowance under contention: the combined run passes 147 of +148 cases, while its isolated rerun passes in 3.84 seconds. Its two bounded +subprocess runs require an explicit test allowance. + +The updated two-file focused run passes 136 cases. Actual copied seed/process/ +Makefile/readiness sources now prove cancellation and deadline cleanup with a +TERM-ignoring synthetic Docker command and a 300ms post-return heartbeat check. +The checked nested-readiness mutation fails the same survival predicate in both +cases. Only the nested fixture's cleanup is delayed to expose that competing +owner deterministically; the clean owner retains the native stop helper and +canonical readiness budget. Deadline shortening is internal to the test driver. +Fixture retirement guards never re-probe or signal a handle after observed +absence. The actual-Makefile case has a finite 45-second allowance; each cleanup +case has 30 seconds and bounded child drivers. No Docker or .NET behavior is +inferred from executable stubs. Full guarded frontend validation passes 1,730 +cases in two packages with zero skips/todos; typecheck, targeted lint, 142 Node +controls and link checks pass. Fresh correction review and actual replay on this +single-owner source remain pending. + +A separate isolated actual replay at `29bb18df` again completes fresh, warm and +third seed passes with **0 / 3 / 0 realm writes**. Independent readback restores +TTL 900 and both scopes while retaining account, client-ID and Hub digests. All +three closed logs have zero generated-secret matches. Exact-project teardown +finds zero containers, networks or volumes, removes only the owned environment +and retains the unrelated database. That replay predates the single-owner +readiness correction and does not prove its cancellation behavior. + +##### Step 3 final correction verification and local closeout + +Two further fresh independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at +`xhigh`, inspect the complete Step 3 source through `1f5cc04e`, including the +single-owner correction. Each independently passes all 31 realm-lifecycle +cases. No production lifecycle or credential-confinement finding remains. +The proof reviewer identifies one Minor in the fixture observer: saved tracked +group IDs are probed again after the native helper observed absence. The fixture +now retains that native ESRCH witness and refuses a later probe/signal through a +retired handle; both observation samples consult it. The same reviewer verifies +the correction with no remaining actionable finding. Production source is +unchanged. The corrected file independently passes all 31 cases with its actual +JSON accepted by the repository report validator; targeted lint and formatting +pass. The latest complete guarded run passes 1,730 cases with zero skips/todos. + +The final actual replay uses runtime commit `1f5cc04e` and tree +`62a27504adfeeaae32ca1dad60abcb213b5b0dff`: fresh seed writes zero in 35.66 +seconds, the owned TTL/two-scope drift repairs three in 14.82 seconds, and the +third run writes zero in 14.38 seconds. All exits are zero with no timeout or +generated-secret match. Independent readbacks retain all four account +projections and the user/client-ID/Hub digests. Exact-project cleanup completes +in 10.49 seconds with zero containers/networks/volumes; the unrelated database +remains running. Only the hash-matching owned private environment is removed; +the isolated `development` clone remains clean. The receipt SHA-256 is +`adf46a23598adc7e116210d5925cdcc283d03cdad2d76a2bde5fe2c1ade6732e`. +The subsequent fixture-observer correction changes no runtime qualification +input. Step 3 closes locally. Step 4 retains the approved account-console delta, +actual API/profile/registration qualification, final-source production demo and +complete hosted CI; this closeout claims neither a BFF session nor packet merge. + + +### P02b-6 Step 4 — real identity qualification and closeout (2026-10-21) + +**Status: implementation and independent reviews complete; the PR checks own +final-head qualification.** Work stays on `development`. Steps 1–3 are complete locally; +their source-bound receipts +above retain their limits. The maintainer approved the narrow account-console +capability and mapper adjustment above. No further decision approval is pending. + +Three implementation areas proceed together: the declared four-persona +self-service capability and non-destructive warm reconciliation; actual account +and registration protection with independent stored-state observations; and +real provider credentials through the production API boundary and PostgreSQL. +The API proof retains the existing physical read-only/application-role witness; +it supplies neither alternate claims nor a replacement token validator. + +Fresh import declares both stock account clients, their stock role/scope +baseline and only the approved account mapper/persona-grant additions. Actual +provider comparison against automatic stock bootstrap remains required before +claiming that parity. Warm reconciliation qualifies the existing builtin +configuration before any write and preserves unrelated mappings and identities. + +Offline transport/ownership/convergence controls enter the existing meta job +with pinned Node setup. Each named test file must produce a fresh, nonempty +JUnit report with actual named cases, zero failures and zero skips/todos. The +exact report gate passes its positive control and refuses planted empty-file, +failed, skipped and todo cases. Seven required check names, execution topology +and existing job ceilings remain unchanged. Actual provider cases enter the +ordinary Docker discovery; final timing, complete assignment and hosted fit +remain qualification work. + +No Step 4 runtime success, catalogue promotion, final-source demo, hosted CI or +packet completion is inferred from source implementation or offline controls. +The implementation commit, both fresh independent review rounds and verified +corrections remain required before this step closes. + +#### Step 4 initial qualification + +The frozen implementation compiles in Release with `CI=true`, zero warnings +and zero errors. The exact new meta step passes 148 named Node cases. The full +guarded frontend run passes 1,730 cases in two packages with zero skips/todos; +workspace typecheck and lint pass. Unit, Docker-free HTTP and contract runs pass +2,616, 289 and five cases respectively, with zero skipped cases. + +Initial actual-provider qualification finds fixture defects and remains red: +the API run passes 11 of 12 cases, while its organization-mutation cleanup gets +400 from an attributes-only Admin user update. That final assertion masks any +earlier failure, so no organization-mismatch success is inferred. The provider's +user-profile update needs the unchanged ordinary fields with its attribute map. +The profile/issuance run passes 13 of 19 cases. Five profile cases receive HTML +from Account GET rather than JSON; explicit JSON content negotiation is required +before any success can count as an account-data observation. A live TTL mutant +also shows that omitting an attribute from a client update does not remove its +existing value; restoration requires explicit removal and independent readback. +Registration's ordinary positive and late-session expiration clamping pass. +These are implementation qualification findings, not independent review rounds. + +The broader account/upgrade run executes 24 cases: eight pass and 16 fail, with +zero skips. Failures include the missing JSON negotiation and a real planner/ +readback incompatibility: the pinned provider removes an empty mapper role-prefix +entry, while the intended configuration comparison requires that empty entry. +One warm attempt therefore fails readback after six durable writes. The stock +builtin comparison itself passes before a later status assertion fails; this +does not make its containing test green. + +The narrow correction accepts only the fixed-account mapper's documented +empty/absent role-prefix equivalence. It preserves every required option, +unknown-option refusal and raw preservation check for existing mappers. The +independent fake provider now models the pinned conversion rather than echoing +the requested configuration. Four additional controls cover normalization, +required/unknown options, create/conflict readback and existing-mapper identity; +all five Node suites pass 152 cases with zero skips. Actual-provider reruns and +the JSON/restore fixture corrections remain pending. + +All three completed provider-run resource sets have zero retained containers, +networks or volumes after normal owned teardown; the unrelated database remains +running. The complete architecture run continues against unchanged production +and architecture binaries. Body-only integration fixture corrections are built +separately, without rebuilding those dependencies; case identities and trait +declarations remain unchanged. Current-source Docker census checks remain +required after the collection-boundary extension. +Neither status-only Account HTML nor a failed restore is proof of the intended +protection or recovery. + +#### Step 4 corrected local qualification + +The corrected source passes **55 actual-provider cases, zero skips**: 24 account, +export and reconciliation cases; 19 profile and issuance cases; and 12 production +API cases. Account observations explicitly request JSON and verify its ordinary +fields. User mutations preserve the unchanged ordinary identity fields, restore +the exact attribute map and verify a fresh positive token/API result. Client TTL +restoration explicitly removes the override and independently verifies its +absence before accepting the recovered 900-second token. + +The account run proves fresh builtin parity, four narrow role additions plus +one console mapper on warm upgrade, zero writes on rerun, existing effective +group/composite capability without a new direct grant, and a nonmanifest user's +403-to-JSON-200/edit-204 transition without changing that user's mappings or +data. Five incompatible account configurations refuse before a write after a +working clean twin. Its complete 24-case TRX SHA-256 is +`a2b000ff5f9646ed7e4f03e20e74054a831e71410f863331892fbb3c0b30ca39`. + +Profile mutation uses its own class fixture, separate from the readonly shared +issuance baseline. The final 19-case run executes those classes concurrently on +independent providers. It verifies all three protected attributes, ordinary +account edits and registration, user-editable counterfactuals, fifteen live +token-profile variants with clean recovery, and the late-session expiry clamp. +Its complete TRX SHA-256 is +`f470c252cbbfc908e1d4996278cf116ba2b78eb514755d729c57a6ae6f8a2aa7`. + +The real API run admits all four declared personas through the stock production +authentication path and application-role PostgreSQL owner. Tenant/organization +disagreements stop before the read and persist one defended-tenant rejection +with the expected actor/source/scope. Claimless public reads preserve their +HostOnly ceiling; actual ID/Hub tokens and the wrong CA are refused. Anonymous +reads remain independent of an unavailable identity provider. Its complete +12-case TRX SHA-256 is +`7fafa97c24ea554cb0a629b5c3c952942d1ee54b767a7a988f4b9c5a5e8eb02e`. +Exact-session teardown leaves no owned provider resources; the unrelated +database remains running. + +The complete architecture assembly passes **433 cases with zero skips**. +Production and architecture input binaries remain unchanged across the separate +integration-fixture correction build; 359 SHA-256 observations retain that +boundary. Current-source Docker/corpus checks pass seven cases, followed by two +Docker census cases after the profile class-fixture isolation change. The census +now detects direct public-read fixtures, the named API collection and partial +test classes; its planted missing-trait controls fail the same detector. +Release builds report zero warnings/errors. The corrected exact meta step passes +**152 named cases**, with all report-refusal controls retained. The previously +recorded complete frontend, unit, HTTP and contract runs remain valid for their +unchanged source inputs. Link/fragment and whitespace checks are clean. + +These are local receipts. Step 4's implementation commit, two fresh independent +review rounds, final-source production demo and complete hosted qualification +remain pending. Both P02b-6 catalogue entries remain Registered; no BFF session, +packet completion or merge is claimed. + +#### Step 4 review round one and executed-case correction + +Implementation commit `ea0363e8` is inspected by two new independent reviewers: +`gpt-6-astra` at `xhigh` for security/ownership and `gpt-6.1-sol` at `xhigh` for +proof correctness, API/fixture isolation and CI/corpus. The security inspection +finds no actionable defect and independently passes all 152 Node cases. +The proof inspection reproduces one Major: Node 22.23.1's JUnit reporter emits +passing `testcase` elements for empty named `describe` suites even though its +actual executed-test count is zero. The initial gate therefore cannot establish +the claimed nonempty execution from JUnit alone. + +The correction adds a second reporter to the same Node invocation. It requires +exactly one completed root `test:summary`, positive safe-integer executed-test +count, all executed tests passed, successful completion and zero failures, +cancellations, skips and todos. The JUnit filename/shape checks remain separate. +Three offline controls execute the actual workflow command/gate in twelve child +runs. Both empty-suite counterexamples pass a checked variant removing only the +counter reporter and fail the real command; ordinary/nested real tests pass, +while empty files, failures, cancellations, skips and todos are refused. These +controls run in meta. The original reviewer independently verifies the correction +and the exact complete meta step: **152 executed tests and 152 JUnit cases pass**, +with no remaining actionable correction finding. Formal round two remains +required. + +The CI plan adds advisory weights for 37 realm method selectors (35 live-provider +methods and two offline export controls) from the three complete 55-case TRXs +above. Those receipts contain 53 live-provider cases and two offline controls. +Exact completed row durations are summed and +scaled by the existing historical ordinary ratio, 2.271245. Artifact digests +are retained; source commit is null because it is not embedded in the TRXs. +Fixture startup and discovery costs are not inferred from case durations. +Topology, selectors, default unknown-method estimate, algorithms and time +ceilings are unchanged. All 52 shard controls pass. + +Actual local adapter discovery independently finds **5,902 cases**: 2,910 base, +433 architecture, 2,528 ordinary Docker and 31 native. Both complete assignments +cover the exact population once, genuinely differ and stay within the existing +selector/filter bounds. Forty-two non-base methods retain the explicit unknown +weight default. Estimated summed case durations are not wall-time guarantees; +no hosted fit or execution success follows from this local discovery. + +#### Step 4 review round two and production demo + +Two further fresh independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at +`xhigh`, inspect the complete Step 4 source through `4a3173d8`. Both approve +without an actionable finding. Each independently passes all 152 executed Node +cases, the three actual-workflow gate controls and all 52 shard controls. The +proof reviewer additionally rejects thirteen missing, duplicate, malformed or +unsuccessful summary streams against the real reporter. The security reviewer +independently verifies that only the 37 measured weights and three provenance +records change the plan. Neither reviewer substitutes a local receipt for +complete hosted qualification. Separately, five environment, eighteen +provisioning and forty native-owner offline controls pass. + +An isolated clean `development` clone at runtime commit `ea0363e8` and tree +`34f391c6d837762a94bf6b704cdc1c01f220d041` passes the actual production +`make demo DEMO_MODE=ci` in 649.497 seconds. Contextual application seed and +four-user realm reconciliation complete before Keycloak is stopped for the +public proof. Nine product pages, 24 visibility controls and all 27 audits pass; +all 27 JSON/HTML report pairs and nine visually inspected screenshots exist. +Accessibility scores are 1.00 throughout, with zero warnings, runtime errors, +failures or skips. Both HTTPS refusal controls and the actual timeout refusal +pass; all 134 API completions are HTTP 200. Cleanup completes in 10.750 seconds: +zero owned containers/networks/volumes, vacant owned ports and removed private +files/environment/lock. The unrelated database identity/state/start time remain +unchanged and tracked clone source stays clean. The receipt SHA-256 is +`e4e823a088e90cbcee37988d239741d86bc300bb66dcd4db7e92a405b075d45b`. +The subsequent commit changes CI controls, timing data and this record, not the +demo runtime; final PR-head hosted qualification remains separately required. + +#### Step 4 initial hosted qualification and source ownership correction + +Workflow-dispatch run `39587211807` checks candidate `4a3173d8` against main +`24705a7a`; OpenAPI, meta and secret scanning pass. Frontend typecheck/lint/build +pass, but its test gate refuses the newly added Python counterexample helper as +unclassified repository source. The prior complete frontend receipt predates +that helper; its runtime source census depends on this additional repository +input. The hosted test result is therefore 1,657 passed and one failed, not a +complete passing frontend run. Other execution jobs retain their independent +results; no full-workflow success is claimed. + +The correction declares only `scripts/test-realm-node-gate.py` as non-runtime, +beside the other exact offline CI control owners. The existing source-classifier +test asserts that exact path; the live census also explicitly requires the new +Node reporter among runtime sources. Unknown Python files and unmodeled runtime +formats remain refused. The complete guarded frontend rerun passes **1,730 cases +in two packages, zero skips/todos**. Fresh focused review verifies this correction +before final-source qualification. + +Two new independent correction reviewers, `gpt-6.1-sol` and `gpt-6-astra` at +`high`, approve `1f0a8d06` without an actionable finding. The former independently +passes all nineteen focused genericity cases and validates their actual JSON +report with the repository guard; both pass the three actual-workflow controls. +The latter also checks exact helper ownership, refusal of five adjacent/unknown +paths, continued reporter inclusion and refusal of a runtime import of the +excluded Python source. Workspace typecheck, targeted lint, hook +formatting, whitespace and link/fragment checks pass. The correction changes +neither the product runtime nor CI membership or time ceilings. + +#### Step 4 implementation closeout and PR qualification handoff + +All four approved implementation steps, their two independent review rounds and +the required fresh correction reviews are complete on `development`. + +| Step | Delivered result | Review status | +|---|---|---| +| 1 | Executable import/profile/scopes, four typed stable identities and real fresh issuance | Both rounds and verified corrections complete | +| 2 | Bounded non-destructive warm reconciliation, credential continuity and preflight/readback | Both rounds and fresh correction reviews complete | +| 3 | One seed/demo operation and cancellation/cleanup owner with real lifecycle replay | Both rounds and fresh correction reviews complete | +| 4 | Narrow account self-service, real profile/registration/API proofs, CI ownership and carrier closure | Both rounds and fresh correction reviews complete | + +The completed first hosted run +[`39587211807`](https://github.com/HodeTech/LearnStack/actions/runs/39587211807) +binds its twenty successful execution owners to source `4a3173d8`. Independent +download/readback recomputes assignment from the actual adapter discovery and +verifies **5,902 distinct passing case identities, zero skips**: 2,910 base, +433 architecture, 2,528 ordinary Docker and 31 native. The 53 live-provider +cases and two offline export controls all pass. Every selected case matches its +completed record; all owners +report actual completion and cleanup, without forced cleanup, and all Docker +owners report no retained resources. The longest execution job takes 860 +seconds, below the unchanged twenty-minute ceiling. Both required backend +aggregates pass and verify their artifact/API provenance. Meta, OpenAPI, secret +scan and the hosted production demo also pass. The known frontend source-owner +failure above keeps this **whole run failed**; no corrected-head success is +inferred from it. + +The plan digest is +`c380356092978a923d4ba98108c3a1f7f13e5160bec1522f7848a368af68092d`; +the hosted manifest digest is +`736b7f268398e429ea8b5c04cc2d619d29418dfc9dd3f37a8637639d1fdf9422`. +The actual hosted toolchain is SDK 10.0.402, VSTest +18.7.0-release-26505-111 and adapter 2.8.2, recorded rather than inferred from +local SDK 10.0.302. The declared SDK roll-forward permits this feature band. + +Both P02b-6 behavioural catalogue obligations are now **Implemented** with their +actual Integration/meta owners. Published counts are 231 Implemented, 133 in the +Architecture assembly and 98 outside; the five corpus-consistency cases verify +those counts and owners with zero skips. No new structural rule or test-method +count is invented. The seven live required contexts and strict protection are +independently read back unchanged; no repository setting is modified. + +This is the implementation/review closeout. The PR's required checks own final +head qualification, including complete unchanged-plan A/B assignments and the +production demo. A full rerun selects B; rerunning only failed jobs cannot +establish a complete alternate assignment. No partial run, old-head receipt or +local success substitutes for those checks, and this record claims no merge. +P02b-7 is next: its decision pass owns BFF/session custody, lifetimes, refresh, +CSRF/logout and SDK bearer transport. P02b-8 owns final enforcement and erasure +inventory; Phase 03 owns live membership/authorization. G13's session part stays +Open until that next packet's accepted decision pass. + +#### P02b-6 PR review corrections (2026-10-21) + +Six review observations are verified against `204a1039` and corrected. Tooling +retains explicit proxy, private-CA and package-cache prerequisites; the Docker +version probe uses the existing Compose environment owner. Application +credentials remain confined. Reconciliation preserves cancellation/deadline +classification after transport rejection. Failed lock initialization closes its +handle and removes its exclusive marker before refusal. Seed stack startup and +migrations retain finite 600s and 300s command budgets respectively; the realm +HTTP/pass budgets remain 5s/120s. The integration pyramid and current realm +issuance wording now match delivered provider coverage. + +Local qualification passes 160 Node controls, the complete guarded frontend +suite (1,730 cases, zero skips/todos), web typecheck and focused lint. New fault +controls fail four times against the original implementation and pass against +the correction. Two fresh independent correction reviewers (`gpt-6-astra` and +`gpt-6.1-sol`, both at high effort) approve `204a1039..e0f9798f` without an +actionable finding; each independently passes all 67 affected Node controls. +The PR checks own new-head qualification; earlier source-bound CI receipts are +not promoted to this head. + + +#### P02b-6 systematic corrections and hosted qualification (2026-10-21) + +The correction pass remains on `development`. The implementation/review receipts +above describe their recorded source, not approval of a later PR head. The live +PR checks own complete current-head qualification; this record retains the +source-bound history and the correction obligations. + +**Failed hosted evidence.** Run +[`39598693980`](https://github.com/HodeTech/LearnStack/actions/runs/39598693980) +tests head `eb707ee84f7c3cbc29c4f7ded2b86cb1b7cb5834` through merge source +`c390635d0efeb92b08b3c75485fc541b4ca83d3f` with the identical head/merge tree +`fd08acbbdc0710f0fb5de579bc1c5975ef95a3a9`. + +- Attempt 1 completes all 27 jobs and seven required contexts, with 5,902 distinct + passing cases, zero skips, exact selected/completed/TRX equality, actual cleanup + and verified job/artifact provenance. Its 55 realm cases comprise **53 live + provider cases and two offline export controls**, not 55 provider executions. +- Attempt 2 is failed evidence. Ordinary-10 exports 185 passing and two failing + cases: both `independentFailure: false` variants of + `Native_completed_cancellation_survives_restart_and_independent_failure_is_not_reclassified`. + Its owner reports `tests_failed`, `owned_completion_missing`, forced cleanup + and no Docker-absence witness. Sanitized records and retained job output omit + assertion/stack details. Neither port pressure, resource pressure nor Keycloak + co-membership is established as the cause; no speculative backend fix follows. +- Attempt 3 reruns only failed jobs. Its ordinary-10 passes 195 cases, but the + integration aggregate fails before issuing a receipt. The exact current-attempt + `ci-proof-39598693980-3-base` artifact is absent. The jobs API can project reused + successful sibling rows into the current attempt; those rows do not prove a + fresh execution. The missing receipt upload is a consequence of refusal, not + a different output path. This partial run does not qualify either full layout. + +**Verified corrections.** + +| Boundary | Correction and proof ownership | +|---|---| +| Aggregate evidence | Preserve current-attempt artifact identity and fail closed; distinguish `artifact_api_missing`, `artifact_api_not_unique` and invalid metadata. An executing partial-rerun control refuses reused sibling evidence. | +| Node execution | A single owner derives the complete test-file census and requires exact reviewed per-file executed counts plus same-invocation JUnit. Added/missing files, deleted cases, redistributed cases and empty suites are rejected. | +| Fixture census | The first correction lists 82 classes. Independent round one finds that qualified collection references and other explicit fixture types remain omitted; the follow-up below corrects this census. No measured fixture startup cost is invented. | +| Realm ownership | Only an exact successful single-user `ADDED` receipt establishes creation with the declared credential. An ambiguous 409 or a publicly registered reserved username without the admitted legacy identity refuses. Existing credentials/MFA and unrelated state remain preserved. | +| Effective login | Disabled realm/clients, consent changes and incompatible stock account callbacks refuse before writes. The two legacy declarations remain tied to the typed seed authority; tooling adds no institution-name branch. | +| Token availability | Bounded proactive administrator-token renewal reserves the complete exchange budget and never replays a failed Admin request. The whole pass still ends at 120s. | +| Real provider repair | A planted warm scope drift exposes Keycloak's required `name` on scope updates. The repair carries only retained `name`, retained `protocol` and merged attributes; a model that accepted attributes-only updates no longer masks this path. | +| Local lifecycle | Read selected private files through no-follow owner-only regular-file handles. New Makefile files use mode 0600; old files require explicit operator repair. Check the effective local Docker context before stack work. Remove the implicit BFF-secret fallback. Print fixed seed stage/reason diagnostics without child output or credentials. Migration credentials remain in the confined factory environment, not process arguments. | +| Independent security proof | Inspect actual loopback Docker bindings, exact stored identity for all four personas, ordinary profile preservation, exact ID-token subject/client/nonce/issuer, transport cancellation and trusted-CA behavior. | + +**Plan revision witness.** On the unchanged 5,902-case manifest +`736b7f268398e429ea8b5c04cc2d619d29418dfc9dd3f37a8637639d1fdf9422`, the timing +revision from source `ea0363e8b936c209a9a1bae6e9a027d6877ae596` moves 2,318 +ordinary cases in A (1,043 methods) and 2,256 in B (1,034 methods); Architecture +moves zero cases. This is the old-plan-to-new-plan difference, distinct from +A-to-B independence. No weight is reverted to conceal the failed layout. +The first, still incomplete fixture-class census changes its eligibility witness +to 2,191 cases, of which 2,046 change owner across A/B. The earlier 1,985 witness +covered a smaller subset. Architecture/ordinary A-to-B changes remain 371/2,339 on +that fixed manifest. New tests require a newly discovered manifest and new full +qualification; none of these historical counts are promoted to that source. + +**Receipt corrections and limits.** The Step 1 round-two total of 46 export +variants is historical; it became 58 after the account-console extension, and +this pass expands the existing export proof again. The early Step 2 receipt of +65 transport/target/lock controls precedes the later 20 + 46 = 66 checkpoint; +neither is a current suite count. Those two historical Step 2 review rounds did +not retain model/effort metadata in this record; it is not reconstructed by +inference. Catalogue status was Registered at the earlier Step 4 checkpoint and +became Implemented only at its later recorded promotion. + +The previous-head `39590028974` A/B capture retained and API-digest-verified 46 +raw archives locally. That is a capture-time receipt, not a claim that all 46 +remain downloadable: later attempt uploads overwrite shared artifact names. +Its 152 meta Node controls belong to that previous source; `eb707ee8` executes +160. Auxiliary artifact names now include run and attempt identity. + +A 999-user ceiling bounds inventory, not completion throughput. An independent +999-user/40ms-per-exchange model reaches the unchanged 120s deadline and refuses; +no real scale benchmark or guaranteed convergence at that ceiling is claimed. +All nonmanifest/group safety checks remain. The measured 913s hosted demo job +leaves a thin margin in its existing allowance, but is not a reproduced deadline +failure. The sixteen-minute proof allowance, four-minute cleanup/artifact +reserve, twenty-minute execution ceilings and required context names remain +unchanged. Pinned image preparation is separately bounded before fixture startup +and must fit the same whole-job budget. Sequential aggregate downloads already +complete in 16/30s against their 240s allowance; no unmeasured parallel rewrite +or timeout expansion is bundled. + +**Local verification at `d8139de3`.** The source-censused Node owner passes 234 cases +(30 core, 41 HTTP, 56 ownership, 95 planner and twelve real CLI cases), with no +skips/todos. The guarded frontend passes 1,735 cases in two packages; typecheck +and lint pass. CI controls pass nineteen aggregate, 57 shard and six Node-gate +cases. The actual CLI success/failure/SIGTERM paths execute target validation, +private-source handling, lock ownership, credential-free child commands, full +planner/readback and cleanup; only the external provider boundary is substituted. +Separate actual HTTP and live-provider proofs retain their own coverage. +The readiness fault controls use an actual child-ready marker before injected +deadline expiry and an explicit cleanup release barrier, replacing two fixed +startup/hold sleeps without changing production timeouts. + +The first expanded provider invocation executes 59 cases (53 live and six +offline): 58 pass and the newly exercised scope-update branch fails. The +attributes-only request is independently reproduced and corrected as above. +The current affected set then passes all 21 cases, including all thirteen +reconciliation cases, actual startup/bindings, transport/export and backchannel +controls. Twenty-two architecture/migration/Seeder/Docker controls also pass; +Release builds have zero warnings/errors. This is an affected-source rerun, +not a claim that the earlier 59-case invocation passed. Cached-image fixture +startup measures 19.491s; no cold-pull or fixture-cost estimate is inferred. +The existing export proof now rejects 66 variants; the earlier 46/58 totals +remain as-of receipts. + +Both fresh independent correction review rounds and full frozen-source hosted +A/B qualification remain pending at the `d8139de3` checkpoint. No passing +partial retry, old-source receipt or missing cleanup witness closes that gate. +This correction record claims no merge or P02b-7 delivery. + +**Independent correction round one.** Three fresh reviewers inspect +`eb707ee8..d8139de3`: security/runtime (`gpt-6-astra`, xhigh), CI/provenance +(`gpt-6.1-sol`, xhigh), and provider/corpus (`gpt-6.1-sol`, xhigh). They verify +two Major findings, now corrected: + +- Compose selection reads the selected source before the hardened realm reader. + A temporary FIFO blocks both actual CLI entries before cancellation can run. + The shared first read now uses one no-follow, nonblocking, owner-only regular + file handle and caps bytes read even if the file grows. Six actual-entry + controls cover FIFO, symlink and oversized sources for seed validation and + reconciliation; every refusal exits naturally with no signal or child command. +- The first census misses qualified collection references and other explicit + fixture types. Its declaration-bound replacement recognizes the repository's + explicit `IClassFixture<T>` classes and members of `ICollectionFixture<T>` + collections, excluding comments, literals and unrelated declarations. Unknown + or ambiguous fixture forms refuse. All 116 such classes are included; manually + constructed fixtures are outside this source-declaration census. This is not + a measurement of fixture starts or cost. + +On the same historical 5,902-case manifest, the corrected fixture witness covers +2,527 ordinary cases / 1,147 methods; 2,338 cases / 1,057 methods change owner +across A/B. The census correction changes no case assignment, source timing or +weight. Its plan digest is +`cbe9f7086f0304aa1d8483aba04ba8feb9b462c9468b085f2fec1fcadaa978f5`. + +The updated Node owner passes 240 cases (30/41/56/95/18), including the six +actual-entry controls. Full guarded frontend verification passes 1,735 cases; +typecheck passes. CI controls pass 59 shard, nineteen aggregate and six Node-gate +cases; source topology remains complete. The provider reviewer independently +passes seven offline transport/export/backchannel controls and both Docker +census architecture cases. The mutable root status now distinguishes earlier +completed step reviews from this correction gate. Round two and full +frozen-source hosted A/B qualification remain pending at this checkpoint. + +**Independent correction round two.** Three different fresh reviewers inspect +`eb707ee8..837d9d50`: security/runtime and CI/provenance (`gpt-6-astra`, xhigh) +and provider/corpus (`gpt-6.1-sol`, xhigh). The provider/corpus review approves; +the other two verify one Major each. Their corrections preserve the plan and +all existing execution/cleanup budgets: + +- A collection-attribute alias can hide the marker used by the source census. + Local and separate global-using aliases now explicitly refuse before the + marker fast path; an executing control covers both attribute types. The + 116-class census, plan digest and assignments remain unchanged. The shard + control suite now passes sixty cases. +- Demo's early context check precedes Compose's removal of inherited keys + assigned by the private source. It can therefore inspect a different Docker + environment from the eventual stack. A second five-second check validates + the exact selected environment before every Compose command. Two actual-entry + lifecycle controls fail before the fix and pass after it. The same comparison + exposes seed's reintroduction of inherited `HOME` into its inspection; that + probe now also uses the exact selected environment. Its additional regression + fails before the one-line fix. Docker's + [CLI configuration and context precedence](https://docs.docker.com/reference/cli/docker/) + make these inputs relevant to engine selection; no real Docker or private + environment is used by the fault controls. + +Combined verification passes 240 Node and 1,738 guarded frontend cases, with +zero skips/todos; typecheck, lint and source topology pass. The independent +provider reviewer again passes seven offline cases and two Docker-census +architecture cases, without claiming live-provider execution. Independent +focused verification of these final corrections and full frozen-source hosted +A/B qualification remain pending. No historical failed layout is relabelled. + +**Final focused correction verification.** Two further fresh independent +reviewers approve `f09b16d1`: CI/provenance (`gpt-6.1-sol`, xhigh) independently +reproduces the alias bypass on the prior source and its current refusal, then +passes 60 shard, nineteen aggregate and six Node-gate cases plus topology. +Docker-environment/lifecycle (`gpt-6-astra`, xhigh) independently passes all 38 +lifecycle cases; the real frontend report validator accepts their exact file +inventory with zero skips/todos. Both inspect the fixes without editing source. + +No measured failure justifies extending the operation, HTTP, fixture or CI +deadlines. Proposed aggregate parallelization adds no demonstrated benefit to +the retained 16/30s result; optional password/certificate policy expansion and +a second seed-wide lock do not fix an established defect in this boundary. +Already-rejected incompatible 409 readback remains rejected. Those suggestions +do not replace the verified ownership, target and creation corrections above. + +Local implementation, both full correction review rounds and focused fix +verification are complete before hosted qualification. Full current-source A/B +execution remains the next gate; the +[live PR checks](https://github.com/HodeTech/LearnStack/pull/34/checks) own its +current status. This source checkpoint claims no merge readiness, passing retry +or next-packet delivery. Source-bound hosted receipts are retained separately +from this local checkpoint. + +**Frozen-source A failure and diagnosis follow-up.** Run +[`39628288185`](https://github.com/HodeTech/LearnStack/actions/runs/39628288185), +attempt 1, tests `0c9d28768758aff8f350abbb5b09daf6a7f6e75a` through merge source +`8560880e96320ce82a7eb3b2f124dba8b71d1668`; both have tree +`b71883fd423567db55b48c5b74cdad6b3bbd647a`. All 27 jobs finish: eighteen pass, +seven execution owners fail and both dependent aggregates refuse. No B attempt +or failed-only retry follows this failed A. + +- Base discovery contains 5,907 cases: 2,915 base, 433 Architecture, 2,528 + ordinary and 31 native. The manifest digest is + `187da443e8fc5e3b179714fe7bf8f718ae4a246a7d1ad7ea9d13d8cce5073d34`; + the plan digest remains + `cbe9f7086f0304aa1d8483aba04ba8feb9b462c9468b085f2fec1fcadaa978f5`. + These discovery counts are not passing execution counts. +- The actual genericity assertion rejects a demo username in the manifest + projection. A local run reproduces it. The projection now binds a legacy + identity to its complete declared actor, tenant, username and legacy attribute + in `SeedData`, without a demo-name branch or guard exception. Eight affected + Architecture cases and all three offline export cases pass; unique-username + swaps, tenant rebinding and a fresh valid UUIDv7 actor are rejected. +- Six ordinary owners retain eighteen failed Keycloak cases with 1 ms result + durations. Their existing closed fixture-startup message is absent from + retained diagnostics. Failed ownership receipts report forced cleanup without + a Docker-absence witness; neither a provider leak nor a startup cause is + inferred from those fields. An unchanged owned Linux fixture starts in + 21.665s with its original two-minute cap, strict TLS and actual loopback + binding checks. That ARM64 container probe does not reproduce the hosted + x64 VM or its load, and does not establish the failed cause. +- Frontend, meta, OpenAPI, secret scan and the production demo pass. Frontend + executes 1,738 cases; meta executes 240 Node cases. Its sixty combined CI + controls comprise **41 shard/plan and nineteen aggregate controls**; running + the aggregate module separately repeats those nineteen, not nineteen new + controls. The demo retains nine pages, 27 report pairs, nine screenshots, + actual TLS/timeout refusals and complete owned cleanup. These successes do + not qualify the failed backend execution or the whole source. + +The bounded diagnosis follow-up preserves only the fixture's existing finite +startup stage/reason/cleanup sentence for five explicit integration classes. +It rejects unknown, ambiguous and oversized messages and never exports raw +provider text. Cleanup diagnostics do not supply a cleanup witness; test +outcomes, complete case/result guards and failure status remain unchanged. +This uses ADR-0063's existing sanitized finite-fault seam, with no new authority, +timeout, selection or admission policy. Current-head full A/B qualification +remains open until actual complete executions pass. + +**Diagnosis follow-up reviews.** Two independent reviewers complete each of two +rounds on `5fbbf093`: first genericity (`gpt-6.1-sol`, xhigh) and diagnostics +(`gpt-6-astra`, xhigh), then fresh genericity (`gpt-6-astra`, xhigh) and diagnostics +(`gpt-6.1-sol`, xhigh). All approve their scoped changes without an actionable +finding. The final diagnostics reviewer independently executes all three new +offline controls. Root verification passes all 43 launcher controls, sixty +combined shard/aggregate controls, the eight affected Architecture cases, three +offline export cases and five corpus cases, with zero skips. No local check or +review establishes the hosted startup cause; a new complete frozen-source run +remains necessary. + +**Second frozen-source A and provider classification.** Run +[`39633149831`](https://github.com/HodeTech/LearnStack/actions/runs/39633149831), +attempt 1, tests `6109268ff5b8ba19d71ed569682e763256e8f903` through merge source +`31f701a48fa9ae407b69c3ad0f6e4e43e2c8fdbc`, with identical head/merge tree +`468302f4ef3520fb80cc59467fb99d8434170b0d`. All 27 jobs finish: nineteen pass, +seven ordinary owners fail and integration refuses. Backend aggregate and all +six Architecture owners pass, confirming the corrected genericity boundary. +Frontend/meta/contract/secret/demo successes retain their own current-source +API-bound receipts; no B or partial retry is started on this failed A. + +All twenty failed Keycloak cases now retain the exact closed diagnostic +`database/provider_error/completed`: nine issuance, ten reconciliation and one +self-service case. Every failed owner archive is checked against its immutable +API ID, digest and payload identity. This proves the diagnosis channel, not the +underlying provider cause or Docker absence. A small owned Linux batch starts +six PostgreSQL containers concurrently (three exact custom-network/loopback +fixtures, three default-network controls) in 6.85–7.61s; all containers and +networks are disposed and independently absent. It does not reproduce the +hosted failure. + +The pinned Testcontainers path checks readiness inside the PostgreSQL container, +without a host Npgsql/TLS login. Normal not-ready results retry; the generic +provider code cannot establish a readiness deadline failure. The next narrow +diagnostic distinguishes Docker API status, resource-reaper initialization, +socket and filesystem failure families without using any provider message or +response body. The pinned resource-reaper exception discards its inner cause, +so its code does not invent a timeout/cancellation distinction. The +[Docker exception](https://github.com/testcontainers/Docker.DotNet/blob/1e4015a84fa48cbcfe9002ecc4e2cf14177edc2d/src/Docker.DotNet/DockerApiException.cs) +and [resource-reaper exception](https://github.com/testcontainers/testcontainers-dotnet/blob/37352559c0af87d5c7eeaced1accc2d21e3a4e69/src/Testcontainers/Containers/ResourceReaperException.cs) +are checked at the installed package repository commits. Existing startup, +HTTP and job deadlines, cleanup and failure outcomes remain unchanged. One new +offline canary control checks the classifier and its unknown-message fallback; +it is diagnostic proof, not a provider repair or hosted qualification. + +The first classifier source checkpoint passes seven offline cases and 43 owner +controls; two first-round reviewers approve its privacy and diagnostic logic. +A subsequent root Architecture run exposes the static fixture reference in the +offline control: six cases pass and the Docker-trait sweep fails. The pure +classifier now lives in `KeycloakStartupFailure`; neither the offline test nor +its helper starts or owns a fixture. The guard is unchanged, with no exemption +or misleading Docker trait. The corrected source passes all seven offline +cases with warnings as errors, all seven corpus/Docker-sweep cases and all 43 +owner controls. Final independent verification follows before a new hosted run. + +Two final second-round reviewers (`gpt-6.1-sol` and `gpt-6-astra`, high effort) +approve the complete `6109268f..dc25ebb0` correction, including the fixture-free +boundary, without a remaining actionable finding. Both independently build and +pass all four transport controls in Release with warnings as errors; the first +also passes all 43 owner controls, and the second all three focused Keycloak +Python controls. Both inspect the final seven-case offline and seven-case +Architecture receipts. The sixty combined plan/aggregate controls pass again. +This completes the narrow diagnostic review gate, not provider repair. New +complete current-source A/B qualification remains required. + +**Third frozen-source A and daemon-family diagnosis.** Run +[`39637263886`](https://github.com/HodeTech/LearnStack/actions/runs/39637263886), +attempt 1, tests `fddfc2665ae401e7c8d15bdce988be65f59b327d` through merge source +`567dce35b3b8eee5c79f808edb2338d8c7083728`, with identical head/merge tree +`f451491961a7e9cb33ca21ed4c46c5e55a27df1b`. All 27 jobs finish: seventeen pass, +nine ordinary owners fail and integration refuses. All 37 failed provider cases +retain `database/docker_server_error/completed`, establishing a Docker API HTTP +500 response, not its cause. Their nine archives have independently verified +immutable API IDs, digests and current-source payload identities. All five +auxiliary checks pass with their own source-bound receipts; these do not qualify +the failed integration result. No B or failed-only retry is started. + +The next diagnostic records last-reached PostgreSQL SDK creation/start/readiness +milestones. It privately classifies bounded, shallow HTTP 500 JSON with exactly +one string `message` into six fixed networking/task families; unknown or malformed +responses retain `docker_server_error`. It exports no daemon text, address, +port, path or exception type. Actual owned cleanup precedes classification, and +the diagnostic remains separate from cleanup witnesses and result acceptance. +The categories follow the pinned Moby +[network setup wrapper](https://github.com/moby/moby/blob/6430e49a55babd9b8f4d08e70ecb2b68900770fe/daemon/start_linux.go#L37) +and [port mapping implementation](https://github.com/moby/moby/blob/89c5e8fd66634b6128fc4c0e6f1236e2540e46e0/libnetwork/drivers/bridge/port_mapping_linux.go). +The hosted daemon version and actual response body remain unobserved. + +A source-level port-allocation hypothesis is not a provider repair: an isolated +unchanged-old/corrected-upstream allocator comparison detects mixed wildcard/ +specific-address allocation differences, but the surrounding TCP bind path can +retry collisions. It neither reproduces hosted HTTP 500 nor justifies changing +application fixture bindings. Startup deadlines, test selection, ownership and +failure outcomes remain unchanged. Root validation passes seven offline C# +cases with warnings as errors, seven corpus/Docker-sweep cases, all 43 launcher +controls and sixty combined shard/aggregate controls. Independent reviews and +actual hosted diagnosis remain required before this follow-up can claim +qualification. + +The first independent lifecycle reviewer (`gpt-6.1-sol`, xhigh) approves +`fddfc266..9bbf2a31` and independently passes all 43 launcher controls. The +privacy reviewer (`gpt-6-astra`, xhigh) reproduces a malformed-string fallback +gap: raw unpaired UTF-16 surrogates throw `ArgumentException`, unlike the +already covered escaped-surrogate form. Four before-red controls reproduce +this against the unchanged helper; the correction catches that specific +exception and adds all four controls to the existing offline case. This is a +bounded .NET string-contract correction, not a demonstrated HTTP decoder path +or the hosted Docker cause. + +One owned Linux/ARM64 startup at `9bbf2a31` uses byte-identical fixture/helper +sources and completes in 20.632s with the original 120s startup budget and +strict loopback checks. Awaited disposal and direct API checks confirm both +fixture containers, its network and the isolated runner absent. The successful +isolated startup validates the milestone subscriptions; it neither exercises +the failure classifier nor reproduces hosted load or HTTP 500. + +Two fresh second-round reviewers (`gpt-6.1-sol` privacy and `gpt-6-astra` +lifecycle, both xhigh) approve `fddfc266..fb4ab5eb` without an actionable +finding. They independently pass all seven offline C# cases with warnings as +errors and all 43 launcher controls respectively. The lifecycle review also +checks pinned event ordering, the seven-case Architecture receipt, actual +third-A source/job counts and all 37 retained closed failures, plus isolated +startup source hashes. Both preserve the distinction between a finite +diagnostic, actual resource absence and complete hosted qualification. These +two rounds complete the diagnostic correction review gate; a new frozen-source +full A remains necessary before B. + +**Fourth frozen-source A and publication repair.** Run +[`39642441764`](https://github.com/HodeTech/LearnStack/actions/runs/39642441764), +attempt 1, tests `4467492b363bdb8dd794721c58897d08a1a348c2` through merge source +`38117937fa67a4ecf680ee73e23689e3eda44bb9`, with identical head/merge tree +`b3ccb2ad280c6f6f9150e94dd70be4cc2aff92ee`. All 27 jobs finish: twenty pass, +six ordinary owners fail and integration refuses. All twelve ordinary owners +finish: six pass and six fail. Five failed owners retain eighteen provider failures at +`database_start/docker_port_listen/completed`: PostgreSQL creation succeeds, +then Docker reports a TCP listen failure. The sixth owner retains one distinct +54.013s public-admission failure at `browser 429/browser-discovery`. Each failed +archive has verified immutable API identity/digest, exact current head/merge +payload identities and the same 5,908-case discovery. These failures do not +authorize B, an old-artifact fallback or a failed-only qualification retry. + +The publisher census finds one mixed-address boundary in ordinary execution: +the application PostgreSQL fixture uses Docker's wildcard default, while both +identity publishers use `127.0.0.1`. The native proof PostgreSQL publisher +already uses loopback and runs in its separate VM. In the +[pinned old Moby path](https://github.com/moby/moby/blob/6430e49a55babd9b8f4d08e70ecb2b68900770fe/libnetwork/drivers/bridge/port_mapping_linux.go#L220), +allocation and bind are retried for dynamic ranges, but TCP listen occurs later +outside that retry loop. An isolated Linux socket experiment with unchanged old +and corrected upstream allocators forces both binds before either listen: both +mixed-address orders fail at the second listen with the old allocator; both +pass with distinct ports using the +[corrected allocator](https://github.com/moby/moby/commit/d6620915db0072817d1eccb41a765de69cb38e9c). +Same-address controls +pass on both. The non-root, network-isolated runner is removed and confirmed +absent. This establishes a mechanism, not the hosted daemon version, socket +errno or actual interleaving. + +The application publisher now uses the same loopback modifier and independent +configured/runtime inspection predicate as the identity publishers. Its live +inspection fails startup and disposes the owned container on a mismatch. +Ryuk startup/readiness precedes fixture creation, so its wildcard listener is +already listening before these fixture binds; ordinary bind-time retry remains +available. Roles, credentials, SQL commands, connection identities, test +assignments and deadlines are unchanged. A new application test requires the +actual loopback publication, and an offline control rejects wildcard/foreign +addresses, invalid mapped ports and extra publications. + +An identical isolated Linux application harness proves the change before/after: +the old publication check returns false, the corrected check true. Both runs +verify all four role postures and an actual `learnstack_app` login with neither +superuser nor bypass authority. Disposal is awaited; direct inspection confirms +the exact PostgreSQL container and runner absent after each run. These are two +real fixture startups with copied source/helper/roles-SQL hashes checked, not +a hosted repair or full regression claim. + +The distinct browser failure establishes only its closed discovery phase. The +[CDP contract](https://chromedevtools.github.io/devtools-protocol/index.html) +does not equate an advertised debugging port with an available page target. +Twenty exact-flag isolated local launches succeed immediately; no natural race +is reproduced. A constructed real-browser control suppresses the startup +window, observes an empty target list, then creates an owned page within the +original five seconds. The original single-read assertion refuses that valid +transition; the production readiness helper accepts it in 324ms. Owned browser +groups/profiles are cleaned. This proves a readiness gap, not the CI case's +raw cause; discovery also includes later WebSocket setup. + +The fixture now polls only successful, valid empty target lists. One unchanged +five-second deadline covers HTTP, body and polling; malformed, foreign, +non-page and transport failures are not retried. Owner closure, browser death +and closed diagnostic branding remain enforced. Focused validated JSON reports +pass 44 browser controls with zero skips/todos. Root verification passes all +1,756 guarded frontend cases in two packages, nine C# cases (eight offline and +the actual application publication test) with warnings as errors, seven +corpus/Docker-sweep cases, all 43 launcher controls and sixty combined +shard/aggregate controls. Scoped lint/typecheck pass. These receipts precede +the new independent correction review rounds and complete hosted qualification. + +The fourth A's five auxiliary checks independently pass on its frozen source: +frontend 1,738 cases, Node 240, launcher 43, combined shard/aggregate 60 and +Node-gate six; OpenAPI transport/fixture controls pass and SARIF has no findings. +The demo retains 27 hash-validated report pairs for nine pages, nine screenshots, +all visibility/TLS/timeout controls and complete owned cleanup. Its source-bound +Keycloak-stop/absence prerequisite is also verified. These successes qualify +their individual evidence, not the seven failed jobs or a later head. + +Two first-round reviewers approve `4467492b..1bf18b80` without an actionable +finding: security/ownership (`gpt-6-astra`, xhigh) and browser/proof correctness +(`gpt-6.1-sol`, xhigh). The first independently builds Release with warnings as +errors, passes the offline publication control and both Docker-trait guards, +and verifies the pinned inspection client's existing 100s timeout. The second +independently passes all 44 browser cases with the repository JSON validator. +Both inspect the full correction and preserve the limits on live author proofs, +constructed readiness evidence and unknown hosted daemon/browser causes. A +fresh second review round follows before the next frozen-source full execution. + +Two fresh second-round reviewers approve `4467492b..faa8c2b8` without an +actionable finding: security/publication (`gpt-6.1-sol`, xhigh) and browser/CI +proof lifecycle (`gpt-6-astra`, xhigh). The first independently builds Release +with warnings as errors, passes the offline publication case, both Docker-trait +guards and six real PostgreSQL cases covering publication, four role postures +and application-login privilege denial; exact PostgreSQL and Ryuk containers +are confirmed absent. The second independently passes all 44 browser cases +with validated JSON and checks the full correction's source/ownership boundary. +Neither promotes constructed examples to an observed hosted cause. Both review +rounds are complete; the PR's current-head checks and complete same-source A/B +receipts own hosted qualification. Seven required contexts, strict protection, +the existing shard plan and execution ceilings are unchanged. + +#### Further setup and proof corrections — 2026-10-21 + +The complete A/B qualification at `abd45611` belongs to +[run `39647583156`](https://github.com/HodeTech/LearnStack/actions/runs/39647583156): +both full attempts pass all 27 jobs and all 5,910 .NET cases, with zero skips. +Independent verification checks 25 API-hash-bound archives per attempt, both +aggregate recomputations, identical source/toolchain/population/plan and changed +actual co-membership for Architecture, ordinary and shared-fixture methods. +Those receipts precede the following corrections and do not qualify a later head. + +- Compose, seed and reconciliation distinguish unsafe file properties with the + closed `preflight/private_file` reason and fixed owner/type/link/permission + guidance, including explicit `chmod 600` remediation. Files are not repaired; + paths and contents are not emitted. Oversized or malformed configuration + retains its existing configuration refusal. Existing real-CLI controls cover + the notice before commands, including FIFO/symlink refusal. +- The export drift predicate records malformed profile JSON as a violation. + Its added malformed-profile mutation first throws `JsonReaderException`, then + passes after extending the existing exception filter with `JsonException`. +- The old username swap does not create a duplicate. Duplicating legacy user 0 + onto legacy user 1 would still be masked by the legacy-identity guard. The + corrected control changes only nonlegacy user 3 to user 2's username; an + isolated exact-source mutant removing only username uniqueness admits it, + while the original predicate refuses it. +- The owned fixture CA/leaf expire after 25/24 hours, preserving both five-minute + backdated starts and all other certificate parameters. Isolated certificate + controls prove a trusted chain at +23 hours and leaf rejection after expiry; + the actual provider custom-CA/wrong-CA test also passes and its two owned + containers are independently confirmed absent. +- Testing Standards now states each integration population's actual dependency + requirement while retaining no mocked repositories and happy/edge coverage. + +Local validation passes all 240 source-censused Node cases, 1,756 guarded frontend +cases, three offline export cases and one real provider TLS case, with zero +skips/todos. Seven corpus/Docker-trait controls also pass. The isolated duplicate +and certificate harnesses each pass six +controls. Scoped formatting, lint and typecheck pass. Both fresh independent +correction review rounds remain pending at this implementation receipt. + +[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) is a +Proposed dedicated carrier for the already approved 900-second development +issuance choice. The original phase approval remains valid; this new ADR needs +separate maintainer acceptance before its authority/cross-link changes. It does +not change issuance, API acceptance or the Open G13 session portion. + +##### First independent correction review + +Two new reviewers inspect `abd45611..47069be2`: `gpt-6-astra` at `xhigh` for +runtime/security/proof behavior, and `gpt-6.1-sol` at `high` for ADR/corpus and +approval provenance. The first finds no actionable runtime issue and independently +passes 74 owner/reconciliation Node controls, three export cases, 38 frontend +lifecycle cases and a Release build with zero warnings/errors; no skips/todos. +The second verifies seven ADR parser controls and all scoped links/fragments. +It finds one documentation overstatement: provider-only cases do not configure +application modules. The corrected population sentence requires committed realm +configuration for provider tests and application module configuration for the +combined provider/API cases. ADR-0067 remains Proposed with no verified finding. +The second fresh review round remains pending at this correction receipt. + +##### Second independent correction review + +Two different reviewers inspect `abd45611..d2467543`: `gpt-6.1-sol` at `xhigh` +for runtime/security/proof behavior and `gpt-6-astra` at `high` for ADR/corpus and +decision provenance. Both approve without an actionable finding. The first +independently passes 74 Node controls, three rebuilt export cases and 38 frontend +lifecycle cases, with zero skips/todos. Its isolated exact-source checks pass +four refusal/cleanup, six username-mutant and ten certificate controls, including +late validity, expiry, wrong-root/hostname refusals, SANs and retained algorithms. +The second passes all seven ADR parser controls, all 619 scoped relative +links/fragments and whitespace checks, and verifies the original phase approval +and pinned provider semantics. Both independent review rounds are complete. +ADR-0067 remains Proposed pending its separate maintainer approval; the earlier +hosted A/B receipts do not qualify this changed head. Current-head PR checks own +new hosted qualification; review/merge remain separate. + +#### Dedicated issuance-carrier review corrections — 2026-10-21 + +The maintainer's review of Proposed ADR-0067 identifies the missing dedicated +authority in Security 11's header. The revised draft makes that rationale and +the acceptance action explicit: only after separate approval will the header +derive issuance from ADR-0067 and replace its draft/pending notices. The earlier +phase approval remains valid. Neither that approval nor this review makes the +new ADR Accepted. + +The draft corrects the pinned source anchors against raw Keycloak 26.6.2 lines, +clarifies the absence of an override on either named client and distinguishes +shortening a configured lifespan from reducing token production. It names the +planner's action/readback contract, the core's apply/verify loop and the shared +entry's qualification/ownership responsibilities separately. Dated adjacent +notes preserve the original package's no-new-ADR statement and correct the +historical source pointers without rewriting their original text. Both front +doors now link the Proposed dedicated carrier. + +The provider already copies access-token expiration into the paired ID token. +The draft explicitly retains that consequence, including session clamping; it +selects no independent ID-token or BFF session lifetime. Separate issuance +clocks still preclude exact `exp - iat == 900` assertions. Renewal demand, +refresh-custody/rotation ownership and explicit reasons to revisit the +development setting are recorded without changing the executable 900s value, +API acceptance or G13's Open session portion. + +Three existing real-provider Facts pass with zero failures/skips: fresh signed +issuance for all four identities, shorter late-session issuance/refresh and the +existing live mapper/scope/audience/TTL mutation case. Each positive ID token +is cryptographically validated before paired expiration is compared. An +in-memory ID-expiration control preserves the unchanged access token and both +fresh-window predicates while breaking only expiration equality. Against the +old profile predicate, the fresh-profile Fact produces the expected failed +TRX; the final predicate refuses the planted mismatch. This is a payload +predicate control, not a provider-signed altered token. The red run's exact +process exit code was not retained. Both final executions exit zero, their +owned process groups are absent, and all ten retained exact fixture container +IDs have destruction events plus direct-inspect absence. Existing Fact/Theory +declarations and the 13-case population are unchanged. + +[Run `39656889029`](https://github.com/HodeTech/LearnStack/actions/runs/39656889029) +passes at the preceding `61924f0f` source. That earlier result neither qualifies +these corrections nor supplies a second assignment for their source. Local +validation passes seven corpus/Docker-trait cases, seven ADR parser controls, +all 676 scoped relative links/fragments and whitespace checks. Two fresh +independent correction review rounds follow this implementation receipt; +current-head qualification and ADR acceptance remain separate. + +##### First independent issuance-carrier review + +Two new reviewers inspect `61924f0f..d0528d16`: `gpt-6-astra` at `xhigh` for +security/test-proof behavior and `gpt-6.1-sol` at `high` for ADR/corpus and +approval provenance. Both approve without an actionable finding. They verify +the actual predicate and signed-token call sites, unchanged 13-case population, +raw pinned source lines, reconciliation responsibilities and Proposed-only +authority. The first independently confirms all ten exact fixture containers +absent and inspects the retained red/green summaries. The second independently +passes seven ADR parser controls; both pass whitespace checks. Neither reruns +provider execution or claims hosted qualification. All review subprocesses +finish. A second fresh independent round follows before correction closeout. + +##### Second independent issuance-carrier review + +Two different reviewers inspect `61924f0f..7bb9a3ee`: `gpt-6.1-sol` at `xhigh` +for security/test-proof behavior and `gpt-6-astra` at `high` for ADR/corpus and +approval provenance. Both approve without an actionable finding. They verify +clock boundaries, signed-token validation, the independent in-memory expiration +control, exact pinned upstream lines and the unchanged 13-case population. +Both independently pass seven ADR parser controls and whitespace checks. The +first checks retained TRX counts and directly confirms all ten exact fixture +containers absent. No build/provider execution is repeated; all review +subprocesses finish. Both independent correction review rounds are complete. +ADR-0067 remains Proposed awaiting its own maintainer acceptance. The authority +header/index actions remain gated; these local results do not claim current-head +hosted A/B qualification or permission to merge. + +#### ADR-0067 acceptance and carrier reconciliation (2026-10-21) + +The maintainer explicitly approves the revised ADR-0067 after the completed +correction reviews. Its lifecycle is now **Accepted — 2026-10-21** and its single +index row moves from Proposed to Active. Security 11 derives development +issuance from this ADR while preserving the earlier package approval and +ADR-0064's independent API acceptance boundary. Draft/pending authority notices +are removed from current guidance; both front doors record separate acceptance. + +Dated adjacent notes reconcile the package's vehicle, G13 answer, test-source +and implementation handoff passages without rewriting historical approvals or +Proposed-state reviews. The existing catalogue source/header gains ADR-0067; +canonical obligations, counts, owners and implementation statuses are unchanged. +Architecture 13 and the Keycloak guide retain Security 11 as the ongoing-rule +pointer and distinguish the dedicated issuance decision from phase provenance. + +No runtime, executable realm value, credential, API policy, BFF session decision +or CI/shard setting changes. The earlier actual-token and hosted receipts remain +bound to their recorded sources. Local validation passes seven corpus/Docker- +trait cases, seven ADR parser controls, all 1,439 scoped relative links/fragments +and whitespace/wrap checks. The parser reports Accepted and the index contains +one Active ADR-0067 row. Two fresh independent acceptance-carrier review rounds +follow before publication. + +The preceding [run `39664005457`](https://github.com/HodeTech/LearnStack/actions/runs/39664005457) +at `c33e529e` fails ordinary-6 and the integration aggregate. Its cause is under +separate investigation; this documentation acceptance does not qualify or waive +that failure. + +##### First independent acceptance-carrier review + +Two new reviewers inspect `c33e529e..03ebd77c`: `gpt-6-astra` and +`gpt-6.1-sol`, both at `high`. Both approve without an actionable finding. +They independently verify the single Accepted lifecycle/Active index row, +completed authority references, unchanged approved semantics and catalogue +obligations, and preserved original phase history. Whitespace, added-prose and +tracked-worktree checks pass. No build, provider execution or hosted +qualification is repeated; all review subprocesses finish. A fresh second +round remains required before acceptance-carrier publication. + +##### Second independent acceptance-carrier review + +Two different reviewers inspect `c33e529e..94618013`: `gpt-6.1-sol` and +`gpt-6-astra`, both at `high`. Both approve without an actionable finding. +They independently verify lifecycle/index consistency, complete authority +references, unchanged obligations and preserved original approval chronology. +The second passes seven ADR parser controls; both pass whitespace and clean +tracked-worktree checks. No build, provider execution or hosted qualification +is repeated; all review subprocesses finish. Both fresh independent +acceptance-carrier review rounds are complete. + +The preceding CI triage independently verifies the ordinary-6 archive against +GitHub's digest and finds 224 completed cases: 223 pass and one existing +background-job cancellation/restart case fails. The failed variant has +`independentFailure = false` and `lieOnlyOnReconcile = true`; both sibling +variants pass. Its sanitized TRX has no error payload and the closed failure +location projection retains no location for this source. Neither a timeout nor +an identity regression is established. The integration aggregate correctly +refuses with `producer_not_successful`; the missing aggregate upload is +consequential. The failed receipt is preserved, without a guessed runtime fix. + +##### Closed lifecycle failure-location follow-up + +Inspection confirms that `BackgroundJobPositiveSdkTests.CausalRestart.cs` is +absent from the launcher's finite source-code projection. The correction adds +only that literal filename as `positive_sdk_causal_restart`. When VSTest supplies +that stack location, existing parsing retains its closed code and bounded line +number; it still emits no raw stack, path, exception or provider message. +This enables future diagnostics without claiming to reconstruct the lost +assertion or fix the observed lifecycle failure. Execution, success witnesses, +aggregate refusal and all time/selection budgets are unchanged. + +The existing projection control plants that filename beside allowed/unknown +sources, duplicates, private canaries and an out-of-range line. It first fails +because the causal-restart location is missing, then all 43 offline launcher +controls pass after the exact mapping is added. Source-inventory and per-entry +projection controls cover the same new literal. No new test case, host mutation, +provider run or hosted qualification is claimed. Two fresh independent reviews +of this diagnostic correction follow before publication. + +**Diagnostic correction, first independent round.** Two new reviewers inspect +`330a8e2e..4cb69463`: `gpt-6.1-sol` at `high` and `gpt-6-astra` at `medium`. +Both approve without an actionable finding. The first independently passes all +43 offline launcher controls; the second passes the focused projection control +and independently makes it fail by removing only the new mapping in memory. +They verify literal-source/line bounds, deduplication, finite output and raw +error/path exclusion. Whitespace and clean tracked-worktree checks pass; all +review/fixture subprocesses finish. No build, provider or hosted execution is +repeated. A fresh second diagnostic review round remains required. + +**Diagnostic correction, second independent round.** Two different reviewers +inspect `330a8e2e..e7a5bf04`: `gpt-6-astra` at `medium` and `gpt-6.1-sol` at +`high`. Both approve without an actionable finding. Each independently passes +the focused projection and removed-mapping negative; the second also passes all +43 offline controls and literal/path/line/trace/output-boundary probes. The +launcher is byte-identical to its baseline after removing the one added mapping. +Whitespace and clean tracked-worktree checks pass; all review/fixture +subprocesses finish. Both diagnostic review rounds are complete. No provider or +hosted qualification is claimed; the failed lifecycle receipt remains unwaived. + + +#### P02b-6 additional verification and correction pass (2026-10-22) + +**Status: implementation and local validation complete on `development`.** +Source-bound reviews and correction evidence are recorded below. +[PR #34](https://github.com/HodeTech/LearnStack/pull/34) records current-head +hosted qualification and maintainer review; merge remains separate. External +review assertions are hypotheses until checked against current source or retained +execution evidence. They do not authorize policy changes, host mutations or +cleanup of another task's resources. No next packet or merge starts here. + +The preceding source `57772a2a` has a complete successful hosted execution in +[run `39668841753`](https://github.com/HodeTech/LearnStack/actions/runs/39668841753), +attempt 1: all 27 jobs and seven required contexts pass. Independent artifact +verification binds ordinary-6's 224 distinct passing records to that source; +all three cancellation/restart variants pass, in approximately 24.3–24.5 seconds. +This does not explain or erase earlier failed variants. The failed receipts and +missing error payload are linked by the preceding triage and diagnostic record; +a green run is neither a root-cause analysis nor a reason to relax a deadline. + +ADR-0063 requires materially different full A/B assignments for rollout and +plan/algorithm/fixture-lifetime changes. Normal later pushes require one complete +assignment. Earlier references to current-head A/B are qualification requests for +their recorded changes, rather than an additional permanent requirement on every +push. The `abd45611` A/B receipts remain historical and source-bound. Advisory +weights and source provenance have changed during this packet; unchanged VM counts, +aggregate names and execution ceilings do not mean the plan file is unchanged. + +##### Verified corrections and retained boundaries + +- Actual Compose argv selects a nonsecret, process-only web-secret placeholder + only for recognized lifecycle commands and exact `config --services`. + Container-capable, ambiguous and full-config invocations remain strict. + Private-file ownership/type/link/permission checks remain mandatory: lifecycle + parsing is not permission to read an unsafe secret file. No source file or + provider credential is changed by the placeholder. +- Seed recognizes only locally typed, fixed Compose-selection notices. Demo + setup cancellation exits 130 after owned cleanup; command/readiness deadlines + retain their closed reason. Arbitrary provider/configuration text remains + outside public diagnostics. +- Migration credentials are removed from the inherited environment before tool + restore/build and supplied only to no-build EF children. The migration skill + uses that same environment-only pattern instead of a secret command argument. +- `public-env` qualifies, reads and writes one no-follow descriptor. It refuses + unsafe mode, ownership, link count, file type and size before reading, and no + longer follows a symlink or silently changes permissions. Copied-CLI controls + cover successful preparation, retained secrets, truncation and refusals. +- Node controls exercise forbidden credential destinations, exact issuer/custody, + independent callback/password-grant repair, username query behavior, actor + collisions, created-account checks and lost-write readback. The inherited-secret + exclusion control now contains matching and unrelated canaries. These are + behavioral checks; census counts alone cannot establish assertion adequacy. +- The actual production workflow validator rejects disabled, nonblocking, missing + or duplicate realm-test gates. Offline mutants call that validator; testing + command-string presence alone is insufficient. +- Actor-format and scope-collision export controls use nonlegacy personas so the + separate legacy identity binding cannot mask the rule under test. The latter + retains its own deterministic replacement-actor specimen. +- Failure receipts add only recognized, finite top-level adapter exception kinds. + An unlabelled xUnit assertion or unknown exception remains unclassified; no + message-text guess, raw exception, provider payload or new success witness is + introduced. This improves future diagnostics without diagnosing a lost error. + +##### Findings requiring no new runtime policy + +Proxy casing variants, private CA/package-cache prerequisites, Docker context/config +handling, transport-abort remapping, lock-initialization cleanup and certificate +validity had already been corrected. Existing ID-token expiry, independent expiry +predicate, session-clamp and live TTL controls are retained. The issuance proof uses +its measured clock window and separate readback; it does not promise exact +`exp - iat == 900` or replace that contract with a guessed five-second interval. +The production backchannel's certificate/hostname checks remain intact. + +The committed BFF example is public development data, whereas a missing runtime key +has no automatic fallback; the guide now states both facts. Automatic rotation, +removing the retained API service account/credential, narrowing the accepted full +scope or removing retained provider features are policy changes, not demonstrated +regressions. The approved account-console capability has its own dated maintainer +acceptance above. LearnStack application permissions remain separate. + +Redundant protection mutants need not all fail independently when another operative +check enforces the same refusal. The declared test-file census does not claim to +detect an empty assertion body. A named legacy migration literal is bounded tooling +data, rather than evidence of a domain-specific application branch. Broad historical +CLAUDE consolidation is outside this minimal correction; history is preserved. +Raw historical review transcripts are not committed evidence. Dated summaries and +source commits record the available scope/results; this pass does not invent missing +transcripts or infer a review's validity from elapsed time alone. + +Fresh independent correction rounds and source-appropriate hosted qualification +follow the implementation receipts below. Author checks are not independent reviews. + +[ADR-0068](../decisions/0068-development-warm-realm-qualification.md) is a +Proposed warm-realm correction. Acceptance would change first-write ordering and +permit three independently qualified stock-console assignment detachments. Separate +approval is required before dependent implementation. Existing visibility and +account-console refusals remain active; approval would not itself +prove complete stock-main upgrade compatibility. + + +##### Initial correction validation and tooling review + +The lifecycle correction is committed as `7e8c54f7`. Author controls pass 187 +lifecycle/migration cases and ten held-file CLI cases. Two fresh first-round +reviewers inspect `57772a2a..7e8c54f7`: `gpt-6-astra` and `gpt-6.1-sol`, both at +`high`. They independently pass twenty file/migration cases and 177 demo cases, +respectively; the latter validates JSON with the repository report guard. The +security review demonstrates one additional defect with a fake `dotnet`: the +skill's explicit build can fail and still reach `--no-build` EF in a shell +without errexit. The corrected example uses a subshell and guards build success; +three isolated shell controls prove no EF after failed build, EF-only credential +custody and preserved build/EF failure statuses. No real database is used by +those shell controls. The complete correction still needs its fresh full reviews. + +The expanded author validation passes **251 source-censused Node cases**, all +**43 launcher controls**, six Node-gate controls and sixty combined +shard/aggregate controls. Root validation passes **1,801 frontend cases** in two +packages with the actual repository guard, zero skips/todos. Fresh Integration +and Architecture Release builds produce zero warnings/errors. All three offline +export cases and seven corpus/Docker-trait cases pass. + +Three separate serial testhost invocations execute all three existing native +cancellation/restart variants: **nine passed, zero failures/skips**. Command +wall times are 76.669s, 74.219s and 85.571s, including fixture/runner work; these +are not per-case durations. The same three exact case IDs occur in every run. +All testhost process groups join, and direct inspections confirm absence of +each invocation's two exact created container IDs. The first immediate readback +still finds one owned container; later reads of those same IDs confirm absence. +That first observation is retained, not rewritten as immediate cleanup. No +foreign-resource inventory or cleanup, runtime fix, retry-until-green, deadline +increase or historical root-cause claim accompanies these results. + + +##### Complete correction reviews + +Two fresh reviewers inspect the complete `57772a2a..dbc8e025` correction, +including the guarded migration example: `gpt-6-astra` and `gpt-6.1-sol`, both at +`high`. Both approve without an actionable finding. They independently pass all +251 Node cases, 43 launcher controls and six Node-gate controls; the proof reviewer +also passes the sixty combined shard/aggregate controls. The separately executed +nineteen aggregate cases are included in sixty, not additional coverage. In +isolated source copies, the new username/census controls pass clean and fail when +their respective production `exact=true` or `exact=false` parameter is removed. +All review subprocesses join; no provider or .NET execution is repeated. + +Two different fresh second-round reviewers inspect that same complete correction: +`gpt-6.1-sol` and `gpt-6-astra`, both at `high`. Both approve without an actionable +finding. The security reviewer independently passes 197 focused frontend controls +across the four affected suites. The proof reviewer passes 251 Node, 43 launcher, +six gate and sixty combined controls. Its initial hyphenated-file `unittest` +discovery executes zero cases and is excluded from evidence; direct script runs +supply the recorded results. All review subprocesses join. Proposed ADR-0068, +its later documentation revision and new hosted qualification are outside these +code approvals. Both full correction rounds are complete; none establishes the +historical cancellation failure's cause. + +##### Historical-realm and account-capability feasibility + +A separate private archive at `57772a2a` uses the existing owned PostgreSQL-backed, +TLS-qualified Keycloak 26.6.2 fixture. The historical tenant import is exactly +`24705a7a`'s export, SHA-256 +`39659a4e505c8ad3c1b2963e69e58dadb725e4fb37b408dcf87214a2bb0d2d07`. +Temporary measurement source and raw output remain private; these are decision +support probes, not committed regressions or automatic-path qualification. +Intermediate harness compile/assertion failures are not counted as product defects +or passing qualification. No private workstation environment is read or changed. + +The original visibility guard refuses `plan/identity_conflict`, zero writes. +Test-owned append of three canonical admin-only definitions has independent full +profile deep-equal readback and reveals the existing legacy attribute. The tool +then refuses `plan/unsupported`, again before ordinary mutations. Assignment +summaries omit protocol; full by-ID reads identify six default and five optional +OIDC scopes. A SAML explanation is not the observed result. The current +bootstrap-parity control derives from today's export and cannot establish this +historical bootstrap path. A separate exposed-conflicting-actor probe preserves +the original account/credential and still refuses with zero reconciler writes. + +An initial feasibility variant manually detaches all eleven console assignments, +then the unchanged reconciler completes thirteen mutations and a zero-write rerun. +One legacy provider ID and its complete credential hash remain unchanged. Actual +code/S256 exchanges validate signed identity/scope for all four personas; console +code/S256 and Account REST GET succeed. Its one Fact passes in 29.52s; TRX SHA-256 +is `1d6f21549028cd903a1d276bb3df480163cbf45507b1c0dcab218ea5710b6a64`. +Both exact fixture containers and the network are directly confirmed absent. + +The narrower follow-up removes only default `roles` and optional `microprofile-jwt` +and `offline_access`. A private copied account module resolves full scope IDs and +binds ID/name instead of assuming summary protocol. Five default and three optional +assignments remain. Thirteen ordinary mutations, preserved legacy ID/credential +hash, zero-write rerun, four strict signed personas and console Account GET 200 all +pass. Its one Fact takes 28.95s; TRX SHA-256 is +`d205a91fce22cfdfd730994b0ddd3dd215398d354bd5855c76ad11478f3cd255`. +The measurement-source hash is +`6224f96197cde534084e00c1073bb3cd32387ccb08e2d71916bdce80800eed70`; +the private account-module variant hash is +`b7db43895726f3964f8da64686167677f5b4fc56c8c611e78dfc6a7e00d22c59`. +Both exact fixture containers and network are directly confirmed absent. This +variant is not the unchanged reconciler. It does not prove automatic preparation, +canonical-stock discrimination, planned DELETE ordering, uncertainty recovery or +preservation for every customized realm. ADR-0068 requires those regressions after +approval; its proposed three-edge path preserves compatible remaining scope state +and needs no durable continuation marker. + +A fresh-import BFF-token probe independently demonstrates Account REST GET and +ordinary profile POST, with stored-field readback. A protected actor replacement +does not persist. Removing the owned account capability and obtaining a new token +produces Account REST 401. The explicit JSON Accept header matters: a preceding +HTML/405 observation is not an account-authorization proof. Under current profile +settings, an ordinary email POST returns 204 but leaves email, username and actor +unchanged; original login and zero-write reconciliation still work. Pinned +Keycloak's ACCOUNT email condition explains the read-only projection. This does +not qualify the separate UPDATE_EMAIL required-action journey. Existing provider +self-service capability remains accepted; automatic email rebinding or a narrower +BFF token capability is not introduced. Its exact fixture pair/network are absent. + + +##### ADR-0068 proposed correction plan and first review + +The maintainer decision covers ADR-0068 and these three correction steps together. +They are Proposed; no dependent runtime starts before approval. Each implemented +step receives a commit, two fresh independent review rounds, verified fixes and +another commit before the next step proceeds automatically. + +1. **Qualified console graph.** Record acceptance and pending catalogue extensions + while retaining shipped Implemented coverage; + add the immutable historical fixture/canonical bootstrap expectations. Resolve + assignment IDs through full representations, preserve compatible graphs and + plan only the three qualified detachments. Prove custom/alias/category/role/ + mapper refusals, partial last-edge recovery and existing grant preservation. +2. **Owned visibility preparation.** Reuse all identity-independent qualifiers + before one absent-definition preparation within the existing lock/deadline. + Add exact trigger/stage/write accounting, durable-progress notices, exact + profile readback and a discarded/rebuilt full plan. Preserve readable prior + definitions during preparation; retain any separately planned ordinary PUT. + Prove real stock upgrade with changed credentials/MFA and hidden-actor + refusal after metadata only; exercise malformed/oversized/uncertain progress, + cancellation and explicit rerun without automatic replay or identity overwrite. +3. **Complete integration and qualification.** Exercise both seed/demo entries, + four-persona signed API issuance and manifest/nonmanifest console self-service, + all protected attributes and shared claim changes. Reconcile catalogue owners, + counts, guides and case/plan evidence. Run source-appropriate complete hosted + qualification under ADR-0063, including full A/B where its change triggers apply; + all seven checks and existing ceilings remain required. No merge or next packet + is authorized by this plan. + +Two fresh first-round reviewers inspect the revised three-edge proposal and its +carriers at `2ef9cf97`: `gpt-6-astra` at `xhigh` for security/design, and +`gpt-6.1-sol` at `high` for governance/proof honesty. Both approve as Proposed +without a verified Blocker/Major. The governance review finds three long prose +lines; they are reflowed without policy changes. It independently passes seven +parser controls, 731 links/fragments and whitespace checks, and verifies the +historical export hash and exact phase quotes. The design review confirms the +subset/last-edge compatible handoff and no additional Minor. All subprocesses +join; neither reviewer repeats provider execution or grants implementation approval. + +Full frontend typecheck independently finds three fixture-only child environments +missing Next's required `NODE_ENV`. The correction explicitly supplies `test` +without inheriting credentials or changing production filtering. Complete frontend +typecheck and lint pass; the four affected suites pass all 197 cases. Fresh +independent checks of this small correction follow before publication. + +##### Final proposal and fixture correction reviews + +Two first-round reviewers inspect the three isolated `NODE_ENV` additions and +proposed plan at `55ff0fe5`: `gpt-6-astra` at `xhigh` and `gpt-6.1-sol` at +`high`. Both approve the fixture correction and approve the plan as Proposed, +without an actionable finding. The latter independently passes seven parser +controls, 306 relative links/fragments and whitespace, and confirms all three +prior wrapping corrections. No frontend execution is repeated by these reviewers. + +Two different fresh second-round reviewers inspect the complete final ADR-0068, +carriers, plan and fixture correction at that same source: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both approve as Proposed, and separately +approve the fixture fix, without an actionable finding. They verify the exact +phase replacements, stock-ID qualification, compatible-mode priority, partial +last-edge recovery, preserved budgets and pending automatic proof. The governance +review independently passes 729 links/fragments and whitespace; both verify the +historical export hash and pinned provider premises. All review subprocesses +join. No build, provider or full frontend execution is repeated. + +Both fresh independent rounds for the small fixture correction and final proposal +are complete. Author verification passes seven parser controls and all 1,065 +scoped relative links/fragments; ADR-0068 still parses as Proposed. Its decision +and three-step implementation plan require separate maintainer approval. The +existing guards remain active; these reviews do not grant runtime authority or +qualify the final source on hosted CI. Publication and its complete current-attempt +assignment follow independently; historical green receipts remain source-bound. + + +##### Maintainer follow-up findings and conditional acceptance authority + +The maintainer directs verification of the remaining findings, correction of +still-valid issues, then acceptance and implementation without another approval +request. This is conditional authority, not a claim that outstanding checks or +new runtime have already shipped. + +The metadata-only first draft's missing second obstacle is superseded by the +current three-edge decision and the two existing phase feasibility receipts. +Those receipts remain private decision-support experiments: the automatic path, +canonical discrimination and actual self-service POST still need committed proof. +The read-only assignment-summary defect is independently corrected under the +existing compatible-scope contract; it grants neither preparation nor DELETE. + +Verified design corrections require every identity-independent refusal/capacity +check before preparation, an exact missing-definition/unmanaged-policy trigger, +admin-view-only preservation, a closed preparation stage and durable-progress +notice, and accounting for preparation plus a separately planned ordinary profile +PUT. All other Admin REST writes are ordinary mutations. The exact three DELETE +paths/status, baseline extraction/regeneration prohibition, opt-in/partial/manual/ +temporary-visibility alternatives and provider-change/retirement triggers are +explicit. Existing Implemented catalogue status/counts remain; acceptance adds +pending extension paragraphs and precise Asserts boundaries instead of erasing +shipped coverage. No universal console role-loss or relative BFF security claim +is inferred without token evidence. + +Raw 26.6.2 source confirms that browser-rendered line indices omit blank lines. +The earlier review's substantive premises hold, but several GitHub line anchors +were wrong. The current draft and mutable guide correct physical source spans; +previous dated review receipts remain intact. The implicit-to-stored profile +configuration consequence and shared-budget worst-case refusal are stated. +A fresh source-bound token/action measurement follows; it cannot replace final +automatic-path qualification. + + + +##### Additional console measurement and independent compatible-read correction + +The independent compatible-read correction is `25de7a61`: full scope GETs bind +summary ID/name/protocol before existing allowance/mapper checks. The provider +fixture now models actual two-field assignment summaries. Author validation +passes 256 source-censused Node cases and six gate controls; no preparation or +DELETE authority is added. Two fresh correction review rounds follow. + +A new private measurement imports the same exact historical export into pinned +26.6.2 and captures 83 endpoint representations, including full console scope, +mapper, allowance and referenced role/composite state. Graph SHA-256 is +`183f1790db8e500a04f8fd16bde0f105455d63bc143b99d7dc8d04106b5d0881`; +measurement-source hash is +`cb50701c8bb182ca16b93e31f67dfb36f86b7f8d00b956b8dd91de24725a40fd`; +the console receipt hash is +`489189669f7e1e548d537b8126e610d5e8cac1a3cb8387c95cd063f38b8796df`. +This captured input is not a qualified production baseline or automatic-path proof. + +For the two existing users, stock `openid` access has seventeen claim keys, no +audience and no realm/client roles. The three test-owned detachments leave it +unchanged. ID tokens retain nineteen keys and console audience. Explicit +`microprofile-jwt` adds only `upn` before detachment; afterward authorization +refuses that scope. Both stock clients directly report full scope false. After +thirteen ordinary writes, all four console access tokens add only the observed +account audience and `manage-account`/`manage-account-links` role projection; +ID claims remain unchanged, and a fresh pass writes zero. The final private Fact +then rejects its own overstrict role-hash equality assertion on the intended grant +addition, before POST. This is a harness failure, not a product defect or passing +regression. Actual profile POST/readback remains unverified by this run. Earlier +compile/assumed-audience/missing-user/optional-scope expectations are measurement +errors and excluded. Every measurement process joins; exact owned container IDs +and networks are directly confirmed absent. No foreign resource is inspected. + +The hosted correction run +[`39687329554`](https://github.com/HodeTech/LearnStack/actions/runs/39687329554) +at `8e914a8b`, attempt 1, independently fails ordinary-10. Its immutable artifact +`12387397602` has API-verified SHA-256 +`30be17f155a2c7bbd0bc0b6a31beba3294a62b46450a7a4f4aef985fa4de153e`. +The completed records contain 241 cases and one failed knownFailure=false Outcome +ACK/held-cleanup variant, ID `4172c42b-b84f-59bf-426f-60d6c521ec52`, in 61.95s. +Its sibling passes in 17.19s. The failed execution requires forced cleanup and +lacks successful owned completion. No assertion/location is retained. This is a +different method from the earlier cancellation/restart failure; duration alone +establishes no cause. Investigation and any verified diagnostic correction remain +separate from ADR-0068; no deadline or ownership witness is relaxed. + + + +##### First revised-decision and compatible-read correction review + +Two fresh independent reviewers inspect `8e914a8b..2c06b4a6`: `gpt-6-astra` and +`gpt-6.1-sol`, both at `high`. Both approve the compatible-read correction and +approve the revised ADR for conditional acceptance, without Blocker/Major. The +governance review finds one long plan line; it is reflowed without changing scope. +It independently passes all 256 Node cases, six workflow/census controls, seven +parser controls, 306 relative links/fragments and whitespace. Both verify the +corrected physical provider spans, pre-preparation refusal requirements, preserved +readable definitions, two distinct profile calls, diagnostics/accounting, exact +DELETE paths, baseline limits and pending catalogue extension. All subprocesses +join; no provider, .NET or full frontend execution is repeated. A fresh second +review follows before the acceptance/implementation handoff. + +**Failed-envelope interpretation.** The new ordinary-10 archive is not evidence +that Docker remained live or that native runtime ownership leaked. The launcher +sets `forcedCleanup=true` for failed workload status and sets `dockerAbsent=true` +only on its success path; `owned_completion_missing` also rejects nonzero workload +status despite joined cleanup. Its `cleanupOwnershipComplete=true` is retained. +The successful-completion claim correctly fails, but its cause needs actual test +evidence. NativeSettlement was absent from the finite source projection; the +separate diagnostic correction adds only that literal source and a closed code, +with planted privacy/near-match controls. No deadline, runtime or success witness +is changed by that diagnostic correction. + + + +#### ADR-0068 acceptance and implementation (2026-10-22) + +**Status: Accepted; three implementation steps authorized.** The maintainer directs +correction of still-valid review findings, then acceptance and implementation +without another approval request. Both fresh revised-decision review rounds are +complete. The second pair inspects `02b886f7`: `gpt-6.1-sol` and `gpt-6-astra`, both +at `high`, approve the compatible-read correction and revised decision without an +actionable finding. Both independently pass 256 Node cases, six gate controls, +43 launcher controls and whitespace; every subprocess joins. Their separate first +review approves `d3e69b7e`'s finite source diagnostic; its fresh second review remains +required and is included in Step 1's correction review scope. + +ADR-0068 is now Accepted — 2026-10-22. The two original phase clauses receive dated +bounded replacements; the Step 2 review receives an adjacent remedy follow-up. +Security 11, Architecture 13, Keycloak guidance, index and front doors distinguish +accepted authority from pending implementation. The two existing catalogue rules +retain Implemented status/counts with dated pending extension Asserts and owners. +No Accepted ADR body other than this newly accepted decision is changed. + +The three correction steps above proceed automatically with commit and two fresh +independent review rounds per step. Step 1 qualifies the fixed historical graph +and scoped detachments; Step 2 adds owned preparation and fresh planning; Step 3 +completes actual-provider/lifecycle/POST/CI proof and catalogue extension delivery. +No automatic-path activation, complete upgrade claim, green final-source CI or +merge follows merely from acceptance. + +Acceptance-carrier checks pass five CorpusConsistency cases, seven ADR parser +controls, 1,454 actual Markdown relative links/fragments and whitespace. The parser +reports Accepted; the index has exactly one Active ADR-0068 row. Existing inline +code examples are not treated as live Markdown references. + +The bounded native-settlement investigation executes three serial paired runs: +all six cases pass on an isolated `2c06b4a6` source, whose backend is identical to +failed source `8e914a8b`. Release build passes without warnings/errors. All exact +six observed fixture containers are directly confirmed absent without forced +removal; no created network is observed. macOS/SDK 10.0.302 differs from hosted +Linux/10.0.402. This is targeted evidence, not the lost assertion's root cause or +a waiver of the failed hosted assignment. No runtime, deadline or ownership +witness is changed; final source still requires complete qualification. + +#### ADR-0068 Step 1 — qualified stock assignment implementation (2026-10-22) + +The first correction step adds full stock-graph qualification and the closed +assignment-only DELETE owner. Compatible existing graphs retain priority, +including compatible custom definitions with historical scope names. Only a +successfully read, definitively incompatible graph can reach the fixed historical +qualifier. Unknown fields, wrong IDs/categories, extra edges, mapper/configuration +changes and unqualified role/composite/container bindings refuse before apply. + +The committed stock expectation preserves stored and effective mapper DTOs +separately; generated IDs are normalized only after independent current reads. +The [extractor](../../scripts/extract-development-realm-stock-console.mjs) checks +an observation against that fixed expectation and cannot overwrite it. Its +[provenance](../../scripts/development-realm-stock-console-baseline.json) records +the original historical source, credential-only fixture transformation, provider +image observation and independent capture/extraction hashes. The committed +historical fixture replaces exactly three published example credential values +with placeholders; the provider test injects test-only values in memory. No other +historical configuration is changed. + +Only opaque qualified bindings can invoke the Admin owner's three assignment +paths, each requiring HTTP 204. Their projected remaining graph must pass the +normal compatible policy. A concurrent or uncertain response ends the pass; +explicit reruns qualify the durable remaining subset, and the last incompatible +edge hands later passes to compatible preservation without a marker. All eleven +global stock definitions, account role closure and other clients' prior edges +remain protected. An ordinary repair of a qualifying stock definition refuses +before writes rather than invalidating its own preservation witness. + +Local offline validation passes 287 exact executed Node cases across six +source-censused files, six census/workflow controls and 43 native-launcher/parser +controls, with no cancellations, skips or todos. The actual-core controls cover +exact DELETE paths, all seven incompatible subsets, compatible custom priority, +non-204/lost acknowledgement, explicit resumption, transport/JSON refusal and +conflicting projected global-definition changes. The NativeSettlement diagnostic +correction remains separately source-bound; these results establish no cause for +the failed hosted case and waive no required check. + +The new `TenantRealmStockBaselineTests` passes both real-provider Facts in +47.1781s after a Release build with zero warnings/errors. The first imports the +credential-redacted historical fixture into pinned 26.6.2 and independently +captures 89 endpoint representations, including account assignment reads and the +four referenced role-name/ID/composite bindings. It matches the fixed canonical +hash recorded in the provenance; a second fresh bootstrap changes generated IDs +while preserving that same canonical shape. Actual image identity is recorded +for the observed Linux/arm64 fixture, not asserted as a universal platform ID. + +The second Fact explicitly appends the three definitions as test-owned setup, +then invokes the production ordinary reconciler: sixteen mutations, followed by +zero on an explicit rerun. It independently verifies the five default/three +optional console edges, unchanged eleven stock definitions/roles, existing IDs, +credential DTO hashes, private API secret and other retained state. The two named +clients' separately approved managed-scope additions are explicitly projected; +other clients' assignments remain exact. An earlier harness rejected those +intended additions after successful sixteen-write convergence. The corrected +preservation predicate and complete two-Fact rerun pass; that earlier run supplies +no passing whole-ordinary-path receipt. All four final-run containers and both +networks are independently absent after joined disposal. + +Seven corpus/Docker-trait cases, seven ADR parser controls, 864 scoped relative +links/fragments, project-scoped C# whitespace verification and diff whitespace +checks pass. The broader solution format invocation reports a local workspace +loading warning and exits nonzero; the explicit integration-project verification +covers the three changed C# files. Current-source hosted checks remain required. + +Committed-source review rounds follow before this step closes. This step supplies +no production preparation implementation, password/MFA login or token/profile +POST proof, full 120-second automatic-path claim, hosted qualification or complete +ADR extension implementation claim. Those remaining proofs retain the following +steps' owners. + +##### First independent Step 1 review and interruption correction + +Two fresh reviewers inspect `db3778c8..57497f01`: `gpt-6-astra` at `xhigh` +for security/runtime/proof behavior and `gpt-6.1-sol` at `high` for provenance, +corpus and test meaning. Both find one persisted proof gap: the original +non-204/lost-acknowledgement loop interrupts only the first DELETE. The successful +subset controls do not establish uncertain failure after the final edge followed +by compatible-mode resumption. Both independently reproduce the later positions +successfully; no runtime defect or new decision is claimed. + +The corrected existing control now covers all three deletion ordinals for each +non-204 response, lost acknowledgement and cancellation. It checks the exact +stopped durable prefix, no repeated DELETE, remaining write counts of three/two/ +one, five default/three optional retained edges, last-edge compatible handoff and +subsequent zero-write convergence. The six-file guarded Node census again passes +287 exact cases, with zero cancellations/skips/todos. Runtime behavior, deadlines, +mutation authority and provider expectation remain unchanged. + +The first reviewer independently passes 67 guarded focused Node cases, 43 native +controls and six supplemental lost-acknowledgement/cancellation scenarios. The +second independently passes the full 287-case Node census, 43 native controls and +supplemental resumption probes. Both independently verify historical/redacted +fixture transformations and hashes, capture/extraction provenance and the bounded +pending-proof claims. Both approve the separate acceptance carriers and provide +the second review of the finite NativeSettlement diagnostic correction. Neither +reruns a provider or build; all review subprocesses finish. A different fresh +second review pair follows this committed test correction before Step 1 closes. + +##### Second independent Step 1 review and closeout + +Two different fresh reviewers inspect `db3778c8..72ee83a5`: `gpt-6.1-sol` at +`xhigh` for security/runtime/proofs and `gpt-6-astra` at `high` for governance, +provenance and test meaning. Both approve without an actionable finding. Both +independently pass the full six-file 287-case guarded Node census and verify +source/redacted/patch/canonical/extraction hashes. The first additionally passes +nine interruption-before-commit probes spanning all DELETE positions. The second +passes six gate controls, 43 native controls and seven ADR parser controls, and +independently reproduces canonical extraction from the private 89-endpoint capture. +Whitespace checks pass. Neither repeats provider/build execution or claims hosted +qualification; every review subprocess joins. + +Step 1 is complete locally after both independent review rounds and its verified +proof correction. Step 2 now proceeds automatically under the same Accepted +three-step authority: bounded metadata preparation, all identity-independent +preconditions first, durable-progress diagnostics and fresh complete planning. +Step 3 retains automatic-path, token/password/MFA/self-service and final-source CI +qualification. Nothing here accepts a background-job failure or authorizes merge. + + +#### ADR-0068 Step 2 — owned visibility preparation (2026-10-22) + +The second correction step implements the exact missing-definition/closed-policy +trigger. A preparation probe reads actual provider state and reuses the ordinary +planner's identity-independent qualifiers and capacity checks. It defers only +visibility-dependent identity admission; it invents no account projection or +ownership. Provisional ordinary actions never escape the probe. A successful +probe returns only the absent-definition append and its private exact verifier. + +The owner dispatches at most one preparation PUT, requires HTTP 200 and a JSON +object, then separately GETs and compares the entire profile, including ordered +arrays and unrelated fields. Existing admin-view-only definitions remain exact. +All prior projections/actions are discarded before a fresh complete plan; any +separately necessary ordinary profile PUT has its own admission and write count. +Known independent secret/client/mapper/scope/account/group/storage and byte/count +conflicts refuse before preparation. Newly revealed identity conflicts may leave +metadata durable but admit no ordinary mutation. + +The closed `prepare` stage and dispatched-progress flag survive transport loss, +cancellation, deadlines, later plan/apply/readback refusal and outer cleanup or +lock-release errors. The fixed failure notice instructs inspection of current +realm state before an explicit rerun. Progress is recorded at actual transport +handoff after refresh and pre-dispatch cancellation checks, without claiming a +provider commit merely because the request was dispatched. All ordinary mutation +counts also use this conservative handoff boundary. The existing five-second +request, 120-second pass and response/body/refresh budgets remain unchanged. + +The guarded Node census passes 335 executed cases across seven exact files, +with zero cancellations/skips/todos. Twenty-two new pure preparation controls +include the complete trigger table, preserved readable definitions, strict +profile equality and independent refusal/capacity pairs. Sixty-two core and +24 entry controls exercise actual transport ordering, fresh replanning, separate +profile writes, malformed/non-200 responses, lost acknowledgement, cancellation, +deadline and durable-progress preservation through owned cleanup. These offline +controls do not prove real-provider convergence or final-source hosted fit. + +The actual-provider focused run passes all eleven cases without retries or +skips in 289.261s after Release builds with zero warnings/errors. Seven new +cases exercise the true historical automatic path (seventeen writes, then zero), +a hidden actor (one preparation, fresh-plan refusal, no ordinary writes), +independent secret/custom-stock conflicts (zero writes), lost acknowledgement and +cancellation (one dispatched preparation, explicit sixteen-write resume, then +zero), and partial admin-view-only preservation followed by a separately counted +ordinary profile PUT. Four existing hidden/default/selector variants also pass; +only the unmanaged-hidden variant now admits the exceptional metadata write. +The renamed theory says “before ordinary writes” rather than claiming zero total +writes for that variant. + +The retained TRX SHA-256 is +`89f40f90c099897aca2bfff0454407242dc9195035a4a4200c340040188c0fc9`. +Each new fixture joins disposal and independently checks its two exact container +IDs and network ID absent: fourteen containers and seven networks. The four +existing variants and shared collection fixture complete their existing cleanup; +no separate resource-absence observation is claimed for those lifetimes. +The historical positive control preserves actual provider IDs, password credential +DTO hashes, grants except the approved account capability, all preexisting global +scope definitions, API secret and Hub state. A credential DTO hash is not a +changed-password or MFA login proof. + +Seven corpus/Docker-trait cases, six census/workflow controls, seven ADR parser +controls, 1,283 scoped relative links/fragments, project-scoped C# whitespace and +diff whitespace checks pass. Committed-source independent review rounds follow +below before this correction step closes. Step 3 retains +complete seed/demo lifecycle, changed-password/MFA login, four-persona token and +manifest/nonmanifest self-service POST proof, request/phase cost and hosted +qualification. A passing Step 2 subset does not complete those obligations. + + + +##### First independent Step 2 review and partial-profile correction + +Two fresh first-round reviewers inspect `52c73e60..8b99de3`: `gpt-6-astra` at +`xhigh` for security/runtime/proofs and `gpt-6.1-sol` at `high` for governance, +reliability and test meaning. Both independently pass all 335 guarded Node cases +and reproduce a knowable refusal deferred until after one metadata PUT. With all +four accounts already present, a visible legacy tenant makes an ordinary account +update necessary, but an unrelated writable defaulted attribute's preservation +guard is skipped by the preparation-only branch. Both also reproduce a visible +actor mismatch or duplicate actor being deferred merely because another claim's +definition is missing. These are two verified Major mechanisms of overly broad +preparation deferral, not authorization to adopt conflicting identities. + +The correction derives readable claims from the actual current profile and reuses +the ordinary actor, field and duplicate-actor validators for those values. Only +checks depending on newly exposed values wait for the fresh full plan. The shared +attribute-preservation guard also precedes every prospective existing-account +write. Six new clean/dirty controls cover the profile-preservation failure, +readable actor mismatch/absence, the legacy absence exception, tenant/organization +disagreement, duplicate actor and the genuinely hidden-conflict boundary. The +complete source-censused suite passes 341 cases across seven files, zero +cancellations/skips/todos. The first provider receipt remains bound to the earlier +implementation. After the partial-profile correction, the same eleven actual +provider cases pass without retries/skips in 270.549s after a zero-warning/error +Release build. TRX SHA-256 is +`b701d3166e5266dab904ae7e921a08034db5d2f6683d17c605bc625c8fa5dc83`. +The seven new fixtures again independently establish fourteen exact containers +and seven networks absent after joined disposal; the existing fixtures retain +only their normal joined-cleanup claim. + +Both reviewers find no further verified diagnostic, cleanup, immutable-ADR or +catalogue-status defect; their limits explicitly exclude provider/.NET/hosted +execution. All review and counterexample subprocesses join without tracked edits. +A different fresh second pair reviews the committed correction before Step 2 +closes. Complete Step 3 obligations remain unchanged. + + + +##### Step 1 hosted mapper-reason regression and correction + +[Run `39694542640`](https://github.com/HodeTech/LearnStack/actions/runs/39694542640) +at head `52c73e60`, merge checkout `54730795`, finishes with 25 successful jobs +and failures in ordinary-1 and its integration aggregate. Ordinary-1 retains +220 executed cases: 218 pass and the two unsafe account-console direct/implicit +mapper variants fail. Artifact ID `12391396743` is independently bound to API +archive SHA-256 +`219bdb75b6f13537a9dba07ae386778a396898feb9869151d94e92cea18a77c4`. +The sanitized TRX exposes no assertion payload; empty finite failure locations +are not a diagnosis. Its failed completion envelope likewise proves neither a +runtime resource leak nor unjoined disposal. + +A targeted actual-provider invocation of those exact two rows reproduces both +failures, with no retry, at the reason assertion: stage `plan` is correct, +`unsupported` differs from the existing `mapper_conflict` contract. It is not a +startup failure. The invocation executes two failed cases, zero skips, in +61.217s; retained TRX SHA-256 is +`104eb1c6178f7002c40c902dd967e28fddbcdf7a597656f34e6a3a7a32e72b8d`. +The later zero-write/preservation assertions are not reached in that failed run +and supply no provider-preservation claim. Offline exact variants independently +refuse without writes. + +The stock fallback had reclassified direct mapper incompatibility while trying +its strict baseline. Direct mappers are outside assignment-normalization repair +authority. The correction qualifies that subset with the shared mapper policy +before fallback, preserving `mapper_conflict`. A direct subset need not contain +the resolver if its compatible scope supplies it; the complete graph still +requires exactly one resolver. Two new controls require the precise direct +refusal and prove inherited-resolver preservation plus duplicate rejection. +The full seven-file Node census passes 343 cases with zero cancellations, +skips or todos. The initial inherited-resolver test incorrectly placed it in a scope also +assigned to application clients, triggering their valid duplicate-resolver guard; +the corrected console-only scope isolates the intended existing compatibility. +The code does not weaken application mapper validation. + +The corrected-source provider subset passes all seven selected cases without +retries/skips in 179.348s. All five unsafe variants reach their final zero-write +and exact provider-state assertions; direct and implicit mappers retain +`plan/mapper_conflict`, while the other three retain `plan/unsupported`. Both +historical automatic/partial-admin-view proofs pass with their original write +counts, graph and state assertions. TRX SHA-256 is +`4497a991aab51936afb923cbd60aa6d01d9480a700211580f6a9fe0b183a1db8`. +The two new historical fixtures independently establish four exact containers +and two networks absent; the existing self-service fixtures finish normal +cleanup without a separate absence observation. Every invocation joins. + +Fresh independent reviews follow before this correction closes. No failed +hosted assignment or earlier native settlement failure is waived, and historical +green receipts remain source-bound. + + + +##### Entry-caller durable-progress preservation + +An author follow-through of the seed/demo call chain finds that their existing +outer cleanup can mask the new dispatched-preparation notice. Seed's finally +can replace either a prepared failure or a successful prepared result; demo's +cleanup replacement and local setup-cancellation wrapper can replace a prepared +reconciliation error. These callers are outside the already tested shared +reconciliation owner's own cleanup boundary. + +Ten targeted entry controls first run against unchanged callers. All five real +`RealmError` prepared-progress cases fail while all five nonpreparation twins +pass, isolating this propagation defect. The correction retains the closed +metadata notice through seed cleanup and failed-reconciliation demo cleanup or +local cancellation, without changing unrelated runtime/public-proof errors, +credential flows or the local cancellation exit convention. Six further actual +seed CLI cases extend the entry controls to sixteen additions. The complete +lifecycle file passes all 61 cases, zero skips, in 24.13s; workspace typecheck +and lint pass. Its changed test file receives the configured Prettier formatting. Prepared and unprepared twins prove error/result cleanup propagation, +fixed diagnostics and actual local CLI cancellation/cleanup exits. Successful +demo progress is not retained into unrelated renderer/runtime failures. All +commands join; no actual Compose/provider work is claimed by these stubbed +entry controls. Fresh independent correction reviews follow before closeout. + + + +##### First-round Step 2 correction verification + +Both first-round reviewers independently inspect `8b99de3..16771fc1` and approve +without a remaining verified finding. Each independently passes all 343 guarded +Node cases across seven files and all 61 lifecycle controls. The security reviewer +also passes ten supplemental assertion controls covering the original failures, +genuinely hidden legacy admission, direct mapper conflicts in compatible/stock +graphs and missing/optional-only resolver refusal. The governance reviewer +independently reproduces the old clean/default/visible-actor configurations and +confirms that each dirty version now refuses before preparation with zero writes. +Whitespace checks pass and every review subprocess joins without tracked edits. +Neither repeats provider/.NET/Docker/hosted execution or converts the reported +receipts into independently observed qualification. A different fresh second +pair reviews the whole Step 2 change before closeout. + + + +##### Second independent Step 2 review and closeout + +Two different fresh reviewers inspect the complete `52c73e60..3810b071` Step 2 +change and dependencies: `gpt-6.1-sol` at `xhigh` for security/runtime/proofs and +`gpt-6-astra` at `high` for governance, reliability and evidence meaning. Both +approve without a verified finding. Each independently passes all 343 guarded +Node cases across seven exact files and all 61 lifecycle controls. The security +reviewer additionally passes 92 visibility/mapper cross-product controls across +missing-definition subsets, four personas, visible/hidden conflicts and duplicate +actors, direct mapper failures and explicit rerun. Its first supplemental harness +omits an await on an async fixture; the corrected harness passes and supplies no +product-failure claim. The governance reviewer also passes seven ADR parser +controls and rejects an unverified metadata-capacity hypothesis after checking +the actual derived metadata and reserve model. + +Both verify unchanged Accepted ADR bodies, retained catalogue status/counts, +exact preparation/readback/fresh planning, early readable-fact refusals and fixed +caller progress diagnostics. Whitespace and tracked-tree checks pass; all +review commands join. Neither repeats provider/.NET/Docker/hosted execution or +claims that reported receipts are independently observed. Complete Step 3 proof +is still explicitly pending. + +Step 2 is complete locally after both independent rounds and verified fixes. +Step 3 proceeds automatically under the Accepted plan: genuine historical seed/ +demo entry journeys, changed credentials/MFA, strict signed API issuance and +manifest/nonmanifest self-service, measured request/phase costs, remaining +catalogue/carrier reconciliation and source-appropriate complete hosted checks. +No deadline, identity refusal, required check or earlier failure is waived. + + + +#### ADR-0068 Step 3 — complete historical-path qualification (2026-10-22) + +The third correction step starts after Step 2 closes at `f714a5af`. Its provider +journey adds changed-password/MFA, strict signed persona/API issuance and +manifest/nonmanifest console self-service proof. A separate serialized owner +exercises actual seed/demo entries in private source copies with test-owned +historical bootstrap input. No new production seam or identity policy is inferred +from test setup. Complete request/phase costs, catalogue/carrier reconciliation, +case assignment and hosted qualification follow actual evidence. + +The private entry proof freezes `f714a5af`, keeps production scripts, Makefile and +the desired current realm byte-for-byte, and changes only the proof copy's Compose +import bind to an external owned historical-input directory. This explicit +bootstrap delta allows a newly occupied random CI project to start historical; +it neither prewarms a supposedly empty CI project nor mutates a workstation +realm. Credentials remain private, source attestation belongs to the proof copy, +and its results cannot replace untouched final-source hosted qualification. + +The first private entry experiment freezes source tree +`2b3663df5c8dd566158d8eaeaee12542530d7a6f`; its archive SHA-256 is +`41126981657cc35148af17c470ead345cdc23cde85af4c9e431effe0be4133f3`. +Only three historical credential literals are transformed in the private bootstrap +input; the Hub input is byte-identical. The desired export and production entry +sources remain unchanged. The private receipt SHA-256 is +`353fa9338bc155d363f2f54fc8da5321bfebd8b137d089d31540e700b6c38d17`. + +Actual `make seed` succeeds with seventeen writes, then zero on explicit rerun, +in 36.224 and 16.491 seconds. Independent reads confirm the original provider and +client IDs, credential DTOs, the complete appended profile, retained five default/ +three optional console edges and observed Hub state. The second full snapshot is +identical. Credential DTO preservation alone is not a usable password/MFA proof. +Natural teardown takes 10.416 seconds; all seven exact owned containers and the +owned network are independently absent, with no fallback or forced stop. + +The first actual historical `make demo DEMO_MODE=ci` experiment is **red**: +323.004 seconds, make exit 2, an audit worker exit 1 without a signal at lane 1, +lesson run 3. Nine page navigations and twenty-four visibility controls pass, but +only eight of twenty-seven Lighthouse report pairs complete. Each retained report +has no runtime error/warning and accessibility score 1.0; these partial results do +not establish the full audit suite. The initial two-user/eleven-edge state and live +four-user/eight-edge/three-definition convergence are independently observed. +The demo entry does not expose reconciliation mutation counts; none is inferred. +Its native public receipt SHA-256 is +`ad6a02b69c8561401312ad913e77d0826b579d743449c85a50cfaeeb884876d3`. + +The retained finite diagnostic establishes worker exit only, with no worker stage +or failed report; it cannot identify an audit, protocol or budget root cause. +Natural cleanup takes 10.722 seconds and all owned processes join. The selected +Compose project is empty; the two remaining container IDs and network captured +from the exact owned process tree are independently absent. Five earlier container +IDs were not observed, so their individual absence is not claimed. No retry, +threshold relaxation or automatic replay converts this failed receipt into success. +A separately recorded fresh experiment may assess repeatability; it cannot erase +this failure or substitute for final-source hosted proof. + +The committed historical journey in `TenantRealmApiTests.WarmQualification.cs` +starts the genuine stock profile/eleven-edge graph with a test-owned changed legacy +password, usable OTP credential and an already eligible nonmanifest account. +Immediate pre/post reconciliation snapshots avoid confusing subsequent successful +logins with credential metadata changes. All old provider IDs, credential DTOs, +groups/grants, unrelated account fields, global scope/role graphs, other-client +assignments, API secret and observed Hub state are preserved. Only the approved +manifest capability/identity changes and three console edges differ. + +The final-source Fact passes, one case and zero skips. Four independently signed +access/ID token pairs reach matching AccountSite hosts through the production +bearer handler and physical ReadOnly `learnstack_app` transactions. Changed +password/MFA work before and after; missing/wrong OTP refuses. Both manifest and +eligible nonmanifest users complete ordinary Account REST POST with independent +admin readback. All three protected attribute replacements fail to persist, and +fresh signed claims preserve the manifest identity/nonmanifest authority boundary. +ID-token access hashes are checked before comparing complete signed claim deltas. +The closed legacy-console profile alone admits an absent audience, while still +requiring signature, issuer, lifetime, purpose and `account-console` authorized +party; all normal web/API audience checks remain strict. + +Before upgrade, ordinary Account REST returns 401 for the legacy manifest user +and 200 for the already eligible nonmanifest user. The approved mapper/grant +changes add only the measured account capability; no universal role-loss or +security-gain claim is made. Explicit `microprofile-jwt` has the measured `upn` +access/ID delta before detachment; subsequent new requests for either detached +optional scope return the verified `invalid_scope` callback. An actual pre-upgrade +offline refresh succeeds and yields the credential retained for the later check. +Both original and newly returned refresh credentials are positively checked as +nonempty before the post-upgrade negative, preventing an empty-input false proof. +After upgrade, that credential returns 400 `invalid_grant`, with no access/ID token, +while its independently read offline session remains present. This is the observed +owned historical case, not a universal revocation or session-deletion guarantee. + +Production core passes perform seventeen, zero and zero writes. The third +explicit pass follows real self-service edits and preserves their stored fields, +credentials and grants. They issue 481/301/301 bounded requests in 3.126/1.352/1.280 +seconds; preparation uses two requests and the initial/fresh plan each use 112. +Fixture startup is separately measured at 19.130 seconds and token/API/profile +work at 13.220 seconds. These are small-fixture observations, not worst-case +capacity or deadline-fit bounds. The existing five/120-second request/pass limits +are unchanged. The Fact's exact recorded duration is 40.2057204 seconds; its TRX +SHA-256 is `3487a4510af4444908eaef908365e8cc4334b0dfc6a531b0af25276f49e657c9`. +A separate seven-file source manifest has SHA-256 +`92cde32454dfb23f0421ce4e2d92ffe3c054281138cfe2d8a2ebe8c734960da3`; +TRX does not embed a commit. Real disposal joins and both exact owned provider +containers and their network are independently absent. + +Exploratory red Facts exposed pinned v2 OTP-form differences and incorrect test +expectations for historical status/callback behavior. A redundant second failed +password stimulus also triggered the real provider's quick-login protection. +The fixture preserves the exact OTP credential selector and closed `invalid_scope` +error, removes that redundant stimulus and checks attack-detection state. No +provider security policy is weakened. The final-source Fact is rerun after those +harness corrections and scoped formatting, rather than treating an earlier +partially reached assertion as complete proof. Eighteen adjacent provider cases +and seven corpus/Docker-trait guards pass with zero skips. Integration and +Architecture builds have zero warnings/errors; scoped whitespace/style verification +passes for all six C# files. Only newline formatting and the two refresh-presence +proof guards follow the eighteen-case receipt; the final historical Fact runs +again against those exact bytes. +Independent correction reviews and full hosted qualification remain pending. + +The new historical journey source also receives one literal CI failure-location +code, `realm_warm_qualification`, with the existing bounded line projection. +No raw stack, path, message, token or provider value is exported. The existing +planted trace control fails without the mapping, then all forty-three offline +launcher controls pass with it. Source inventory includes the exact new partial +file; no diagnostic code is inferred from arbitrary filenames. + +Measured weights replace the renamed selector and cover the nine completed +Step 2 method groups. Two previously unknown historical-baseline methods gain +actual hosted durations from this Step 2 run's independently verified ordinary-1 +and ordinary-4 receipts: 98,022 and 102,868 milliseconds. Local row sums retain +the existing advisory scaling; hosted rows are not scaled. These weights are +assignment hints, not wall-clock upper bounds or proof of final hosted fit. +The offline shard/result controls pass sixty and nineteen cases respectively. +The journey adds a 91,318-millisecond advisory weight from its actual TRX row; +the plan now has 1,382 weights. Twenty explicit bounded VSTest discovery calls +complete in 20.356 seconds with all owned process groups/readers joined. Actual +ID/FullyQualifiedName metadata preserves all 5,919 earlier case identities and +adds only the new journey: 5,920 total, 3,350 non-Docker, 2,539 ordinary and 31 +native. Every changed selector belongs to that manifest; the retired selector is +absent. Source, plan, parsers and four Release assembly hashes stay frozen. + +On that same complete manifest, the revised plan moves 1,055 methods/2,289 cases +in layout A and 932 methods/2,018 cases in B relative to the Step 2 plan. Both +layouts have complete unions and materially different co-memberships. Maximum +filter/argv bytes are 15,491/16,137 in A and 26,048/26,695 in B, below the unchanged +32,768/65,536 limits. Unknown method weights fall from 53 to 43; those remaining +use the existing default and are not represented as measured. The manifest digest +is `c79e7e37f5304b3e27d966f0e628b80d8746872aa911933a52383c434ac4bc8e`; +the finite validation-summary SHA-256 is +`9f9f400132c21ff9ffd291a2bd4b606bd69f45199c79edfea347f4720210b4b1`. +This is complete metadata/assignment validation, not final-source execution. +The execution VM count of twenty, seven required names and whole-job ceilings +remain unchanged; both final hosted layouts still require execution. + +[Run `39699380813`](https://github.com/HodeTech/LearnStack/actions/runs/39699380813) +finishes successfully at Step 2 head `f714a5af`: all twenty-seven jobs and seven +required contexts pass. Checkout `d55ae6fc37b794e482c42ebbdd49d3e59a9c3f0a` +has the recorded source tree. The hosted fresh demo independently completes all +nine pages and twenty-seven hash-bound report pairs; it does not erase the failed +local historical-input experiment. Native proof passes all thirty-one cases, and +base passes 2,917 cases, with zero skips. Independent revalidation of all twenty +producer archives verifies API digests, current-attempt ownership and exact case +unions: backend 3,350 plus integration 2,569 (2,538 ordinary and 31 native), all +5,919 passing with no skips. Both aggregate receipts match recomputation using +that source's validators. The verification-summary SHA-256 is +`60cf4e7af91b76a512f717b6c7df875e996c7804edcc1197a29a92ab9a637012`. +The failed `52c73e60` assignment remains failed; its reproduced mapper +classification defect is fixed and independently qualified at this later source. +Final Step 3 source and its revised plan still require ADR-0063's materially +different complete assignments at the same frozen source, rather than borrowed +receipts. + +##### Step 3 first independent review round + +Implementation is committed at `ca3560df`. Two fresh independent reviewers inspect +the complete thirteen-file `f714a5af..ca3560df` change and adjacent authorities: +`gpt-6-astra` at `xhigh` for security and nonvacuous provider proof, and +`gpt-6.1-sol` at `high` for governance, assignment/evidence meaning and reliability. +Both approve without a verified Blocker, Major or Minor finding. Neither changes +repository files or executes provider, Docker or .NET/build/format commands. + +The security reviewer reads the complete historical journey and independently +checks the final TRX and seven source hashes. It verifies usable password/MFA +controls, strict web/API versus closed historical-console validation, nonce and +access-token hash binding, stored self-service/protected-field readback, the +positively nonempty offline credential and the exact preservation/cleanup claims. +It distinguishes the observed offline result from universal revocation and keeps +the failed historical demo and final hosted obligations visible. + +The governance reviewer independently verifies the eighteen adjacent and seven +corpus outcomes, all twelve timing upserts/one retirement/five sources and their +actual selector bindings. It reparses all twenty retained discovery diagnostics +to the exact 5,920-case manifest, preserving every prior case identity plus one +new case. Both complete assignment unions, distinct co-memberships, movement and +filter bounds recompute. All forty-three offline launcher controls pass, including +the literal finite failure-location projection. Accepted ADR bodies and catalogue +statuses/counts remain unchanged. All review commands join. A different fresh +second review pair and final-source complete hosted assignments remain required. + +##### Independent historical demo repeat + +One explicit independent repeat of the same historical-input experiment succeeds +without runtime, budget, capture or threshold changes. It freezes the same +`f714a5af` production archive and identical transformed historical/Hub inputs. +The private proof commit is `d7e981ab102b7ae4502789773f422ddba2b61a48`, tree +`304651aa11d636cc456b8bfd40ebb2142a429367`; its only source delta is the owned +Compose import bind, SHA-256 +`3a4773ed123eb159fafe2aae88a7e202485504fd93772c55819935a2769c755a`. +Production-source hashes remain equal and the private proof source stays clean. + +Actual `make demo DEMO_MODE=ci` exits zero in 662.279 seconds within the unchanged +1,200-second whole-run budget. Nine navigations, twenty-four visibility controls +and all twenty-seven JSON/HTML report pairs complete. All reports have no runtime +error/warning and accessibility score 1.0; all nine screenshots are inspected for +readability/clipping. All 134 observed API completions return 200, and both TLS +refusal controls plus the timeout refusal control pass. Independent reads observe +the original two users/eleven edges, then four declared protected identities, +eight retained edges and exactly three appended profile definitions. The unchanged +demo entry exposes no reconciliation mutation count; none is inferred. + +Natural cleanup takes 10.711 seconds. All seven proactively captured owned +container IDs and the network independently return not-found; the selected +Compose project is empty, private environment/lock files are removed and all +owned processes/readers join. No forced or fallback cleanup runs. The final +private receipt SHA-256 is +`64c647657a3a3afe671996d7da957c78e81cca4040fbd820ae80d463ead189d1`; +the native public receipt SHA-256 is +`ae53906f2a476abc4c3f208a2dd0daf646e838ef3ab2f4a8bf83b13b6f336cae`. +This completes the independently recorded historical entry proof. It neither +explains nor erases the first red experiment and does not replace untouched +final-source hosted qualification. + +##### Step 3 second independent review round + +Two different fresh reviewers independently inspect `f714a5af..ca3560df` and +one-hop dependencies: `gpt-6.1-sol` at `xhigh` for security, runtime correctness +and nonvacuous provider proof; `gpt-6-astra` at `high` for governance, CI/evidence +meaning and reliability. Both approve without a verified Blocker, Major or Minor +finding. Both read the entire new historical journey and all thirteen changed +files. Their review approval does not substitute for the separately executed +historical demo or final-source hosted checks. + +Each independently verifies the final historical TRX, its exact duration and all +seven committed source hashes. The security reviewer checks actual credential/ +MFA controls, nonce/access-hash binding, strict web/API and closed historical +console boundaries, physical application-role ReadOnly observations and stored +POST/protected-field assertions. The governance reviewer reparses all twenty +discovery diagnostics, verifies every prior identity plus the one new journey, +and recomputes both complete assignments, limits and local/hosted timing weights. +Both pass all 122 offline launcher/assignment/result controls; the governance +reviewer also checks that removing the diagnostic mapping breaks its planted +control. No reviewer executes provider, Docker or .NET/build/format commands; +all review commands join. Accepted ADR bodies and catalogue counts/statuses stay +unchanged. All three correction steps now complete their local implementation +and two independent review rounds. Full final-source A/B hosted qualification is +the remaining completion gate; no merge or P02b-7 work is authorized by this +record. + +##### Final hosted qualification + +[Run `39705264083`](https://github.com/HodeTech/LearnStack/actions/runs/39705264083) +freezes Step 3 head `ca3560df775ac86304fdfefbc0c3bf81cc118cef`. Checkout +`0d65aa34cf54d3424f1d7870c5a042a971e0b374` has that exact second parent and the +same tree, `e124af40d71057ba73657a925c32c67413956409`. No code, plan, deadline or +success witness changes between assignments. + +Attempt 1, layout A, passes all twenty-seven jobs and seven required contexts. +Its public demo archive is downloaded and independently verified before rerun: +all twenty-seven report pairs, nine screenshots, nine navigations and twenty-four +visibility controls pass. Its private verification-summary SHA-256 is +`aa0f3c673e83ca7bd5ffc10de14f36253c8251cd1ab09bc92a82c89fb2cb61a5`. +After the full rerun starts, prior artifact API endpoints return not-found; no +cause is inferred. Initial job-log capture is separately blocked by the installed +CLI's terminal-escape output guard, not an observed HTTP refusal. Using its +documented flag only into private pipes/files later recovers both original +aggregate log receipts. They report 3,350 backend and 2,570 integration cases at +the exact source/attempt; their private canonical receipt SHA-256 values are +`1242916895281b40c7e21d8d50f18a382904fa95a244fda953a6ab1a6a0e7a19` +and `c8602bea4b1c508a06ee1dcc65f4ae308749247f3e74a1091181d545efee688b`. +The original successful jobs API response and downloaded public proof also remain +retained, but complete independent producer-archive revalidation is not claimed +for attempt 1. The later A assignment is explicitly for complete retained +qualification evidence, not a failed-test retry or permission to combine siblings. + +Attempt 2, layout B, passes all twenty-seven jobs and seven required contexts. +Before any further rerun, all twenty producer archives and both aggregate archives +are downloaded, API-digest checked and independently revalidated with the frozen +source's pure validators. Exact current-attempt job/source identities, build/ +execution/upload gates, cleanup, toolchains, runner observations and complete +case/TRX unions pass. Backend contains 3,350 cases (2,917 base and 433 Architecture); +integration contains 2,570 (2,539 ordinary and 31 native). All 5,920 cases pass, +with zero skips. Both aggregate payloads match independent recomputation. +The longest observed producer whole-job wall time is 911 seconds, within the +unchanged 1,200-second ceiling; queue delay is separate and not hidden in that +measurement. Observed SDK/console are `10.0.402` and +`18.7.0-release-26505-111`, with their actual binary hashes retained. + +The B verification-summary SHA-256 is +`dfb122abc2bab511b8be916baa6566385a408f4eeb62d84f001334265f7554a1`. +The original capture checks both aggregate API digests, but does not retain the +integration aggregate's raw API envelope. Its ZIP, digest, payload comparison and +the verifier source remain retained; the latter has SHA-256 +`1e7d235d74aa63ecf6fdb715a7f68be6f965d9f118717431f6daad8cd6dde5f6`. +A subsequent independent reviewer can replay all twenty cached producer API/ +archive bindings and both complete unions/payloads, but cannot independently +replay that one aggregate API binding from a cached raw envelope. This limit is +distinct from the original capture's checked assertion. Later capture retains +both raw aggregate API envelopes before another transition. +Its plan digest is +`aec25a0597f0944dd4168fc5caf36faef983eb96fc0f053b6eb74befefd2e4be`, +manifest digest +`c79e7e37f5304b3e27d966f0e628b80d8746872aa911933a52383c434ac4bc8e`, +and assignment digest +`fe4cde10ee32f0ef85df6abbfa7e3137cc6a783a1791215abfa182e267d9b244`. +The separate B public-demo verification-summary SHA-256 is +`713a5dd039532fd4c847975c864ed7e466ef37795c467421f7174e3f566b4344`: +all twenty-seven JSON/HTML pairs and nine PNGs match their native manifest, +the full report contract passes, all 134 API completions return 200 and all +cleanup flags pass. This hosted clean-bootstrap evidence remains distinct from +the private historical-import experiment. + +The complete third attempt, layout A, starts only after B's archives and full +revalidation are retained. Its source and plan stay frozen. It finishes **red**: +twenty-four jobs pass, ordinary-7 and frontend fail independently, and integration +correctly refuses the failed producer. No earlier green assignment waives it. +The public demo producer separately passes all twenty-seven report pairs and +owned cleanup; its independent verification-summary SHA-256 is +`6afe2a1b664de4c59013f2a0a85077af3326634a151bada78734cc21bd9c09cf`. + +Ordinary-7 retains one failed known-failure variant of the actual Outcome ACK/ +held-cleanup test, 62.8366378 seconds, with finite source locations 164/179/183 in +`BackgroundJobPositiveSdkTests.NativeSettlement.cs`. The owner reports +`owned_completion_missing`, workload `tests_failed` and forced cleanup. Source +line 164 combines an awaited count query and the exact-two assertion; the retained +TRX/message cannot distinguish a query fault from a count mismatch, and no actual +count is recorded. A simple ledger visibility-delay explanation is not supported +by the transactional ordering. No wait, assertion or deadline is weakened. + +Frontend fails at the first development-server readiness boundary after the +production ingress/optimizer controls. No probe response completes; all existing +closed compilation/configuration flags are false. Current-child progress and the +probe-error kind are absent, so preparation delay, health-route delay, connection +refusal and TLS failure cannot be separated. The subsequent failed-fixture cleanup +command is not reached. Test-only finite diagnostics and exercised transport +controls are the justified next correction; neither failure has a proven +functional root cause from this receipt. Complete corrected-source qualification +remains required. + +##### CI failure diagnosis and exercised transport + +The settlement correction separates the original count read from its assertion +and records a bounded, case-bound observation before cleanup. A separate +application-role query observes ledger stages, counters and closed state; its +later snapshot is never represented as the failed assertion's original count. +Unknown/unavailable observations stay explicit. A bare rethrow preserves the +original failure. Only the three exact settlement cases and actual xUnit +`StdOutMsgs` can project these finite facts; raw output, identities, error text +and SQL are excluded. No assertion, wait or cleanup deadline changes. + +All forty-six offline launcher controls pass. A private copied-source experiment +changes only the last known-failure assertion's expected count to an impossible +negative value. The real pinned adapter transports that failed case's output: +the original count is two, the later snapshot is two (normal/finalize one each), +and the original assertion/stack remain intact. Two sibling cases pass and the +intended case fails, with zero skips. Sanitization removes output and preserves +the failed outcome. Initial immediate reaper absence is not proven; that refusal +is retained separately from later exact-ID proof that both owned containers +disappear naturally. Private compile-harness setup refusals precede execution; +no repository rule is disabled. + +The untouched source is rebuilt and all three real cases pass, with zero skips; +their command takes 62.599 seconds including runner/fixture work. All owned +processes and containers finish. Release builds report zero warnings/errors and +scoped format verification passes. The combined private receipt SHA-256 is +`0074b9dd2bab6371f992163cd76f6f4e4b3920999092cd0b3e58a80969286489`; +root independently checks all nine source hashes and six retained receipt hashes. +Rebuilt binary hashes are recorded per build; byte-identical production binaries +are not claimed. + +Fresh complete metadata discovery executes twenty bounded commands in 18.086 +seconds: the same 5,920 exact cases, manifest, plan and both assignments. Its +summary SHA-256 is +`11ac0e91f607bf3b70cd41e20e2f2da3e4c472388e60937b16ea1e485b8d11b8`. +These receipts qualify diagnostics and preserve the historical A3 failure; they +do not establish that failure's missing root cause. + +Frontend's first instrumented local run remains red: its development child is +running in preparation, with no observed bind and 196 refused probes/zero +responses in 20.058 seconds. A second, separately instrumented run observes +Next 15.5.27's exact informational npm version fetch still pending after 19.533 +seconds. The unchanged readiness boundary fails at 20.052 seconds. Production, +stock and optimizer-mutant listeners had readied in 1.068/0.526/0.642 seconds. +The pinned `HotReloaderWebpack.start()` awaits `getVersionInfo()` before compiler +startup; that exact global fetch has no timeout. This establishes the pending +dependency in the local reproduction, without guessing a DNS/remote/network +cause or claiming to recover the earlier CI child's missing observation. +The second private receipt SHA-256 is +`943f5ce5d18631e2c8151b43c06079172c679fb23643a674f38f9f1b81b7118f`. +Both failed runs retain their outcomes and complete owned cleanup. + +The correction adds an owned two-second abort only to that exact, one-argument +informational fetch inside the disposable development launcher. Next's existing +failure/unknown-staleness path handles the actual rejection. No synthetic HTTP +response or competing completion race is introduced; a delegate ignoring abort +remains pending until its real settlement. Other URLs, URL objects and calls +with options/explicit second arguments pass through unchanged. Any remaining +timer is cleared on actual settlement; notifications cannot replace the original +response/error. +Fetch resolves at response headers: the two-second budget does not extend through +Next's later JSON body consumption. The existing readiness refusal still bounds +that preparation check; no universal body/network I/O deadline is claimed. +The shipped launcher, workflow, plan and all ingress/HMR readiness, probe, +cleanup and success conditions remain unchanged. + +Twenty-three focused controls pass, including actual signal expiry, ignored-abort +settlement, timer cleanup, private-error containment, current-child attribution +and separation from upgrade messages. The single corrected actual native run +passes in 21.828 seconds. Both development children observe a real timeout at +2.004 seconds, then genuine healthy owned binds at 4.298/3.390 seconds; original +TLS, GET/HEAD, stock-bypass, optimizer mutant, DEBUG, query, HMR and both shutdown +signals pass. Its private receipt SHA-256 is +`00743393b8da99607eae39693803a4b51d6415f56f2ab958987bc8295fbb3b4e`. +Root independently matches five proof-source hashes and the observed Next package, +hot-reloader, lockfile and build-ID hashes. This fixes the demonstrated local +informational-lookup stall; it does not invent the earlier CI child's missing +internal trace. Full correction reviews and hosted qualification remain required. + +Final frontend validation passes workspace lint/typecheck, all 1,840 guarded +cases in two packages with zero skips/todos, and all nineteen cleanup controls. +An initial typecheck rejects two unchecked mock-call tuple accesses in the new +controls; explicit call-count/tuple guards correct only that test source. The +immutable native receipt is retained, and all four harness/helper/declaration +files still match it. The final guard binds all five current sources; its +private receipt SHA-256 is +`9422382afa7da79557c63fa799e76db2c23667b34cc8a554d12f600df2a0f29e`. +Root independently matches those five hashes. The unchanged, attested production +build is exercised by the native proof; no new production build is claimed. + +Root passes seven corpus/Docker-trait controls with zero skips; all testhost +processes finish. Changed-document validation checks 1,415 real relative links/ +fragments with no broken target, new analysis reference or overlong added prose. +The diagnostic correction still needs its two fresh independent review rounds +and complete corrected-source hosted qualification before closeout. + +##### First independent CI-correction review + +Two fresh reviewers inspect all seventeen files in `61e47ff3..87ecc114` and +their relevant dependencies: `gpt-6-astra` at `xhigh` and `gpt-6.1-sol` at +`high`. Both approve without a verified actionable finding. They independently +check application-role snapshot attribution, original-count separation, closed +parser output, actual failure preservation, exact fetch targeting/settlement, +current-child admission and unchanged success/cleanup conditions. + +The security reviewer passes all forty-six offline controls and independently +checks nine source hashes, six receipt hashes, the real mutant's original +assertion/stack and sanitized failed outcome. The frontend reviewer independently +passes all twenty-three focused cases through the actual runner/report guard, +with zero skips/todos, and verifies native/final source bindings and installed +provider/build hashes. An initial unsupported runner invocation refuses before +test execution; the corrected repository runner completes. Both inspect the +recorded evidence limits and retain the historical A3 failure. No provider, +native or full frontend experiment is repeated. All subprocesses finish and the +tracked tree remains clean. The second fresh review round remains required. + +##### Second independent CI-correction review + +Two different fresh reviewers inspect all seventeen files in +`61e47ff3..8ae35ecf` and their relevant dependencies: `gpt-6.1-sol` at `xhigh` +and `gpt-6-astra` at `high`. Both approve without a verified actionable finding. +The first independently passes the three added Python controls, checks raw +VSTest events alongside original/sanitized TRX and verifies nine source, six +top-level and seven mutant-subreceipt hashes. The second independently passes +all twenty-three focused frontend cases with the actual report guard and zero +skips/todos. Their source/receipt checks confirm original-count separation, +application-role observation, strict parser output, real fetch settlement, +unchanged readiness/cleanup admission, provider/build hashes and unchanged plan. + +The explicit limit above distinguishes fetch/header settlement from later body +consumption; it adds no runtime change. Both reviewers preserve the historical +A3 failure and pending corrected-source hosted qualification. No provider, +native, .NET or broad frontend suite is repeated. All subprocesses finish and +the tracked tree stays clean. Both fresh correction review rounds are complete; +complete corrected-source hosted qualification is the remaining gate. + +##### Reviewed-source hosted failure and identity attribution + +[Run `39716534536`](https://github.com/HodeTech/LearnStack/actions/runs/39716534536), +attempt 1/layout A, freezes reviewed head +`7b0fd1b6f718d49c7c5daad318685295b48d90cc`. All twenty-seven jobs finish: +twenty-five pass; ordinary-7 fails and integration refuses that producer. The +frontend job now passes. No layout B starts and no earlier green receipt waives +this failed source. All twenty producer archives and the successful backend +aggregate archive are retained and API-digest checked before another transition. +The private failed-run capture summary has SHA-256 +`0c4c7c37ab39af1ed37afa6494a57e68efc63876c4fdbc9d76ba62ed7a6a2394`; +it records a failed run, not complete qualification. + +The known-failure Outcome ACK/held-cleanup case fails in 20.6750301 seconds at +source line 221: the final process-wide `LeaseLossRenewalRefused == 0` assertion. +Its earlier count, generation, outcome and provider assertions pass. Runtime +stop/completion and the preceding zero-execution/elapsed-loss assertions also +pass. This location is distinct from the earlier count boundary. The retained +artifact has SHA-256 +`6f37596cf9acd045fe6993f67adf8c30e6513617d74648566ac8ff2742479c70`. +The diagnostic catch precedes these post-cleanup assertions, so no marker records +the counter value, execution identity or triggering renewal branch. None is +inferred from the stack location alone. + +Independent source inspection identifies a legal candidate interleaving: the +later Finalize execution holds the job row, renewal skips its lock and observes +no renewed row before managed commit acknowledgement. Conservative refusal can +then increment the cumulative counter while a commit already admitted completes. +This is a source-supported counterexample to treating the cumulative counter as +an observation of only the held Outcome identity; it is not a recovered CI trace. +The existing refusal/commit policy remains unchanged. Exact-identity attribution +and a controlled real-store interleaving are required before correcting the +proof; waits and deadlines are not increased. + +Public demo independently passes on the same source. Its immutable artifact +`12400165434`, SHA-256 +`c6c5ab29fb83ca43e187a95d00758cde9eab7db690fbec6ffd539aab9a7fde99`, +is retained before any rerun. All twenty-seven JSON/HTML pairs, nine PNGs, nine +navigations and twenty-four visibility checks pass; all 134 API completions +return 200, both TLS and the timeout refusals pass, and all cleanup flags pass. +Natural cleanup takes 10.732 seconds. Independent verification-summary SHA-256 is +`a0e3688c3ab02d6403d145845485b43499dc8d6f9bbde4ac5ec0866832cd1ef2`. +This successful producer does not change the run's failed conclusion. + +##### Exact lease-loss attribution proof + +The corrected stock proof keeps all three case identities, its held-cleanup +barrier, exact counts, generation, provider observations and original deadlines. +It checks the captured Outcome execution's sticky first cause after actual +cleanup instead of attributing later process totals to that identity. The later +Finalize control is captured independently. Aggregate zero checks remain while +only the original held identity exists. Post-cleanup and cleanup-first failures +now produce the same bounded diagnostics; cleanup cannot replace an earlier +exception. Closed per-identity causes and cumulative counts remain observations, +never admission or completion evidence. + +A separate explicit-owner subphase runs inside the existing known-failure case. +It uses real publication, provider, Outcome, Finalize and PostgreSQL control +owners; it does not claim a stock Hangfire handoff. A test-only proxy holds the +real Finalize COMMIT request only after that exact gate admits commit. An actual +`SKIP LOCKED` read confirms its row remains locked. The production renewal lane +then refuses the omitted identity. A test-owned cancellation callback holds +propagation while the already-admitted real COMMIT request and ACK complete. +All barriers release before actual joins. No control field, counter, completion +or production policy is manufactured or changed. + +The initial experiment uses a COMMIT ordinal and refuses at the required +`CommitStarted` precondition: the held transaction is preparatory. It is not +accepted as the intended negative; both owned containers and all processes +finish. The corrected barrier uses the exact gate predicate and measures the +actual before/after COMMIT count rather than guessing an ordinal. + +The source-attested one-substitution experiment restores the old global-zero +assertion only at the final explicit-owner boundary. Two siblings pass and that +case fails exactly at `later_post_cleanup`, with zero skips. The real pinned +adapter transports original cause `none`, Finalize cause `renewal_refused`, +cumulative renewal loss one, elapsed loss zero and zero active executions. +Actual attempts are two (one normal, one Finalize), generation advances once and +one finalized row exists. The original assertion survives; sanitization removes +output and preserves the failed outcome. Both owned containers are absent. +The private mutant receipt has SHA-256 +`ac261c52d4a5b261cb5928b397b8993e4cb17b24432dd491544f5d3468e7c906`. +Root independently checks its finite facts and receipt hash. This proves the +attribution counterexample, without asserting the missing CI interleaving. + +Untouched-source Release rebuilds report zero warnings/errors, scoped format +verification passes and all forty-seven offline launcher controls pass. The +single clean real run passes all three cases with zero skips: false 16.184 +seconds, known failure 19.449 seconds including the separate counterexample, +and retained recovery 21.383 seconds. Command wall time is 63.415 seconds. +Both owned containers and the process group are absent; all commands join. +The combined private receipt has SHA-256 +`10658b0cf90dea34b533b80941514f243085e4eac0e48d1a71b538570fe3b735`. +Root independently verifies seven current source hashes, nineteen retained +artifact hashes and both clean TRX hashes. Rebuilt production binary identity +is recorded per build; byte-identical binaries are not claimed. + +Fresh complete metadata discovery executes twenty bounded commands in 19.077 +seconds. All 5,920 exact identities, the plan, manifest and both assignment +digests remain unchanged. The private summary has SHA-256 +`f64f219670a3d12a8efa99b81001c05740aec3e6ea4ba63f96d30cd99c0bbdd0`. +Seven corpus/Docker-trait controls pass with zero skips in 9.465 seconds and +their process group is absent. Independent review and complete corrected-source +hosted qualification remain required; no earlier red receipt is waived. + +##### First independent attribution review + +Two fresh reviewers inspect all five files in `7b0fd1b6..9adba275` and their +ownership, renewal, persistence and diagnostic dependencies: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both request changes for the same verified +Major: the new explicit-owner failure cleanup releases barriers but can call +`JoinAsync` before issued business/admission/external tasks actually return. +An unfinished task then makes cleanup fault sticky and retains the invocation; +preserving the first exception does not prove a completed join. The successful +path's retained receipt does not qualify this early-failure path. + +Both otherwise confirm the attribution boundary, real gate-bound COMMIT/ACK, +unchanged default proxy behavior, finite diagnostic privacy and honest evidence +limits. The first passes all forty-seven offline controls in 17.125 seconds and +independently verifies seven source and nineteen artifact hashes. The second +independently verifies changed executable sources and four raw/sanitized TRX +hashes. Neither reruns provider/.NET/Docker work, and all commands join. +The pre-existing stock pre-ACK guards remain setup requirements; this review +does not claim an earlier loss is impossible or change conservative refusal. + +The verified correction retains each actually issued admission, external, +business and disposition flight before its synchronous prefix. Failure cleanup +closes future issuance, requests owned cancellation and releases its barriers, +then independently awaits actual flights and their cleanup results before +positive execution/private joins. An already-started private completion task is +retained and reused. One failed step cannot skip independent stop/join steps, +and an unfinished or cleanup-faulted operation never supplies a positive witness. + +The original failure observation remains separate from a closed post-cleanup +witness. Only the exact known-failure case and stdout category can carry that +optional witness; finite states/counts, malformed/ambiguous/private-output +refusals and sanitizer behavior remain enforced. It grants no completion or +admission authority and cannot turn a failed case into success. + +A single copied-source substitution plants an impossible expected renewal count +after the cancellation callback enters, while the real business task is pending +and COMMIT remains held. The actual adapter reports the intended `later_refusal` +failure with one active execution. Its separate cleanup witness records both +admissions, external/business flights, callback, both identities, private work, +control and generation joined; unissued disposition stays `not_issued`. +Executions, running work and retained work are zero. Two siblings pass, the +intended case fails and zero cases skip. The original assertion survives, +sanitized TRX remains failed and both owned containers/process group are absent +without forced cleanup. The private mutant receipt has SHA-256 +`99cff1933d6de69c190542b2141e04799f7406f45b5de7c6ac3b62399f166889`. +Root independently verifies the pre/post-cleanup facts and seven source hashes. + +Corrected-source Release builds report zero warnings/errors; scoped format +verification and all forty-nine offline controls pass. The single clean real +run passes three cases with zero skips: false 16.070 seconds, known failure +18.092 seconds and recovery 21.263 seconds; command wall time is 61.189 seconds. +Both owned containers and the process group are naturally absent and all +commands join. Combined private receipt SHA-256 is +`bdbf89a86f718b30c6d449dc5f127efa467c961e86beb9bb697c66460d3968c6`. +Root independently verifies seven current source hashes, nineteen artifact +hashes and both clean TRX hashes. The earlier attribution and rejected ordinal +experiments remain source-bound historical evidence, not new-source reruns. + +Twenty fresh metadata commands complete in 16.080 seconds, preserving every +one of the 5,920 identities, the plan/manifest and both complete assignments. +Private summary SHA-256 is +`67d477db5a547e837ac7ea3e908b80f89463884cf7bef3b1670f4ef68c8f41c0`. +Seven corpus/Docker-trait controls pass with zero skips in 8.868 seconds; +their process group is absent. The second fresh independent review round and +corrected-source hosted qualification remain required. + +##### Second independent attribution review and source freeze + +Two different fresh reviewers inspect all six files in +`7b0fd1b6..c9abc978` and their dependencies: `gpt-6.1-sol` at `xhigh` for +ownership/security and `gpt-6-astra` at `high` for evidence/governance. Both +approve without a verified Blocker, Major or Minor. Both independently confirm +the first round's cleanup correction: actual flights precede positive joins, +private completion is reused, independent cleanup continues and first failure +survives. The early negative verifies issued business and held cancellation +cleanup; it does not infer cleanup from process exit. + +The first passes all forty-nine offline controls in 16.588 seconds. Both inspect +the actual driver, adapter output, four raw/sanitized TRX hashes and nineteen +artifact hashes, preserving the intended failure and clean three-case outcome. +The second also approves the unpublished PR description and its explicit +qualification boundary. Neither repeats .NET/provider/Docker/native experiments. +All commands join. One initial status probe reports an existing untracked +directory entry; no contents are opened or enumerated, and later status probes +exclude untracked paths. + +The commit hook normalizes only line 461's leading indentation from sixteen +spaces to twelve. Reversing the exact retained mutant substitution reconstructs +the tested source, SHA-256 +`4538ae656ffded55fe4c39d2918a143a882276958403ea6a4dd8be0db7da68df`. +Both reviewers independently verify the one-line whitespace mapping to committed +SHA-256 `1cefcb2f5c5f6e996cd3f4c9ada7164b2ca487b2d8225361ba62b52ae810c1cd`; +the other six attested files match byte-for-byte. Seven-file byte identity is +not claimed after the hook. The separate private binding receipt has SHA-256 +`e3b73f02e9b572ab602a5875360be7e48450005b23c4195d85695871d2d6b0cc`. +It records a formatting bridge, not a new runtime or binary-identity claim. + +Local implementation, validation and both fresh independent attribution review +rounds are complete. [PR #34](https://github.com/HodeTech/LearnStack/pull/34) +records the frozen head's exact run/attempt identities, complete A/B assignments, +retained producer/aggregate/public artifacts and current seven-check result. +Complete current-source qualification is required before readiness; a successful +sibling or earlier revision supplies no waiver. Merge and P02b-7 remain separate. + + +##### Reviewed-source recurrence failure and evidence boundary + +[Run `39723329277`](https://github.com/HodeTech/LearnStack/actions/runs/39723329277), +attempt 1/layout A, freezes reviewed head +`4e06ffa1359bb2701e7a097a1fb1b7f9244ad9d1`, tree +`565a62db2958306fc29d198b2672e531b5318fb1`. All twenty-seven jobs finish: +twenty-five pass; ordinary-8 fails and integration refuses that producer. No +layout B starts. All twenty producer archives and the successful backend +aggregate archive are retained with their raw API inventory and verified +digests. The failed-run capture summary has SHA-256 +`46a0af0a9af9b64593ef834a8474d5a8fa84887c6d0c1fd9051dd848f8b669e3`. +This capture records failure, not complete qualification. + +The held actual native recurrence callback case fails in 32.5851077 seconds. +Its artifact, `12402495557`, has SHA-256 +`c19332a22de1977c1368e4262430f29bd677ac52d50b40ea81a3d333d1c79be9`. +The retained top-level exception class is `timeout`; no mapped source location +is available. The owner reports `owned_completion_missing`, workload +`tests_failed` and forced cleanup. Multiple independent thirty-second waits +exist; the test's cleanup can also replace an earlier exception. Duration alone +identifies none of these boundaries. + +The actual job log contains no underlying adapter stack or error message. +Ordinary console output is discarded, raw execution diagnostics are deleted and +TRX errors are sanitized. Neither native recurrence source file has a finite +location mapping. Empty exported locations therefore do not establish an empty +original stack. Two independent read-only inspections find no source-proven +production defect; this run's exact timeout boundary is unrecoverable from its +retained evidence. The next correction preserves the first exception, maps both +source files and records finite first-failure and later cleanup facts separately. +It changes no production behavior, assertion, wait or admission rule. + +Public demo independently passes on this same source. Immutable artifact +`12403135471`, SHA-256 +`3d31ba7b57bb3de2c19a868fed71eb7b42fde79fde4ca794ec63b925e2bccd55`, +is retained with its raw API binding. All twenty-seven report pairs, nine PNGs, +nine navigations and twenty-four visibility checks pass; all 134 API completions +return 200. Toolchain, TLS/timeout controls and natural cleanup pass; cleanup +takes 11.783 seconds. Independent verification-summary SHA-256 is +`5335e9a6dcde02f51cda4c103508afdc32e07e75018974d4f1db801847957a72`. +This successful sibling supplies no waiver for the failed recurrence case. + + +##### Recurrence failure transport and first-exception proof + +The correction retains the existing case identity, assertions and timeouts. +Its first body, explicit cleanup or post-cleanup exception is preserved through +`ExceptionDispatchInfo`. Later cleanup steps are attempted independently. An +early body failure also requests the two actual source disposals; only their +positive completion can establish cleanup. No production code changes. + +One exact integration case may project its two test-owned `StdOutMsgs` markers. +Finite boundary, task/thread, owner-count and source-state fields distinguish +the first failure from the later cleanup observation. The sibling task arrays +retain their production-published order. Neither diagnostic proves completion +or changes a failed outcome. Unknown or malformed data is refused; identities, +raw errors, SQL and arbitrary text are excluded. Both recurrence source files +now have finite source-location mappings. These bounds constrain output; the +owner snapshots are not represented as lock-free or universally nonblocking. + +A private one-substitution control changes only the held callback assertion's +expected count from one to an impossible negative value. The actual pinned +adapter transports the intended failed case at `held_assertions`: callback one, +thread alive, return pending and both sources undisposed. Its original assertion +and stack survive. After callback release, the actual thread returns, all three +pools, three control loops and fixed sibling/control/runtime tasks complete, +and both source disposals complete without unconfirmed cleanup. The failed +outcome remains failed after output sanitization; no process exit supplies the +internal cleanup evidence. + +A separate two-substitution control adds an awaited cleanup failure after the +actual stop completes. The exact case's output proves this second fault was +reached. The first assertion and its stack still survive, while subsequent +completion, thread and source cleanup continue successfully. An initial private +build refuses a literal throw under CA2219; the corrected awaited failure keeps +that rule enabled. Offline proof validators initially refuse duplicate summary +output and replay-file bindings. Their refusals remain recorded; validation is +corrected against the same unchanged actual execution and exact case output, +without rerunning the test to replace its result. + +Both fault experiments have one intended failure and zero skips. The untouched +source is then rebuilt with zero warnings/errors; scoped format verification +passes. The original case passes once with zero skips in 2.7962847 test seconds, +9.522 command seconds. Each experiment's process group and two exact owned +containers disappear naturally. The combined private receipt has SHA-256 +`f37b584d22c72191a54465b4dd2e1649ea2d9db641a9a4d5f0139ec1885926b4`. +Root independently verifies seven source hashes and sixty-one retained artifact +hashes, including raw protocol, original/sanitized TRX and actual owner cleanup. +These local controls qualify the diagnostic correction; they cannot recover the +earlier hosted timeout's missing boundary. + +All fifty-three offline launcher controls pass. Twenty fresh metadata commands +complete in 22.886 seconds, retaining all 5,920 exact cases and unchanged plan, +manifest and A/B assignment digests. Their private summary has SHA-256 +`127e95b0d206e067c89d4cbc0061e3c1b706938c62c50569880161c7925e71c9`. +Seven corpus/Docker-trait controls pass with zero skips in 9.863 seconds; their +process group is absent. Changed-document validation finds no broken relative +link or fragment, added analysis reference or overlong prose. +Fresh independent correction reviews and complete current-source hosted +qualification remain required before readiness. + + +##### First independent recurrence diagnostic review + +Two fresh reviewers inspect all five files in `4e06ffa1..55dfeaea` and their +relevant dependencies: `gpt-6-astra` at `xhigh` for ownership/security and +`gpt-6.1-sol` at `high` for export/evidence/governance. Both approve without a +verified Blocker, Major or Minor. Both confirm first-fault preservation, +independent cleanup, unchanged assertions/timeouts, actual thread/owner/source +completion, ordered sibling observations and failure-only finite transport. +Neither treats a disposal request, elapsed wait or process exit as cleanup. + +Both independently verify seven current source hashes and all sixty-one retained +artifact hashes, reconstruct the exact private substitutions and inspect actual +protocol, original/sanitized TRX, proof drivers and cleanup records. The dual +control's exact-case marker proves its second fault was reached while the first +assertion and stack survive. The export reviewer independently replays both +failed controls and the clean result through the decoder, verifies forty-two +clean assembly hashes and passes all fifty-three offline controls in 17.016 +seconds. The core reviewer independently checks the production completion chains +and the sibling helper's unchanged adjacent caller. + +The export reviewer also checks all twenty-one failed-run archives against their +raw API inventory. The record retains the unrecoverable historical timeout and +requires complete corrected-source qualification. No .NET/provider/Docker/Node +experiment is repeated. All commands join, no files change and the tracked tree +stays clean. The second fresh independent review round remains required. + + +##### Second independent recurrence diagnostic review and source freeze + +Two different fresh reviewers inspect all five files in +`4e06ffa1..196a5b4e` and their relevant dependencies: `gpt-6.1-sol` at +`xhigh` for ownership/correctness and `gpt-6-astra` at `high` for +privacy/evidence/governance. Both approve without a verified Blocker, Major or +Minor. They independently confirm first-fault preservation, continued cleanup, +unchanged assertions/waits, actual completion chains, the adjacent helper caller +and strict finite failure-only export. No production code changes. + +Both verify seven source hashes, sixty-one artifact hashes, exact private +substitutions, actual adapter/first-stack transport, original/sanitized outcomes +and forty-two clean assembly hashes. Both also check all twenty-one historical +archives against the raw API inventory. The core reviewer reconstructs the twenty +fresh metadata commands, every identity and both distinct assignment digests, +and verifies the seven-case corpus TRX and build/format records. Independent +launcher runs pass all fifty-three controls in 16.713/18.139 seconds. All commands +join; neither repeats .NET/provider/Docker/Node experiments or changes a file. + +The governance reviewer also approves the unpublished final PR draft subject to +replacing its pending qualification marker with actual current-source results. +Local implementation, validation and both fresh recurrence diagnostic review +rounds are complete. [PR #34](https://github.com/HodeTech/LearnStack/pull/34) +records the frozen head's exact hosted run/attempt identities and retained +producer/aggregate/public evidence. Complete corrected-source A/B qualification +remains required before readiness; the earlier timeout boundary stays +unrecoverable. Merge and P02b-7 remain separate. + + +##### Reviewed-source startup failure and retained evidence + +Frozen-source assignment A at +`dbfad06b1302c76c9d2b4a29dfca0d6db0795026` did not qualify. Run +[39727855228](https://github.com/HodeTech/LearnStack/actions/runs/39727855228), +attempt 1, completed 25 of 27 jobs successfully; `backend ordinary-7` failed +and the required integration aggregate refused its incomplete evidence. No +assignment B was started and no failed-job retry substitutes for this result. + +- Failed case `4172c42b-b84f-59bf-426f-60d6c521ec52`, the Outcome-ACK + settlement case (`knownFailure: False`), returned cancellation after + 32.0671777 seconds. + Its source locations identify the startup wait for the Outcome cleanup + barrier. The retained finite snapshot reports `prepared`, one normal + attempt, one renewal refusal, zero elapsed losses and zero executions. + No original Outcome owner was captured. This establishes failure before + the intended post-ACK proof; it does not identify the renewal refusal branch. +- Producer artifact `12404570952` has SHA-256 + `29cc4750561aabf3efc51b2e59b841033ae5a9c95a7601ff4d66a97b50a42dbc`. + It reports `tests_failed` and `owned_completion_missing`, with forced + cleanup, incomplete ownership and separately completed cleanup ownership. + All 20 producer archives and the successful backend aggregate are retained + against the raw Actions API sizes and digests. The final 21-archive capture + has SHA-256 + `44bb709c4683ad3d9a077ea5ec6686f83790746d6a1cfa30cc0a6ebdb32a1ae6`; + its qualification flag remains false. +- The previous recurrence failure's exact case passed in this run after + 5.5832527 seconds, with complete natural ownership. This supplies no missing + historical timeout cause. The public proof also passed independently; + neither result overrides the failed whole assignment. + +Source inspection identifies a possible legal interleaving: Prepare's real +row lock can exclude the still-active identity from a successful +`FOR NO KEY UPDATE SKIP LOCKED` renewal batch. A timely, acknowledged empty +batch closes that identity's permission; Prepare may still receive its +already-issued COMMIT acknowledgement. The observed startup facts are +compatible with this branch, but do not prove that it occurred in CI. +The correction owner is the settlement test fixture. Production renewal +policy, SQL, lease deadlines and refusal semantics remain unchanged. + +Failed-job reruns do not replace this evidence. Attempt 2's integration job +`119676062757` refused `artifact_api_missing`: only `ordinary-7` produced +an attempt-2 archive. Its artifact `12405733408`, SHA-256 +`68252513daa900062f3f8ed7823922f3dd09da91a6942b3a588d0f2302dee91a`, +contains 240 passing cases under assignment B; the previous failed case is +absent. Reusing the same shard name does not rerun the same assignment. +Attempt 3's integration job `119676234308` refused +`jobs_api_population_changed`; no attempt-3 producer archive exists. +The original API response at that refusal was not retained, so its exact +population discrepancy is not recovered from a later consistent response. +The rerun capture has SHA-256 +`b730e8293ae0a806865579c6e838d0418892f7ddf881fd06efcd34c691d13496`. +The [existing recovery procedure](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) +requires **Re-run all jobs**, with all producer evidence from the same attempt. + +##### Settlement fixture scheduling and real counterexamples + +The three existing settlement cases now isolate the intended post-ACK proof +from unrelated legal pre-ACK renewal refusals. Their fixture uses a distinctive +validated 1125 ms renewal cadence instead of one second. No production code, +SQL, lease duration, deadline or assertion is weakened. + +- The first typed native lease factory creates and retains its real system + timer, then waits outside locks for the actual renewal pacing timer. The + execution identity is still unpublished, so the immediate initial renewal + scan sees no eligible identity. Native lease and deadline clocks keep running. +- The first actual pacing callback waits until the original Outcome ACK and + held cleanup. Its release exercises the real renewal loop. The existing + four-second observation budget also requires the second actual pacing timer + to arm before releasing Outcome cleanup. Holding that callback prevents an + unrelated pre-ACK Finalize race from contaminating this settlement proof. + The existing 30/80-second startup/completion waits remain unchanged. +- Cleanup seals and opens both holds before stopping the runtime. Actual timer + disposal joins queued callbacks before synchronization objects are disposed; + incomplete runtime cleanup cannot close the factory census. Synchronous + timer disposal never joins itself from inside a forwarded callback. The + second callback's separate 120-second safety watchdog cannot extend any + caller deadline or prove disposal. +- An independent explicit-owner counterexample holds the real Prepare COMMIT + request and verifies its PostgreSQL row lock. A separate actual renewal + operation returns a timely, clean, physically acknowledged empty result, + with its exact original job/attempt/token probe. The identity closes with + renewal refusal while the admitted Prepare later ACKs. Application-role + readback confirms prepared state, no execute intent/outcome and no provider + invocation. This proves an available legal interleaving; it does not recover + the historical CI branch or claim stock Hangfire handoff. The existing + later-Finalize attribution counterexample remains independently asserted. +- Failure export adds two fixed source roles and optional finite pacing facts, + retaining the eight-location bound. Prepare-only facts bind the exact + `knownFailure: True` case. No raw path, exception/provider text or identity + enters this projection; diagnostics cannot qualify completion. + +One frozen private copy binds 1,927 source files and five exact changed-source +overlays. Clean execution passes all three original case IDs, zero skips, in +64.145 seconds; their durations are 16.1845573, 21.3963182 and 18.9924022 +seconds. The actual adapter is `2.8.2.0`. + +Two private controls exercise the proof rather than merely its setup: + +- Removing both active-selection and empty-result settlement exclusions makes + all three cases fail at `renewal_second`, on the unchanged open-Run assertion + after physical Outcome ACK. Actual Outcome cleanup is still pending and the + durable phase is `finalize_pending`. The original sticky cause and both loss + counters remain empty/zero, as required for an already settled identity. + Actual pacing callbacks/timers join without a pacing fault. +- A planted Prepare assertion after the genuine empty-ACK observations makes + only the named known-failure case fail; the other two pass. The original + assertion survives. Issued admission, external/business work, cancellation + callback, identity, control, private invocation and generation all join; + execution/running/retained counts are zero. No unrelated operation is labelled + issued or joined. + +All six test-created containers across these runs are naturally absent; owned +process groups join. The complete receipt has SHA-256 +`1ef5254dc6086a722e6d8b95c63b3b3451a755b1222a31d5d4634fd40b19576a`. +It binds original/sanitized TRX, protocol, exact private substitutions, source +and binary evidence, seven command receipts and 749 final workspace outputs. +The final clean workspace Release build reports zero warnings/errors and +scoped format verification passes. Independent pure replay of all three +actual protocol streams agrees with their retained outcomes and finite facts. +All fifty-five launcher controls and nineteen aggregate controls pass. + +Fresh metadata discovery completes twenty bounded commands in 17.379 seconds: +5,920 cases, the same complete manifest and unchanged, materially different A/B +assignments. Its receipt has SHA-256 +`19ab2cfd147b8477983f5addf40eee6bbf207e29c484f887f92189883ca563be`. +This is metadata evidence, not execution of the whole suite. Seven current +corpus/Docker-trait cases pass without skips in 8.042 seconds; their receipt has +SHA-256 +`25d949b4a406b9ad1ecd322166023de788894ae185ab8592a74ead9840196445`. +The phase's 288 relative links/fragments resolve. Independent implementation +reviews and complete corrected-source hosted A/B qualification remain required. + +##### First independent settlement scheduling review + +Two fresh reviewers inspect all six files in `dbfad06b..0dc962dc` and their +relevant production owners, publication, timer, proxy and cleanup dependencies: +`gpt-6-astra` at `xhigh` for correctness/ownership and `gpt-6.1-sol` at +`high` for privacy/evidence/governance. Both approve without a verified +Blocker, Major or Minor. They confirm unchanged production policy, exact +case identities/deadlines, actual timer joins, first-fault preservation and +positive cleanup only after every issued operation is observed. + +Both independently match all five executable-source overlays and forty-eight +scenario artifacts. Raw TRX confirms three clean passes, three intended +post-ACK exclusion failures and the single intended Prepare failure with two +passing siblings. The evidence reviewer additionally reconstructs all three +actual adapter protocols, checks the 1,927-file clean manifest, all twenty-one +historical archives against their API inventory and the partial-rerun capture. +Neither starts tests, builds, processes or containers, edits a file or claims +that the historical refusal branch is recovered. The second fresh independent +review round and complete corrected-source hosted A/B qualification remain +required. + +##### Second independent settlement review: deadline finding + +Two different fresh reviewers inspect the complete six-file change through +`c971f4cc`, with `gpt-6-sol` at `xhigh` for ownership/correctness and +`gpt-6-astra` at `high` for privacy/evidence/governance. The governance +reviewer identifies one verified Major: normal publication calculates the +remaining deadline before creating the lease timer, but starts its deadline +observer only after that factory returns. The fixture's blocking handshake +therefore shifts the native deadline observation by its wait duration. The +running system clock and lease timer do not compensate for that distinct delay. +The ownership reviewer initially approves, then independently confirms this +ordering in an explicit addendum that supersedes that approval. Both require +the correction; neither reports another verified finding. + +This limits the preceding unchanged-deadline claim. The three clean passes and +both private controls remain retained evidence for their exact source, not +qualification of deadline preservation. Recovery's separate elapsed-time +re-debit does not repair the normal publication path. The correction must start +both actual normal timers before holding publication, retain their real +cleanup ownership and keep the initial renewal scan ahead of identity +publication. Production code and deadline policy remain unchanged. + +The reviewers independently verify source/receipt/artifact hashes, the finite +projection, raw/sanitized outcomes and retained failure chronology. No runtime, +test, build, process or container is started. The original API response behind +attempt 3's population refusal remains unavailable. Fresh source-bound proof, +independent fix verification and complete hosted A/B qualification are required +after the deadline correction. + +##### Deadline-preserving settlement correction + +The normal fixture returns the actual lease-timer handle immediately and +intercepts only the next deadline-timer factory in that same execution flow. +A shared consumed slot prevents inherited execution contexts from selecting it +again. The actual System deadline timer starts with its original duration +before the publication hold; its callback is never gated. The test deliberately +holds first pacing-timer creation, verifies both actual normal timers and the +unpublished identity, spends real time inside the existing startup budget, then +opens pacing creation. An expired deadline cannot authorize business execution +when that synchronous construction path resumes. This does not claim the +execution-close action runs while its own synchronous prefix is held. + +Retained recovery keeps its separate lease-return handshake and elapsed-time +re-debit; it has no normal deadline observer. Cleanup seals factories before +opening waits, observes every issued factory return, and joins actual timer +and callback disposal before releasing synchronization resources. The three +case identities, production source, stage durations, four-second post-ACK +observation and physical application-role assertions remain unchanged. + +The finite diagnostic projection adds the normal-only `deadline_armed` +boundary and actual deadline-timer state. Retained recovery cannot claim that +boundary or an issued normal deadline timer. Fifty-six offline launcher +controls pass, including case binding, closed values and canary rejection; +the existing eight-location cap remains unchanged. + +The corrected-source actual pinned-adapter run passes all three settlement +cases with zero skips. Both normal cases prove actual lease/deadline arming +before the held first pacing factory; the known-failure case also executes the +unchanged real Prepare and later Finalize counterexamples. A copied complete +settlement-exclusion defect makes all three fail at `renewal_second`, preserving +the original assertion, physical acknowledged Outcome and actual timer/runtime +joins. These results are source-bound local proof, not hosted qualification. + +A separate copied deadline-ordering defect moves actual deadline creation after +the publication handshake. Both normal cases fail at `deadline_armed`, and +retained recovery passes. The original cancellations survive sanitization and +the selected deadline and first pacing timers finish/cancel, but runtime +completion has no positive join within the unchanged drain budget. Its full cleanup oracle therefore +refuses. The bounded test process exits naturally and both exact owned +containers become absent; those observations do not replace the missing +internal runtime witness. This is retained detection evidence with an explicit +cleanup limit, not a passed cleanup control. No corrected-source change or +production change is inferred from that deliberately broken construction. +The earlier planted Prepare control remains evidence for its original frozen +source only; the unchanged helper body does not turn an old binary into fresh +corrected-source proof. + +The retained corrected-source summary has SHA-256 +`195fff62567643010e27f0dc5f0cde5bb2af24a94fe50ef5cd3f319891cb8f5e`; +its 1,927-file frozen source manifest has SHA-256 +`5b0988882c9a6331c4f0c878c063597256566711a2104a5dbdf6a26649813d37`. +Independent replay matches all actual adapter protocol completions, original +and sanitized TRX outcomes/durations, finite facts and source substitutions. +All retained artifact hashes and five workspace overlay hashes match. The +final workspace Release build passes with zero warnings/errors in 47.217 +seconds; scoped format verification passes in 23.198 seconds. Every owned +command group exits. The initial clean Docker absence inspection inherited +its helper environment, with application credential-prefix presence checked +false; all .NET commands and subsequent Docker checks use the explicit tool +environment allowlist. This distinction remains in the provenance receipt. + +Fresh metadata discovery completes twenty bounded commands in 18.006 seconds: +5,920 exact identities, unchanged complete A/B unions and materially different +assignments. Its summary has SHA-256 +`940090d702545aa7eb791559b333f7c46408cb0b30ad902c75c2ce6f9ea6072d`. +Seven current corpus/Docker-trait controls pass in 8.631 seconds; their receipt +has SHA-256 +`5e092c42b844d746d7ad6a5be99682641c95a6ec71b08b62542f94253a857ad3`. +All 749 final workspace build outputs match their retained manifest. +Independent fix verification and complete corrected-source hosted A/B remain +required before final qualification. + +##### Independent deadline-fix verification + +Two new independent reviewers approve `c971f4cc..c618414e`: `gpt-6-astra` +at `xhigh` for correctness/ownership and `gpt-6.1-sol` at `high` for +privacy/evidence/governance. Both inspect all five changed files and the +adjacent publication, recovery, native lease and cleanup paths. Neither finds +a verified Blocker, Major or Minor. Each independently checks the original +deadline ordering, actual timer arming before the hold, publication/gate safety, +factory/callback ownership and the recovery distinction. Their offline replay +matches exact identities, durations, raw/sanitized outcomes, substitutions and +retained hashes; focused in-memory parser checks also pass. Neither executes +.NET, providers, Docker, Node or a build, edits the repository or scans processes. + +Both explicitly preserve the ordering control's refused runtime-cleanup +oracle. Its natural process/container absence is not substituted for internal +quiescence. The earlier unchanged-deadline claim remains limited by the dated +finding above. Post-commit hashes match all five tested overlays. The reviewed +correction is ready for a new complete hosted A/B qualification; no prior green +sibling or failed-job rerun supplies that missing final-source proof. + +#### P02b-6 closed-PR CI rerun correction (2026-10-22) + +PR #34 is squash-merged as `28b9113a` at 08:02:48 UTC. Its tree, +`b310fb7862b977adc5037e260f8d638e7f0f08a9`, exactly matches the reviewed +`c1238ffc` head and its checked-out PR merge. The first complete assignment of +[run 39742745102](https://github.com/HodeTech/LearnStack/actions/runs/39742745102/attempts/1) +passes all 27 jobs and 5,920 .NET cases. Independent API/archive/result verification +has summary SHA-256 +`2c21b98d1595dcff0ca0e07a060b806623799ef1bea8f6696b4289e5b8ae4681`; +the separate public-demo receipt has SHA-256 +`b9c10a7ff7172e51f8da81361a26674155527be20826c900e45f2cd149b9246e`. +The merged `main` push, +[run 39744842943](https://github.com/HodeTech/LearnStack/actions/runs/39744842943), +also completes successfully on that identical source tree. + +The squash merge precedes the second full assignment. All twenty B +producer jobs pass, and independently validated producer evidence contains +all 5,920 cases, including the three settlement cases. Its producer-only +summary has SHA-256 +`00615bc56fc469beb02145b5bdc44d58953fe62d3b600f074fef1b186924b0a6`. +Nevertheless the complete B attempt is refused: `meta` fails, and both +aggregates reject `run_pull_identity_mismatch`. GitHub's same-repository PR +projection is now empty. The aggregates retain their required identity witness; +producer consistency cannot replace it. This is **not** a successful complete +B qualification or a pre-merge A/B claim. + +The separate `meta` defect is reproduced from its actual shell owner. It +fetches the current base branch with depth one after a squash merge, then +requests `origin/main...HEAD` against the old checkout. Git refuses with +`no merge base`. The correction selects the event's immutable base SHA and +compares the two snapshots directly; no live branch fetch or merge-base walk +is needed for link existence. The unresolved-base full-tree fallback remains. + +Five actual-workflow regression controls construct an isolated real Git +squash/shallow graph. They cover a valid closed-PR range, broken changed links, +push snapshots, missing/manual-base full-tree checks and an empty valid range. +All five pass in 1.964 seconds; the unchanged old owner fails five assertions. +The retained regression summary has SHA-256 +`7bd8aabce9ab8de37b41ad02dc48401161abe660c72d6b321f246425ae4cb9a7`. +The controls run in `meta` under their own one-minute ceiling, within its +unchanged five-minute job ceiling. + +Closed-PR API refusal is documented rather than weakened. Further PR +qualification uses an open follow-up PR and completes both full assignments +before merge. Required names, producer ownership, plan, permissions and +execution ceilings remain unchanged. No application, realm, credential, +production renewal or commit policy changes. The workflow correction and its +independent reviews own the follow-up qualification; earlier failed and +partial receipts retain their source and evidence limits. + +Local validation passes 98 controls: five actual-workflow Git regressions, +seven ADR/parser controls, seven supply-chain controls, sixty plan controls and +nineteen result/aggregate controls. Their two retained summaries have SHA-256 +`8bb09cedad6ab1b323aa88323ec36737ccd38766e3debd7b57a68741e1291db1` +and `1c9483f979aeedca06e26076789e2a1e16708d7c184b6b5575bce11a3a07b15e`. +The unchanged application sources require no new local provider experiment; +the follow-up's complete hosted assignments remain separate proof. + +##### First independent link-audit correction review + +Two fresh reviewers inspect `2fdf31eb..e2a476cf`: `gpt-6.1-sol` at `high` +for shell/Git correctness and regression meaning, and `gpt-6-astra` at `high` +for governance, chronology and scope. Both approve all eight changed files +without an actionable finding. The first independently runs the five corrected +controls (2.206 seconds), observes five assertion failures against the original +owner, and passes the actual six-file Markdown audit. The second independently +verifies the identical reviewed/squash/reconciliation trees and retained +regression hashes; it does not claim independent hosted or runtime execution. + +The root also executes the corrected actual workflow audit against the event +base: all six changed Markdown files pass. Seven existing corpus/Docker-trait +controls pass in 8.301 seconds, with retained receipt SHA-256 +`be6a5dd437113a81932ee7ece49a2ff5dcccb3e6634f4c50fb3f5a345424304b`. +A different fresh reviewer pair follows before the open follow-up PR and complete +hosted A/B qualification. No application/provider experiment or closed-PR +identity exception is introduced. + +##### Second independent link-audit correction review + +Two different fresh reviewers inspect `2fdf31eb..ecc9f92e`: `gpt-6.1-sol` +at `high` for correctness/proof behavior and `gpt-6-astra` at `high` for +cross-document governance and evidence limits. Both approve all eight files +without an actionable finding. Both independently pass the five corrected +actual-workflow controls (2.374 and 1.924 seconds), observe five assertion +failures against the original owner, and pass the actual six-file audit. +Both verify unchanged required names, ceilings and permissions, untouched +aggregate identity checks and identical reviewed/squash/reconciliation trees. +The second also verifies all seven supplied retained receipt hashes; this is +not a fresh hosted API/archive verification. All review subprocesses join. + +The correction is locally complete after both independent review rounds. The +follow-up PR remains draft until complete same-source A/B hosted qualification; +no partial producer evidence or closed-PR identity refusal is treated as passing. + +##### Follow-up frontend census correction + +The first follow-up attempt on `b25c1c4a` passes `meta`, including the corrected +link audit, but frontend's real repository census refuses the newly added +Python regression file as unclassified. The first two review rounds and local +backend controls did not cover that frontend census. This failed whole attempt +is not A qualification. + +The narrow correction adds exactly `scripts/test-markdown-link-audit.py` to the +existing explicit non-runtime tooling list. Unknown paths/formats and runtime +JS/TS exemptions remain refused. The complete guarded frontend suite passes +1,840 cases across both packages, with zero skips/todos, in 26.468 seconds; +its retained summary has SHA-256 +`2e5d31d914e52c9c24d4006445e557a535e1458d63c6d48b13adea51b083258d`. +No workflow, selector, runtime or case-count contract changes. Both independent +review rounds follow this census correction before a new full qualification. + +The first fresh correction pair reviews `b25c1c4a..36adb3aa`: +`gpt-6.1-sol` and `gpt-6-astra`, both at `high`, approve without an +actionable finding. Both verify the exact classification, actual Python +owner, unchanged unknown-format/runtime refusal controls and honest failed-run +scope. The second independently checks the retained receipt and both log +hashes, including the executed 1,840-case total. These are source and retained +evidence reviews, not independent hosted/runtime reruns. All subprocesses join. +A different fresh second pair follows the committed correction. + +The different second fresh pair reviews `b25c1c4a..76ca3adc`: +`gpt-6.1-sol` and `gpt-6-astra`, both at `high`, approve without an +actionable finding. Both independently verify the retained summary/log hashes, +actual workflow ownership, exact-path admission and unchanged unknown-source/ +runtime-refusal controls. Neither reruns Node, a provider or hosted jobs. +Whitespace checks pass and all review subprocesses join. Both correction review +rounds are complete; the failed initial attempt may be superseded by the corrected +push, and its partial successes are not complete qualification. Fresh full A/B +attempts on the same corrected source remain required before draft readiness. + +#### P02b-6 native constructor-stop failure attribution (2026-10-22) + +The corrected follow-up source `d2a32c9e` completes all 27 jobs in +[run 39753775916, attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39753775916/attempts/1). +Twenty-five jobs pass, including frontend, meta and the backend aggregate. +Independent artifact identity/digest/assignment checks cover all twenty +producers and the complete 5,920-case population: 5,919 pass and one fails. +The failed-attempt summary has SHA-256 +`6d5241086f709942d0608b85376cb6273b0d23949635c794ddb39e5d6e614f92`. +This is not successful A qualification. + +The failed `ordinary-0` case is `Native_stop_returns_the_wrapper_before_a_held_external_constructor_really_cleans_up` +with `reason: lease_loss`, ID `a37ab998-d153-7507-f862-98fd478840c8`. +Artifact `12415871381` records 32.0063708 seconds, a closed `cancellation` +label and no registered source location. The aggregate correctly refuses +this actual producer failure. `owned_completion_missing` and forced workload +cleanup are consequences, not an independently established test cause or +positive internal cleanup evidence. + +Duration alone cannot distinguish the 30-second startup token from the +runtime's separate 30-second shutdown wait. The test's 40-second caller cleanup +budget does not remove that internal bound. Its original `finally` can also +replace an earlier body exception with a cleanup exception. Three separate +local process observations on the prior source pass both theory cases +(six results); they do not reproduce or explain the hosted failure. Their +summary has SHA-256 +`21b5d51eba72a4c86eb09cf61b6abc0479bbbfc186cdda1958716ad23e3cc602`. + +The test-only correction preserves the first body or explicit runtime-join +exception with its original stack. It separately records first-failure and +later-cleanup boundaries, constructor/invocation observation and actual task +states for the wrapper, operation observer, runtime, control, ordered pools, +shared maintenance and bridge. These are finite diagnostic observations, +not authority to declare cleanup. Logging failure cannot replace the original +exception. Existing startup, wrapper, return and shutdown budgets stay intact. + +The launcher accepts this diagnostic only for the two exact existing theory +cases and the integration assembly, with bounded messages, closed state sets, +separate failure/cleanup markers and no raw provider/error/path text. The two +native helper files receive finite source codes under the existing eight-location +bound. No runtime, policy, case identity, selector or topology changes. + +Sixty offline launcher/parser controls pass, including malformed/ambiguous/ +wrong-case/wrong-channel/canary and truthful failed-outcome controls. The +copied real-provider proof passes both clean cases. Three distinct copied +controls produce six intended failures: body only, cleanup only and both. +The paired corrected control preserves the original body exception, whereas +the same paired control in the legacy test loses it to the cleanup exception. +Every usable cleanup fault is planted after actual runtime completion; +process groups join and exact owned containers are independently absent. +The retained proof summary has SHA-256 +`909b18c47080ca618eecdc1df4f42d774b049a75f15096971dd7dcffcf2483c0`. +This establishes diagnostic and first-failure behavior, **not** the cause of +the earlier hosted cancellation. The final integration-project Release build +passes with zero warnings/errors. Seven corpus/Docker-trait cases and targeted +C# whitespace verification pass; the tested three overlay hashes match the +workspace. Committed-source independent reviews follow. + +A separate source inspection finds a one-extra-hint scheduling weakness in +`EnsureNativeSdkStartAsync`: committed bridge metadata does not prove an earlier +null-routing recovery control has finished private cleanup. Its extra hint can +therefore be rejected before the 60-second repair grace, beyond the caller's +30-second startup budget. This is not evidence that the interleaving occurred +in this failed run. Deterministic qualification of that fixture path remains +with this correction; no production defect, timeout increase, passing retry or +waiver is inferred from it. Complete final-source hosted A/B remains required. + +##### First native-wait diagnostic review (2026-10-22) + +The first fresh pair reviews `d2a32c9e..f3ca5c4d`: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both approve the tracked correction; +neither runs .NET, Node, Docker or hosted jobs. The correctness reviewer +independently passes all sixty offline controls and verifies raw/sanitized +results, protocol observations, eighty retained artifact hashes and all three +source overlays. The evidence reviewer independently verifies artifact and +source binding and the stated limits. No source finding remains. + +One proof-bookkeeping finding is corrected with original records preserved. +The private proof runner shadowed its container list with the diagnostic +projection, so three initial receipts counted twelve absent containers rather +than two. Each original `cleanup.json` records exactly two owned containers, +both independently absent. The derived corrected summary has SHA-256 +`09a103c975baf193f3bae5d6f4dd4be8983c30e14e18b6033378d91e38c5dcba`; +it binds original receipts, cleanup records and corrected receipts. The initial +summary above remains unchanged. This count correction neither manufactures +cleanup nor changes any process, test result or source digest. Reconstructed +clean and four planted source variants exactly match the original pre-execution +manifests; their materials index has SHA-256 +`e0c1f749e07b315ac770e53eab3292a6fcc32c81081aa7695e2383371102e888`. +The separate helper interleaving and hosted cancellation cause remain unproven. + +##### Second native-wait diagnostic review (2026-10-22) + +A different fresh pair reviews `d2a32c9e..8234856c`: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both approve without an actionable finding. +Both independently pass all sixty offline controls, verify eighty artifact +hashes, three committed overlays, five exact source variants and corrected +receipt linkage. The evidence reviewer reprocesses every retained protocol +stream and reproduces the recorded case sets, outcomes and finite diagnostics; +the correctness reviewer independently checks original-exception preservation +and diagnostic authority boundaries. Each verifies actual raw cleanup records +for two owned containers per scenario. Neither runs .NET, Node, Docker, a +provider or hosted jobs. Whitespace checks pass. Both diagnostic correction +review rounds are complete; the earlier hosted cause remains unknown. Full +same-source A/B qualification is still required before draft readiness. + +##### Diagnostic-source hosted A qualification (2026-10-22) + +[Run 39762258730, attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39762258730/attempts/1) +qualifies assignment A at `12d4f088`: all 27 jobs and all 5,920 cases pass, +with zero skips. Independent validation rechecks current-attempt producer API +identities, archive digests, assignments and both aggregate calculations. Its +summary has SHA-256 +`423e01b7d33acf081b999c2f4d78a209ef500c1c494a69c8fefa39082f7e44cf`. +Independent public-demo verification covers 27 JSON/HTML report pairs, nine +screenshots/navigations, 24 visibility controls, 134 API completions and natural +cleanup; its receipt has SHA-256 +`502db1b3b3c088651dd136755f4938da2fb55f5bd08fbf9c09c8d5ab6b53dd94`. +Both constructor-stop theory cases pass, including the previously failed +`lease_loss` case at 4.7362398 seconds. This does not explain the earlier +cancellation. The fixture correction below supersedes this source before B; +this A is not final-source A/B qualification. + +#### P02b-6 fixture hint waits for actual prior cleanup (2026-10-22) + +The separate fixture weakness above is reproduced with a controlled real +native interleaving. Its original committed handoff can remain owned by a +null-routing recovery invocation while private cleanup is pending. An extra +hint sent merely because the bridge ACK is visible can be consumed by the +local identity gate without entering the intended constructor. The bridge's +60-second repair grace is outside these fixtures' 30-second startup budget. +This controlled mechanism is not proof of the earlier hosted cancellation. + +`EnsureNativeSdkStartAsync` retains one extra real hint. It waits for the prior +native job's success, empty actual external-pool work and routable local +identity, then checks durable eligibility under the same generation. It never +retries failed native work or resets its allowance on a changed generation. +Pool readiness precedes generation capture under the pool's own lock. Polling +SQL uses the original startup token. Pending, finalization and due recovery +callers retain their existing boundaries; production behavior and all wait +budgets are unchanged. + +The new real-provider fact holds the original invocation's actual timer-wrapper +`DisposeAsync`, after joining the underlying System timer's disposal. A real +initial SQL row lock forces the original empty acquisition, but that lock is +committed before testing the helper. Independent observations then show the +original native job still Processing, one owned recovery identity and +`CanRoute == false`. The corrected helper creates no extra hint while that +cleanup remains held. After release, one real same-generation hint enters one +constructor and consumes one normal attempt, without a bridge repair. + +The copied counterfactual removes only readiness guards: its premature real +extra hint succeeds at the native layer while the original identity remains +owned, but no constructor enters. The native-count assertion intentionally +fails. Both paths release barriers and independently join helper, pulse, +transaction, bridge and runtime cleanup while preserving the first failure. +The six clean cases (new fact and five existing callers) pass; the planted +counterfactual remains failed. All actual process groups join and exactly two +owned containers per scenario are independently absent. Four source overlays +match the tested copy; its final proof summary has SHA-256 +`e11cb520b64abf105da06cc96f56d718668c3984c597022721f7275e9419b032`. +Sixty offline controls pass, including the new finite source-code registration; +C# whitespace verification passes and the final integration-project Release +build has zero warnings/errors. Seven corpus/Docker-trait cases pass. Fresh +local discovery executes twenty actual project/filter commands: all prior +5,920 case identities remain unchanged and one fact is added, for 5,921 cases. +Both assignments retain complete membership and different co-membership with +the unchanged plan. The metadata receipt has SHA-256 +`262636b71c88456c39596b8aedc2bc5e18f2b4b02f47078bdbbe3cd920a6e038`. +Committed-source reviews and final-source hosted A/B qualification remain +required. + +##### First fixture-handoff review and cancellation guard (2026-10-22) + +The first fresh pair reviews `12d4f088..87ac3713`: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both approve the actual-cleanup correction. +They independently verify the source overlays, 42 scenario artifact hashes, +real discovery/execution results, intended premature-hint failure and actual +process/container cleanup. The evidence reviewer replays the twenty discovery +streams and recomputes both complete assignments. Neither runs a provider, +.NET, Node or Docker. No additional source finding remains. + +One small cancellation correction is confirmed and applied: preserve the old +helper's explicit cancellation check immediately before synchronous hint +creation. Readiness-lock waits follow the last token-aware SQL read, so an +already observable cancellation must be rechecked at emission. This check +neither makes cancellation atomic with issuance nor explains the hosted failure. +Fresh exact-source runs pass the new fact and five existing callers; the copied +readiness-guard counterfactual still intentionally fails while preserving this +same cancellation check. All actual process groups join and two exact owned +containers per scenario are absent. The refreshed proof summary has SHA-256 +`8ad260316b633421806b8aa79c19bc57abf30c8746de4b330701d882cebf6b81`; +the prior summary remains unchanged. The integration-project Release build +passes with zero warnings/errors. Second-round independent review and complete +final-source hosted A/B remain required. + +##### Second fixture-handoff review (2026-10-22) + +A different fresh pair reviews `12d4f088..9d1ba8cf`: `gpt-6-astra` at +`xhigh` and `gpt-6.1-sol` at `high`. Both approve without a verified finding. +Both independently verify the refreshed proof summary, four overlays, exact +planted sources, 42 scenario artifact hashes, six clean passes and the intended +premature-hint failure with actual native count two. The correctness reviewer +also verifies 1,490 backend/script source hashes. The evidence reviewer replays +the raw execution/discovery streams and twenty metadata streams, checks 61 +metadata artifact hashes, recomputes complete distinct assignments and passes +all sixty offline controls. Both verify actual process joins and two exact +owned-container absences per scenario. Neither runs .NET, Node, a provider or +Docker. The original metadata record remains bound to `87ac3713`; the subsequent +cancellation-only correction preserves all declarations. Whitespace checks +pass. Both fixture correction review rounds are complete. The historical +hosted cancellation remains unexplained; complete final-source A/B remains +required before draft readiness. + +#### P02b-6 hosted browser dependency acquisition (2026-10-22) + +At source `9eecf967`, run `39767540577` attempt 2 qualifies complete B: +27 successful jobs and 5,921 passed cases, with independently checked producer, +aggregate and public-demo evidence. The independent summary has SHA-256 +`a5173cf4c33805e6a886e357d9924698be854ef3c99f546f09ad2714b74857c3`; +the public proof receipt has SHA-256 +`cafcca3abb54c14e1ee31cfabea06daedab1b78e7fcba736426026f803dd1423`. +Neither unsuccessful A attempt contributes to that qualification. + +Attempts 1 and 3 fail before product launch in the unchanged five-minute +`Install pinned browser tools` step. Package installation through pnpm completes; +Playwright's APT acquisition waits on the runner's existing Ubuntu mirror while +fetching system fonts. Attempt 1 visibly reaches the next official mirror only +after minutes. Attempt 3's raw job log has SHA-256 +`bc4ea0cabcee872092f6e8645daabb32a95aae5a0f731e2278918f53ca3c92c6`. +These observations establish a dependency-acquisition failure, not a browser, +application, DNS, IPv6 or provider defect. Failed attempts remain failed. + +The correction uses the runner project's +[pinned APT acquire handling](https://github.com/actions/runner-images/blob/dff7cf5f1d89bdac4336cd261875e553582fe769/images/ubuntu/scripts/build/configure-apt.sh#L15-L39): +one retry and 15-second HTTP/HTTPS timeouts for the existing x64 job. The actual +workflow creates one exclusive, late-sorting temporary APT fragment, checks the +three effective root settings without evaluation and removes only its fragment +on shell exit. No sources, package verification, package set, browser revision, +sandbox, permission or job/proof deadline changes. This is an ADR-0056 setup +repair, not new host-crash authority or a total-duration guarantee. A forced +termination can leave the fragment until the disposable VM is removed; such an +attempt cannot qualify. + +The existing workflow-shell owner gains eight controls: successful complete +installation and configuration cleanup, plus creation, partial-write, readback, +installer, cleanup, pnpm and unsupported-architecture refusals. They execute the +actual shell with isolated command substitutes and no local privilege or APT +mutation. All thirteen cases pass. Committed-source independent reviews and +complete A/B qualification on the resulting source remain required; the prior +source's complete B cannot qualify the changed workflow. + +The complete frontend runner passes 1,848 cases across both packages with zero +skips/todos. Workspace typecheck, lint and the changed TypeScript formatter +check pass. These isolated shell controls do not claim real APT or hosted +mirror-failover execution. + +Attempt 3 subsequently finishes with 26 successful jobs: all 5,921 backend +cases and both aggregates pass. Independent source/API/archive/assignment +revalidation produces a backend-only summary with SHA-256 +`984dfc4a315b5f7a273a81e250a240a17d8f13d80492159c507667c3b09d93a7`. +Its whole-workflow qualification flag is false because the public setup fails. + +##### First browser-acquisition correction review (2026-10-22) + +Two fresh reviewers inspect `9eecf967..b25d00a9`: `gpt-6-astra` at `high` +for security/correctness and `gpt-6.1-sol` at `high` for evidence/governance. +Both approve without a Blocker or Major. They independently check the retained +validation digest and all five file hashes. The correctness reviewer executes +eleven extracted-shell cases under the hosted default Bash errexit behavior; +the evidence reviewer executes all eight committed success/refusal paths with +isolated substitutes. Neither runs Node, .NET, Docker, APT or privileged code. +The reported full frontend result remains a root-observed console result, +not independently retained raw-report evidence. + +One Minor proof mismatch is verified: the purported partial-write substitute +previously wrote all configuration bytes before returning failure. It now writes +only the first line and fails, so cleanup is tested after a genuinely incomplete +fragment. All thirteen targeted controls pass again. The implementation shell +does not change. A different fresh review pair and complete final-source hosted +A/B remain required. + +##### Second browser-acquisition correction review (2026-10-22) + +A different fresh pair reviews `9eecf967..60275302`: `gpt-6-astra` at +`high` for correctness and `gpt-6.1-sol` at `high` for evidence/governance. +Both approve without an actionable finding. Each independently passes sixteen +actual-shell executions: all eight paths under hosted default Bash errexit and +the stricter test flags. The evidence reviewer additionally observes exactly +one configuration line before partial-write cleanup, exit 18 and no browser +invocation. Both verify the pinned runner source and the old validation receipt's +explicit source limits; they do not extend its hashes to changed test/docs. +Neither runs Node, .NET, Docker, APT or privileged commands. + +All five real-Git link-audit controls also pass in 2.119 seconds. Whitespace +checks and commit hooks pass. Both browser-acquisition review rounds are +complete. The resulting source stays draft until complete same-source A/B, +including the real hosted APT installer and public product proof, qualifies. + +#### P02b-6 public-demo outer budget allocation (2026-10-22) + +At source `e2954be9`, run `39775966553` attempt 1 passes all 27 jobs and +5,921 backend cases. Independent complete verification has summary SHA-256 +`3c71040273ec9d63a9aa0dd5ce9593bc97b6accdee7cb923af6e28648dd20233` +and public-receipt SHA-256 +`30afd8a7479a953cdbf6696ad49cf7fe180b3df1b3045940a1465b493c0dd574`. +The complete demo takes 196.294 seconds of setup, 661.787 seconds of proof +and 10.725 seconds of natural cleanup. Browser installation passes in 32s. + +Attempt 2 passes all 5,921 backend cases and both aggregates, but fails the +public demo at the sixteen-minute outer deadline. Its backend-only independent +summary SHA-256 is +`ebb8b7c5db62a397de2c3780cb16d9d2310ccdf597e6ddb9791c468592d6a111`; +whole-workflow qualification remains false. Browser installation passes in 36s. +The public artifact API/archive digest is +`32d01fe2d31b1330aa58e1c5485425a27aca55a86fc7ff45976f98db9d14b495`. +It retains 26 of 27 report pairs, nine navigations, 24 visibility controls and +132 API completions, all 200. Setup takes 252.382 seconds; the final audit is +cancelled after 651.728 seconds of proof, below the 720-second proof ceiling. +Exit 124 agrees with outer-deadline exhaustion. Natural cleanup passes in +10.714 seconds; neither its success nor partial reports qualify the failed run. +This is separate from the earlier APT acquisition and native cancellation cases. + +[ADR-0056](../decisions/0056-public-demo-browser-and-lighthouse-enforcement.md#pacing-runtime-and-artifacts) +fixes the 12-minute proof, 30-second native cleanup and 20-minute whole-job +ceilings and requires reserved tail time. It does not fix the 16/4 allocation. +That allocation's dated delivery records remain historical. The correction +uses a seventeen-minute outer allowance and three-minute reserve within the +same approved limits; no audit, quiet interval, sandbox or correctness check +is removed. The existing package permits implementation details inside those +approved boundaries without a new decision. + +| Nominal tail allowance | Seconds | +|------------------------|---------| +| Existing owner stop/forced-stop grace | 35 | +| Sandbox cleanup: TERM 15s, KILL after 5s | 20 | +| Sanitized workflow receipt: same wrapper | 20 | +| Existing artifact-upload step limit | 60 | +| Runner transitions, cancellation and post-step margin | 45 | +| Total reserve | 180 | + +These are scheduling allocations, not a worst-case OS guarantee. The 35-second +failure grace does not enlarge passing native cleanup beyond 30 seconds. +Forced termination proves no detached-child, container or private-resource +absence; unconfirmed/censored cleanup or receipts fail. The public job uses the +same pinned cache action's restore-only entry, removing its save post-hook. +Other jobs retain cache writes and a miss still performs normal restoration. +Complete final-source A/B and both fresh review rounds remain required. + +Local validation passes: 22 actual workflow-shell/control cases; complete frontend +1,857 cases in two packages, zero skips/todos; typecheck, lint and scoped +Prettier verification. The five real-Git link-audit controls and +`git diff --check` pass. These local checks do not qualify hosted fit. + +##### Outer-budget correction review round 1 + +Two fresh independent reviewers (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspect `e2954be9..d5f19826` and approve +without actionable findings. Both independently replay the actual first-step +reservation and eight tail argument/status cases using private fake commands. +The correctness reviewer also executes the sanitized receipt Python body: ten +offline checks pass. Both verify historical API/archive identities, hashes and +complete/partial report distinctions. These controls verify wrapper arguments +and failure propagation, not real GNU signal timing or hosted fit. The actual +changed-doc workflow audit passes all eight changed Markdown files. No provider, +Docker, privileged installer or application runtime is launched by reviewers. + +##### Outer-budget correction review round 2 + +A different fresh pair (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspects `e2954be9..2dc9d745` and +approves without actionable findings. The correctness reviewer independently +passes seventeen extracted-shell/receipt checks, including proof failures and +exhausted-budget refusal. The evidence reviewer passes nine shell controls, +fully revalidates both historical 5,921-case producer sets and both public +archives, and verifies the previous roadmap bytes remain intact. Both retain +the fake-timeout/hosted-fit limitations. Reviewer-reported round-1 executions +and root-observed local suite results are distinguished from their own checks. +No source correction is required. Both rounds are complete; the final source +still requires new complete A/B qualification before the draft becomes ready. + +#### P02b-6 OpenAPI fixture maintenance completion (2026-10-22) + +At source `58d9ecdf`, run `39784545745` attempt 1's OpenAPI job +`119844135596` fails during `SnapshotControls.tearDown`: temporary repository +removal raises `OSError: [Errno 39] Directory not empty: objects`. +The snapshot-admission control body reaches its cleanup; breaking-policy and +actual comparison steps do not run. The retained log SHA-256 is +`137c5fa3d7ef08a4d50547eaad3bf141030286e0d0ee026a0ac5b7a75da3d909`. +The runner reports Git 2.55.0. This whole attempt cannot qualify. + +[Git 2.55's automatic-maintenance owner](https://github.com/git/git/blob/v2.55.0/run-command.c#L1956-L1992) +waits the maintenance command, which can detach its background work. The +[maintenance implementation](https://github.com/git/git/blob/v2.55.0/builtin/gc.c#L1785-L1828) +can continue touching the object store after the waited commit returns. +The hosted log lacks process tracing: this is a verified mechanism consistent +with its cleanup failure, not a proven trace of that particular failure. + +Only the synthetic snapshot-control repository sets +`maintenance.autoDetach=false` immediately after initialization. Its actual +maintenance then finishes before the waited Git command returns and before +strict temporary-directory removal. No error is swallowed, removal retried, +repository maintenance disabled, workflow deadline extended or OpenAPI +comparison/admission rule changed. Project and user Git configuration remain +untouched. + +A real-Git regression supplies a private global configuration requesting +background work, forces actual commit-graph maintenance, and reads Trace2 +immediately after commit returns. The nested graph process must exit before +the commit process, use the foreground path and produce the graph-chain file. +A private negative counterpart without the fixture setting produces the real +graph after commit returns; the guarded counterpart finishes it first. Both +are observed on Apple Git 2.54.0, not represented as Git 2.55 runtime proof. +All fifteen snapshot controls pass in 2.223 seconds; `git diff --check` passes. +Fresh independent review rounds and complete final-source hosted A/B remain +required. + +##### OpenAPI maintenance correction review round 1 + +Two fresh independent reviewers (`gpt-6-astra`, high correctness; +`gpt-6.1-sol`, high evidence/governance) inspect `58d9ecdf..f5696ec0`. +The correctness reviewer reproduces a Minor proof gap: an existing graph plus +an owned graph-chain lock lets the regression pass despite the real graph +process exiting 128. The regression now requires that process's exit code zero; +the same planted failure is rejected and clean execution passes. The evidence +reviewer identifies normalized web-parser line numbers in two source links; +both now target independently downloaded physical v2.55 source lines. The raw +source SHA-256 values are `68cdb7e7a83b1d3ca71af1620e16af3e537e8e3921564c6e8acb60460bcea1e1` +and `6640547903186a7e597b2826cd7b64a36c01033c49bee845c0d032dab19d3581`. +Both approve the corrected scope without remaining findings. Independently +executed 15-case suites and negative/guarded real-Git counterparts pass; +reviewers distinguish local 2.54 runtime evidence from hosted 2.55 source +analysis. Root's final corrected fifteen-case suite passes in 2.277 seconds; +the actual eight-file changed-doc audit passes. No broader runtime is needed +for this two-file test/document correction. + +##### OpenAPI maintenance correction review round 2 + +A different fresh pair (`gpt-6-astra`, high correctness; `gpt-6.1-sol`, high +evidence/governance) independently inspects `58d9ecdf..ace2a77a` and approves +without findings. Both run all fifteen controls (2.132s / 1.952s), real-Git +negative/guarded counterparts and the planted existing-graph/owned-lock failure. +The planted exit 128 is rejected by the success assertion; strict fixture +cleanup completes. Both verify hosted identity/evidence limits and corrected +physical source anchors. No repository edits or broader runtime is performed +by reviewers. Both rounds are complete; final-source full A/B remains pending. + +#### P02b-6 aggregate gate-refusal diagnostics (2026-10-22) + +Run `39784545745` attempt 1 at `58d9ecdf` completes all twenty producer jobs +and the public-demo job successfully, but both aggregates refuse with +`producer_gate_not_successful`. Backend job `119851050390` retains log SHA-256 +`0244aaf9f2efe10941f066268a323c28a769bac24489cd6fed617d185e38173d`; +integration job `119854078976` retains +`e76f5b94d0c18a76e9b99281c6b3f145a0863bf7f21d07b73f7dec7f6d782431`. +The final result is 24/27 successful jobs: the separate OpenAPI fixture cleanup +failure and these aggregate refusals prevent whole-workflow qualification. + +The error occurs after a producer job's completed/success check, at one of +its build, execution or upload gates. The original response is unavailable; +subsequent exact-version, exact-page and ordinary job API reads show all three +gates successful for all producers. Both retained later backend snapshots pass +the unchanged seven-owner verifier. API projection lag is plausible but is not +proven, and neither the failing owner nor its original gate state is known. +The missing aggregate receipt and upload failure follow the refusal; they do +not establish a wrong output path or a failed test. + +The correction adds only a closed stderr diagnostic before the same refusal: +finite source-owned producer key, build/execute/upload gate, missing/one/multiple +match class and allowlisted status/conclusion words. Unknown or structured API +values become `other`; no API names, provider text, run/job identifiers, tokens +or payloads are exported. Successful validation remains silent. The original +refusal, nonzero CLI result, every identity/gate check and all time limits remain +unchanged. No polling, retry, cross-response union or failure-to-success mapping +is introduced. + +Twenty aggregate controls pass, including 21 planted gate/shape/state subcases, +canary exclusion and clean-path silence. The next complete final-source A/B is +still required; later successful metadata does not repair this failed attempt. +Fresh independent review rounds remain required. + +##### Gate-diagnostic correction review round 1 + +Two fresh independent reviewers (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspect `979750cd..5bce55db` and +approve without findings. The correctness reviewer passes 30,492 direct input +combinations across every source-owned producer, gate and scalar/structured +state value; the evidence reviewer independently passes 1,890 combinations +and all twenty aggregate controls. Both confirm unchanged refusal and silent +success. The evidence reviewer validates both historical log hashes and both +later snapshots with the baseline and current verifier identically. The +original failing API response remains unavailable. Root's combined owner/ +aggregate suite passes 61 controls in 2.532s with no skips; diff hygiene passes. + +The same failed whole attempt's public artifact is retained independently by +API ID `12428514412`, digest +`22c3236ca499a1f095a40472301667f6b9f0b292bd5ae2871318b6e80909399c`. +Its archive has all 27 JSON/HTML report pairs; the native receipt reports passed, +150.158s setup, 628.378s proof and 10.986s confirmed cleanup. This component +observation does not qualify the failed whole workflow or a changed source. + +##### Gate-diagnostic correction review round 2 + +A different fresh pair (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspects `979750cd..84f681a6` and +approves without findings. Independent baseline/current matrices pass 36,414 +and 20,286 combinations respectively, with 63 silent successes each. The +correctness reviewer kills five in-memory diagnostic/refusal mutants using the +committed 21-subcase control. The evidence reviewer runs all twenty aggregate +controls, verifies historical hashes and both backend snapshots, and confirms +that an earlier incomplete integration snapshot still refuses. It independently +checks the public artifact API/digest and all 27 per-report pairs against the +native receipt. Both preserve the unknown original API state and failed whole +attempt status. Both review rounds are complete; new final-source full A/B is +required before the draft becomes ready. + +#### P02b-6 Outbox startup ownership and isolated diagnostics (2026-10-22) + +Run `39789942868` attempt 1 at `95edb219` fails the ordinary-10 producer +`119863012904`: the Outbox invalid-credential startup cases `missing` and +`unreachable` fail after 10.724s and 10.689s respectively; `malformed` and +`wrong-user` pass. Its retained log SHA-256 is +`29f35393c2623f414dd45a1aa99c2eaecec3e33ce8775e3efe1f28c90b885ca1`. +The sanitized result lacks the original exception and failure-location detail. +`owned_completion_missing` follows the test failure and cannot establish its +cause. The failed whole attempt does not qualify. + +The fixture still enables the default outbound OTLP collector although this +Outbox proof owns PostgreSQL and its captured logger, not a collector. +Separately, its ten-second `WaitAsync` can expire while the actual +`WebApplicationFactory` startup task is still running; await-using disposal then +has no startup-completion witness. These are verified fixture defects. The +hosted exception/stack is unavailable, so neither is claimed as the proven +cause of that particular hosted failure. + +Only this test factory disables its unowned exporter endpoint. The startup +task is retained and actually observed before either await-using owner +disposes. The ten-second passing bound and credential/secret assertions remain; +elapsed time is never a startup-completion witness. An uncooperative startup +can keep the failed test waiting until the outer owner stops the process; +that path cannot qualify cleanup. Production telemetry and Outbox behavior do +not change. + +A private owned loopback collector reproduces the same two failed variants +against the baseline: each exceeds ten seconds while the other two pass. +With the corrected factory all four pass and the listener receives zero +connections. A separate twelve-second startup injection makes exactly the +`missing` case fail its original ten-second assertion. All four factory-disposal +observations show actual startup completion with the join present; removing +only that join produces one disposal while startup remains pending. Both +counterparts finish naturally, join their process groups/listener and confirm +both exact owned containers absent. The expected failing counterparts +are diagnostic controls, not successful production qualification. + +The finite result/completion observations use the test's output helper: a +prototype using `Console` was absent from the real adapter result and is not +claimed as evidence. The real VSTest failure decodes as +`timeout/pending` followed by `refused/faulted`; the abandoned-task counterpart +is rejected because its completion is still pending. No raw exception, provider +message, credential or arbitrary test output is exported. Only the four exact +startup cases in the integration assembly can receive this detail; unknown, +duplicate, malformed or oversized observations produce no detail. + +The final factory's independently discovered nineteen-case Outbox class passes +without skips in 31.251s after a zero-warning Release build. Its retained TRX +SHA-256 is `649cafcb99e57a347502d05daf1203c8cd40b5d13527f3cc70f593e90cefb5fc`; +all exact discovered names match the passed results. The held collector sees +zero connections and all owned cleanup checks complete naturally. The actual +joined-timeout adapter trace has SHA-256 +`403b33ecd0c82ec578e2877a3fdfc577ca505ab051835d7f3a532b5d1f540989`; +the abandoned-task trace has +`cf5c55782733fba8b56318ca13eb5bfe9cfaa89f532db48f9761b6411f3ba587`. +These private trace identities support the finite projection and ownership +counterparts, not an assertion that arbitrary trace contents are publishable. + +#### P02b-6 aggregate producer-state refusal attribution (2026-10-22) + +The same `39789942868` attempt's backend aggregate `119869461632` refuses +earlier than the three producer gates, at `producer_not_successful`. Its log +SHA-256 is +`a40a0f102d86f3b710da1a1dd28d19b17dc7d857e8ac2dd01e07245672cbab68`. +Later API reads show base and all six Architecture jobs successful. The +original aggregate response is unavailable: the original owner/state and any +projection delay remain unknown. The integration producer's actual failed test +and this independent backend refusal must not be conflated. + +The existing check now reports a source-owned producer key plus closed +status/conclusion words on stderr before the unchanged refusal. Unknown or +structured API values become `other`. Successful producer checks remain silent; +identity checks, the nonzero refusal, complete-current-attempt requirements and +all deadlines remain unchanged. No polling, retry or union of snapshots is +introduced. The offline control plants 126 owner/state combinations across +both aggregates and verifies finite output, canary exclusion and unchanged +failure. Fresh independent review rounds and complete final-source hosted A/B +remain required for these corrections. + +Local validation passes 63 native-launcher offline controls and the combined +62 shard/aggregate controls without skips. The extra standalone aggregate run +passes its 21 controls. Scoped .NET formatting verification and diff hygiene +pass. An initial unittest-discovery command finds zero hyphenated scripts and +is not counted; the actual explicit owner entry points above provide the +reported populations. An initial formatter invocation names a nonexistent +`.sln` and is likewise superseded by the successful actual-project invocation. + +##### Outbox/producer diagnostic correction review round 1 + +Two fresh independent reviewers (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspect `95edb219..8231d171` +and approve without findings. The correctness reviewer runs the three focused +Outbox parser/protocol controls, all 21 aggregate controls and 56 additional +parser boundary/refusal assertions. The evidence reviewer independently runs +all 63 launcher controls, the combined 62 shard/aggregate controls and the +standalone 21 aggregate controls. Both check exact baseline/final source and +all six named receipt identities, full-class discovery/TRX equality, actual +adapter projections and retained natural cleanup observations. No reviewer +runs .NET, Node, a provider or Docker. + +Both distinguish the original unknown hosted exception/API state from the +verified local mechanisms; neither treats a later successful snapshot or +component as whole-attempt qualification. The same failed attempt's integration +aggregate log (`119872787733`) independently retains +`producer_not_successful`, SHA-256 +`efd26c774659250373774d9400b9a3f169e9fe3ea8ffd778fafb102c68ed8fdc`. +It does not restore the unavailable original backend API observation. Production +behavior, passing deadlines, retry/identity policy and case populations remain +unchanged. A second fresh independent pair and final-source full A/B remain +required. + +##### Outbox/producer diagnostic correction review round 2 + +A different fresh pair (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspects `95edb219..0fa8e641` +and the precise evidence-wording correction below. Both approve without +remaining findings. Each independently runs all 63 launcher and 21 aggregate +controls; the evidence reviewer also runs the combined 62-case owner suite. +The correctness reviewer adds 33 parser boundary/refusal assertions. Both +rehash all six receipts and associated source/TRX/log identities, match the +nineteen discovered class cases and independently decode the joined and +abandoned adapter traces. Both confirm actual disposal observations and +retained natural process/listener/container cleanup checks. + +Root narrows an overstatement from "both exact owned PostgreSQL containers" +to "both exact owned containers": the harness identifies two created IDs and +checks each absent, but its cleanup receipt does not retain both image +identities. Both reviewers inspect and approve that correction. No runtime, +parser or refusal change is needed. Both review rounds are complete; new +same-source complete hosted A/B remains pending and the PR remains draft. + +#### P02b-6 pending aggregate metadata acquisition (2026-10-22) + +Run `39799864449` attempt 1 at `ed223aca` completes all twenty producers +and the other five checks successfully, but both aggregates refuse and the +whole result is 25/27. The integration job `119905589422` observes +`ordinary-7 / in_progress / other`; the backend job `119908475486` observes +`architecture-5 / in_progress / other`. Their retained log SHA-256 values are +`d34c3df792b1520c1176728712a40dc477b346c49aa01968659da652f0bb77c3` +and `f87dc50abfac0415345d2603949241923b69e89a008dd8878f583b84aba1f48d`. +The original conclusions are not known: the closed `other` diagnostic includes +null and arbitrary values and must never itself authorize waiting. + +A retained snapshot also observes integration queued while ordinary-7 is still +in progress. Later metadata reports that producer completed at 15:09:41 UTC; +the aggregate's refusal is logged at 15:09:53 UTC. These observations establish +an incomplete API projection at the aggregate read, not the underlying cache +or propagation mechanism. Later successful producer/gate reads cannot repair +the failed attempt. Independent baseline-verifier analysis of all twenty +immutable producer archives verifies 3,350 non-Docker and 2,571 Docker cases, +5,921 total, with matching complete manifests. The private component-summary +SHA-256 is `8be85e8eb61e84bc2f2f8a37917ce56a3f2729115aedd659dfdfc93894841d02`. +All four Outbox startup cases now pass in 0.804–0.824s. These are component +observations only; whole-attempt qualification remains false. + +ADR-0063 fixes final current-attempt evidence and the five-minute aggregate +ceiling, not an immediate first-read decision. The implementation now gives +jobs metadata its own at-most-thirty-second window, at most sixteen complete +observations and two-second pacing, further bounded by the unchanged original +aggregate deadline. All paginated requests share that one acquisition deadline; +artifact work retains the original deadline and sixty-second upload reserve. +This explicitly extends the earlier diagnostic-only correction, which added +no polling. It introduces no new runner, permission, plan, execution retry, +artifact reuse or acceptance predicate. + +Only an explicitly present null conclusion together with `queued` or +`in_progress` can remain pending. Validate all identities, unique required +owners and all three required gates before deciding to wait. A terminal, +unknown, malformed, missing or duplicate gate/owner, API failure, inconsistent +pagination, timestamp error or completed-producer ceiling violation refuses +immediately, including when an earlier owner is pending. Completed/null and +in-progress/success are not pending. The pending producer's completion time +must be explicitly null; in-progress start times remain well-formed. + +Each pending snapshot is discarded. One independently validated snapshot must +have every required producer and gate completed/success before the unchanged +artifact, outcome, provenance and union checks run. Neither successful subsets +from different reads nor a worker payload can replace that witness. Fixed +`producer_metadata_pending` diagnostics contain only source-owned owner/gate, +protocol and bounded observation number. An immediate clean read stays silent; +exhaustion remains a nonzero failure. Thirty seconds is a bounded acquisition +allocation, not a measured propagation guarantee. Its cost reduces time +available for artifact work; complete new-source hosted A/B must establish fit. + +Offline controls cover each producer and gate in both aggregates settling to +success; earlier pending followed by terminal/malformed evidence; pending then +failure; no cross-snapshot union; absent/non-null/structured conclusions; +API/pagination refusal; per-request/pacing/global deadlines and the sixteen-read +cap. The real aggregate fixture settles a first pending response, then still +downloads every immutable artifact and checks complete output/provenance. +The combined owner/aggregate suite passes 66 controls without skips in 3.080s. +The existing `CI_Test_Shards_Are_Complete_And_Bounded` Asserts records the +obligation; its rule/status/count stays unchanged. Both fresh review rounds +and complete new final-source hosted A/B remain required. + +##### Pending-metadata correction review round 1 + +Two fresh independent reviewers (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) inspect `ed223aca..4834e0c8`. +The evidence reviewer reproduces a timestamp gap: a queued producer with +missing creation time, or a completed peer with missing/reversed creation time, +can wait alongside an earlier pending owner. All required creation timestamps +are now parsed before waiting; completed and in-progress producers require +creation at or before start. Eight planted missing/malformed/ordering subcases +exercise this boundary. The corrected combined suite passes 67 controls in +2.885s without skips; diff hygiene passes. + +Both reviewers approve the inspected correction with no remaining findings. +The evidence reviewer reruns all three original reproductions: each refuses +`api_timestamp_invalid` on its first read with zero sleeps. The correctness +reviewer independently passes four focused controls and verifies that the new +timestamp control rejects the previous implementation with five assertion +failures and no harness errors. Its initial inspection also kills five +in-memory regressions: absent-null check, early pending exit hiding another +failure, accepting a pending snapshot, sliding deadline and seventeen reads. +Both verify existing authority/evidence limits and do not run providers or +broader runtimes. A different second pair and final-source full A/B remain +required. + +##### Pending-metadata correction review round 2 + +A different fresh pair (`gpt-6-astra`, high correctness/security; +`gpt-6.1-sol`, high evidence/governance) independently inspects +`ed223aca..8e437c3c` and approves without findings. Both run all 26 aggregate +controls without skips (2.048s each). The evidence reviewer reruns the three +original timestamp reproductions and confirms first-read refusal with zero +sleeps, verifies both retained log hashes and the component-summary hash, and +preserves the failed 25/27 whole-attempt boundary. It does not rerun the +twenty-archive component analysis or claim whole qualification. + +The correctness reviewer independently exercises the actual paginated API +path: two request budgets decrease from thirty to twenty seconds under one +deadline. The real API subprocess refuses a local fake executable sleeping +two seconds when given a 150ms deadline. Three in-memory regressions are +killed by assertions without harness errors: accepting absent conclusions, +removing creation/start ordering and treating a pending snapshot as success. +Both verify unchanged final artifact/provenance/union requirements, five-minute +ceiling and upload reserve; no broader runtime/provider execution occurs. +Both review rounds are complete. New final-source full A/B and independent +artifact/public/identity validation remain required before the draft is ready. + +#### P02b-6 hosted browser dependency removal (2026-10-23) + +[Run 39805658821](https://github.com/HodeTech/LearnStack/actions/runs/39805658821) +at `dada277b` produced three attempts: + +- **Attempt 1 (A)** fails only `public demo + lighthouse`. The five-minute + `Install pinned browser tools` step times out while Playwright's `--with-deps` + installer downloads fonts from the runner's APT mirror at minutes per package. + The 15-second acquire timeouts do not end a slow transfer that is still moving. +- **Attempt 2 (B)** completes all 27 jobs. +- **Attempt 3 (A)** fails only `backend ordinary-8`, and both required aggregates + fail as its consequence. + `Native_fixture_start_waits_for_previous_actual_cleanup_before_one_same_generation_hint` + is cancelled after 31.38 seconds at `BackgroundJobPositiveSdkTests.NativeHandoff.cs:112`, + while it waits for the provider constructor after the single same-generation + fixture hint. The same case passed in attempt 1 in 3.47 seconds. + +The hang has the same signature as the earlier unexplained constructor-stop +cancellation. The case added by the fixture-hint correction shows it too, so that +correction neither explains nor removes it. About 150 local repetitions all pass, +60 of them under CPU saturation with `DOTNET_PROCESSOR_COUNT=4`. Its cause remains +unknown, and this entry changes nothing about it. + +The step now installs only Playwright's pinned Chromium build. In attempt 1 the +dependency installer added nine font packages (CJK, Thai, Unifont and X fonts) +and upgraded eight packages that were already installed. Every shared library +Chromium needs was already present on the hosted image. No public-demo check +depends on system fonts: Lighthouse's `font-display-insight` audits web fonts. +The temporary APT fragment, its readback and the architecture check are removed +with the installer. Local developer instructions keep `--with-deps`. + +`public-demo-ci.test.ts` executes the actual step against command stubs: + +- A successful run records exactly the two pnpm calls. +- Any `sudo` or APT invocation fails the step. +- Both failure exits are preserved. + +Against the previous workflow, the success case and the browser-failure case +fail. All 17 cases pass, and web lint and typecheck pass. + +On 2026-10-23 the maintainer decided that PR #35 qualifies with one complete +green assignment. [ADR-0063](../decisions/0063-complete-bounded-ci-test-shards.md) +requires both variants only for plan, algorithm or fixture-lifetime changes. +This decision replaces the final-source A/B requirement stated in the entries above. + +## Status archive + +The Status block the phase document carried until 2026-10-22, kept verbatim. Its +in-document links were retargeted to whichever file now holds their target. The +phase document's current Status block replaces it; nothing below is current. + +**Current status — 2026-10-22.** P02b-0 through P02b-5 are complete. +P02b-1, P02b-2 and P02b-3 are merged through PRs #29, #30 and #31; +their dated merge closeouts below retain final verification. +**P02b-4 is complete and merged** through +[PR #32](https://github.com/HodeTech/LearnStack/pull/32) on 2026-10-19. +Its [merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records the final +source, identical squash-merge tree, both complete hosted assignments and current +evidence availability. All nine runtime steps, all three ADR-0063 CI steps and +verified correction bundles completed their required independent review rounds. +Accepted ADR-0047/0058/0059/0060/0061 govern the delivered job runtime; +ADR-0062/0063 govern the delivered bounded CI ownership and partitioning. +Production business and recurrence definitions remain empty. + +**P02b-5 decision pass Accepted — 2026-10-19.** The maintainer approved the +revised [decision package](#p02b-5-decision-package-2026-10-19) and +[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md). G10, G11, +G12's BFF-client choice, G14 and G20 are Accepted. Five implementation steps are +authorized; [Step 1](#p02b-5-step-1--token-foundation-2026-10-19) completes the +dated disclosures and isolated token foundation after both independent review +rounds. Steps 2–3 complete the real read-only subject and attributed admission +after both independent reviews. [Step 4](#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) +installs the complete HTTP boundary after both review rounds. +[Step 5](#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) +completes the authority census, carrier reconciliation and both independent review +rounds with verified corrections. **P02b-5 is complete and merged** through +[PR #33](https://github.com/HodeTech/LearnStack/pull/33) on 2026-10-20. Its +[merge closeout](#p02b-5-merge-and-closeout-2026-10-20) owns final-source CI, +unchanged-plan A/B qualification and identical merge trees. +**P02b-6 decision pass is Accepted — 2026-10-21.** The maintainer approved the +[package](#p02b-6-decision-package-2026-10-20) at `6d75e532` and its four-step +implementation plan. G12's realm/reconciliation/callback choices and G13's +issuance-lifetime part are Accepted; G13's session part stays Open for P02b-7. +The dedicated issuance record, +[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md), is +separately Accepted — 2026-10-21; it changes no runtime or session policy. +P02b-6's four implementation steps and local reviews are complete; the +[Step 4 record](#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) +owns local qualification and correction receipts. ADR-0068's three correction +steps and both independent review rounds are complete locally; their +[qualification record](#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) +owns exact hosted assignments, retained failures and evidence limits. +**P02b-6 implementation is merged** through +[PR #34](https://github.com/HodeTech/LearnStack/pull/34) on 2026-10-22. +The [closed-PR CI correction](#p02b-6-closed-pr-ci-rerun-correction-2026-10-22) +owns the subsequent rerun failure, bounded workflow fix and qualification scope. +P02b-7 BFF sessions and +P02b-8 enforcement/erasure inventory remain pending; Phase 02b remains in +progress. Earlier dated delivery +and failed-run receipts keep their as-of state. + +**P02b-0 complete — 2026-10-12.** Phase 02d is complete and merged through PR #28; +its [merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) +records the verified exit. The +[entry verification](#p02b-0-entry-verification-2026-10-12) reconciles the code, +corpus and Hub premises. P02b-1's +[decision package](#p02b-1-decision-package-2026-10-12) and ADR-0057 are +Accepted — 2026-10-12. G2, G3 derivation, G5 stored identities, G6 producer/common +ownership, G18 payload and G19 flow are Accepted; remaining gate parts stay open. +The four producer implementation steps are authorized. Step 1 lifecycle work is +implemented; both independent review rounds passed. The +[Step 1 record](#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) owns +verification. Step 2 implements immediate enqueue; its +[record](#p02b-1-step-2--immediate-outbox-production-2026-10-12) owns verification +and both completed review rounds. Step 3 implements collection and the publisher; +its [record](#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) +records passing verification and both completed review rounds. Step 4 adds +production-census guards and catalogue enforcement; its +[record](#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) records full +backend verification and both completed review rounds. **P02b-1 is complete and +merged** through [PR #29](https://github.com/HodeTech/LearnStack/pull/29) on +2026-10-12. The [merge closeout](#p02b-1-merge-and-closeout-2026-10-12) owns final +verification. The P02b-2 merge closeout below owns final dispatcher verification. + +**P02b-2 decision pass — 2026-10-12.** The +[decision package](#p02b-2-decision-package-2026-10-12) and +[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md) are Accepted. +The four implementation steps are authorized on development. Step 1 is complete; +its [record](#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) owns +delivery evidence and both completed review rounds. Step 2 implements durable +transitions and terminal audit; both independent review rounds pass. Step 3 +implements hosted lifecycle and observation; its +[record](#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) owns +verification and both completed review rounds. Step 4 enforcement and local +closeout are complete; all four steps completed both independent review rounds. +The [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns final verification. +P02b-3 was pending at that decision pass; its current implementation and review +status is recorded in [Step 6](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13). + +**Phase 02d handoff — 2026-10-11.** P02b-0 re-verifies the delivered `/api/v1` +public contracts, native HTTPS on retained `*.learnstack.local` seed hosts, +manual hosts/trust setup and the shared private hop-secret source. ADR-0053/0054 +supply visitor and peer admission; ADR-0055 supplies one middleware-owned site +bootstrap per native request: two API calls per normal product document, one per +fixed status document and three for a followed missing detail. HEAD, RSC and +prefetch retain their separately proved accounting. Seed authoring distinguishes +tenant-wide rows from default- and sibling-organization rows; typed settings remain +uncached. Anonymous public reads retain no cookies or forwarded credentials. +The [Phase 02d delivery record](phase-02d-walking-skeleton.md) +owns verification and the CI/phase-exit state. G12/G14 re-verify these premises +before adding BFF/session behavior; auth routes may not shadow enabled +`/{locale}/courses...` paths. This handoff accepts no Phase 02b auth or BFF gate. + +**Review follow-up — 2026-10-20.** [P02b-5 remediation](#p02b-5-external-review-remediation-2026-10-20) +retains the verified fixes and Accepted ADR-0065's implementation/local proofs; +the merge closeout above owns final-source qualification. diff --git a/docs/roadmap/phase-02b-events-auth.md b/docs/roadmap/phase-02b-events-auth.md index 99ee6915..fb09b52a 100644 --- a/docs/roadmap/phase-02b-events-auth.md +++ b/docs/roadmap/phase-02b-events-auth.md @@ -1,107 +1,30 @@ # Phase 02b: Events, Background Jobs, Identity, and Session -**Current status — 2026-10-22.** P02b-0 through P02b-5 are complete. -P02b-1, P02b-2 and P02b-3 are merged through PRs #29, #30 and #31; -their dated merge closeouts below retain final verification. -**P02b-4 is complete and merged** through -[PR #32](https://github.com/HodeTech/LearnStack/pull/32) on 2026-10-19. -Its [merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records the final -source, identical squash-merge tree, both complete hosted assignments and current -evidence availability. All nine runtime steps, all three ADR-0063 CI steps and -verified correction bundles completed their required independent review rounds. -Accepted ADR-0047/0058/0059/0060/0061 govern the delivered job runtime; -ADR-0062/0063 govern the delivered bounded CI ownership and partitioning. -Production business and recurrence definitions remain empty. - -**P02b-5 decision pass Accepted — 2026-10-19.** The maintainer approved the -revised [decision package](#p02b-5-decision-package-2026-10-19) and -[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md). G10, G11, -G12's BFF-client choice, G14 and G20 are Accepted. Five implementation steps are -authorized; [Step 1](#p02b-5-step-1--token-foundation-2026-10-19) completes the -dated disclosures and isolated token foundation after both independent review -rounds. Steps 2–3 complete the real read-only subject and attributed admission -after both independent reviews. [Step 4](#p02b-5-step-4--atomic-http-activation-and-contracts-2026-10-19) -installs the complete HTTP boundary after both review rounds. -[Step 5](#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) -completes the authority census, carrier reconciliation and both independent review -rounds with verified corrections. **P02b-5 is complete and merged** through -[PR #33](https://github.com/HodeTech/LearnStack/pull/33) on 2026-10-20. Its -[merge closeout](#p02b-5-merge-and-closeout-2026-10-20) owns final-source CI, -unchanged-plan A/B qualification and identical merge trees. -**P02b-6 decision pass is Accepted — 2026-10-21.** The maintainer approved the -[package](#p02b-6-decision-package-2026-10-20) at `6d75e532` and its four-step -implementation plan. G12's realm/reconciliation/callback choices and G13's -issuance-lifetime part are Accepted; G13's session part stays Open for P02b-7. -The dedicated issuance record, -[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md), is -separately Accepted — 2026-10-21; it changes no runtime or session policy. -P02b-6's four implementation steps and local reviews are complete; the -[Step 4 record](#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) -owns local qualification and correction receipts. ADR-0068's three correction -steps and both independent review rounds are complete locally; their -[qualification record](#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) -owns exact hosted assignments, retained failures and evidence limits. Current CI -failure investigation and corrected-source qualification remain open. -P02b-7 BFF sessions and -P02b-8 enforcement/erasure inventory remain pending; Phase 02b remains in -progress. Earlier dated delivery -and failed-run receipts keep their as-of state. - -**P02b-0 complete — 2026-10-12.** Phase 02d is complete and merged through PR #28; -its [merge closeout](phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) -records the verified exit. The -[entry verification](#p02b-0-entry-verification-2026-10-12) reconciles the code, -corpus and Hub premises. P02b-1's -[decision package](#p02b-1-decision-package-2026-10-12) and ADR-0057 are -Accepted — 2026-10-12. G2, G3 derivation, G5 stored identities, G6 producer/common -ownership, G18 payload and G19 flow are Accepted; remaining gate parts stay open. -The four producer implementation steps are authorized. Step 1 lifecycle work is -implemented; both independent review rounds passed. The -[Step 1 record](#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) owns -verification. Step 2 implements immediate enqueue; its -[record](#p02b-1-step-2--immediate-outbox-production-2026-10-12) owns verification -and both completed review rounds. Step 3 implements collection and the publisher; -its [record](#p02b-1-step-3--domain-completion-and-provisioning-publisher-2026-10-12) -records passing verification and both completed review rounds. Step 4 adds -production-census guards and catalogue enforcement; its -[record](#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) records full -backend verification and both completed review rounds. **P02b-1 is complete and -merged** through [PR #29](https://github.com/HodeTech/LearnStack/pull/29) on -2026-10-12. The [merge closeout](#p02b-1-merge-and-closeout-2026-10-12) owns final -verification. The P02b-2 merge closeout below owns final dispatcher verification. - -**P02b-2 decision pass — 2026-10-12.** The -[decision package](#p02b-2-decision-package-2026-10-12) and -[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md) are Accepted. -The four implementation steps are authorized on development. Step 1 is complete; -its [record](#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12) owns -delivery evidence and both completed review rounds. Step 2 implements durable -transitions and terminal audit; both independent review rounds pass. Step 3 -implements hosted lifecycle and observation; its -[record](#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12) owns -verification and both completed review rounds. Step 4 enforcement and local -closeout are complete; all four steps completed both independent review rounds. -The [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns final verification. -P02b-3 was pending at that decision pass; its current implementation and review -status is recorded in [Step 6](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13). - -**Phase 02d handoff — 2026-10-11.** P02b-0 re-verifies the delivered `/api/v1` -public contracts, native HTTPS on retained `*.learnstack.local` seed hosts, -manual hosts/trust setup and the shared private hop-secret source. ADR-0053/0054 -supply visitor and peer admission; ADR-0055 supplies one middleware-owned site -bootstrap per native request: two API calls per normal product document, one per -fixed status document and three for a followed missing detail. HEAD, RSC and -prefetch retain their separately proved accounting. Seed authoring distinguishes -tenant-wide rows from default- and sibling-organization rows; typed settings remain -uncached. Anonymous public reads retain no cookies or forwarded credentials. -The [Phase 02d delivery record](phase-02d-walking-skeleton.md) -owns verification and the CI/phase-exit state. G12/G14 re-verify these premises -before adding BFF/session behavior; auth routes may not shadow enabled -`/{locale}/courses...` paths. This handoff accepts no Phase 02b auth or BFF gate. - -**Review follow-up — 2026-10-20.** [P02b-5 remediation](#p02b-5-external-review-remediation-2026-10-20) -retains the verified fixes and Accepted ADR-0065's implementation/local proofs; -the merge closeout above owns final-source qualification. +> **Status (2026-10-22).** Phase 02b is **in progress**. P02b-0 through P02b-5 are +> complete, and P02b-1–5 are merged through PRs #29–#33. P02b-6's implementation is +> merged through [PR #34](https://github.com/HodeTech/LearnStack/pull/34); its +> post-merge CI corrections continue on `development`, and their records own the +> remaining qualification. P02b-7 and P02b-8 are pending; G13's session part, G16 +> and G18's erasure inventory stay Open. +> +> This document is the plan. Every dated decision package, step record, review +> round, correction and merge closeout lives in the [delivery log](phase-02b-delivery-log.md), split out +> on 2026-10-22 under +> [ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md). An Accepted +> decision package there is normative; the [decision register](#the-decision-register) +> links each answer. +> +> | Packet | Title | State | +> |---|---|---| +> | P02b-0 | Phase entry | ✅ complete — 2026-10-12; [entry verification](phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) | +> | P02b-1 | Producer | ✅ complete and merged — PR #29, 2026-10-12; [merge closeout](phase-02b-delivery-log.md#p02b-1-merge-and-closeout-2026-10-12) | +> | P02b-2 | Dispatcher | ✅ complete and merged — PR #30, 2026-10-13; [merge closeout](phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) | +> | P02b-3 | Consumer | ✅ complete and merged — PR #31, 2026-10-15; [merge closeout](phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) | +> | P02b-4 | Background jobs | ✅ complete and merged — PR #32, 2026-10-19; [merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) | +> | P02b-5 | API authentication | ✅ complete and merged — PR #33, 2026-10-20; [merge closeout](phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) | +> | P02b-6 | Realm and seed | Implementation merged — PR #34, 2026-10-22; post-merge CI corrections in progress; [records](phase-02b-delivery-log.md#p02b-6--realm-and-seed) | +> | P02b-7 | BFF session | Pending — G13's session part and P02b-6 | +> | P02b-8 | Exit enforcement | Pending — G16 and G18's erasure inventory | ## Goal @@ -154,15 +77,12 @@ keeps the phase from re-deciding settled questions or repairing repaired defects [ADR-0044](../decisions/0044-audit-write-path.md). This phase adds the entry points it does not yet cover. -At the [P02b-0 entry audit](#p02b-0-entry-verification-2026-10-12), `IOutbox` -and step 7's implementation were absent. P02b-1 Step 2 now supplies immediate -enqueue and the enrollment/invariant guard. P02b-2 Step 3 implements the -API-host `OutboxProcessor` BackgroundService, with both independent review -rounds complete. P02b-3 delivers `IInboxGuard` and `inbox_messages` as shared -transport infrastructure under ADR-0046. P02b-4 delivers guarded Hangfire -storage, worker activation and all nine runtime steps; its -[merge closeout](#p02b-4-merge-and-closeout-2026-10-19) owns final verification. -The realm's protocol mappers belong to P02b-6. Packet 5's earlier `IInboxGuard` +At the [P02b-0 entry audit](phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12), +`IOutbox` and step 7's implementation were absent. P02b-1 supplies immediate +enqueue and the enrollment/invariant guard; P02b-2 the API-host `OutboxProcessor` +BackgroundService; P02b-3 `IInboxGuard` and `inbox_messages` as shared transport +infrastructure under ADR-0046; P02b-4 guarded Hangfire storage and worker +activation; P02b-6 the realm's protocol mappers. Packet 5's earlier `IInboxGuard` references were planned comments, not an interface declaration. ### What this phase is not @@ -297,10 +217,8 @@ Decisions made or referenced in this phase: - [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md) is Accepted with its bounded delivery supersessions and separate additive audit seam. [ADR-0047](../decisions/0047-transactional-background-job-runtime.md) and - [P02b-4's package](#p02b-4-decision-package-2026-10-15) are Accepted — 2026-10-15; - all nine implementation steps are complete and merged; the - [merge closeout](#p02b-4-merge-and-closeout-2026-10-19) owns final-source - qualification and merge verification. + [P02b-4's package](phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15) + are Accepted — 2026-10-15. ## Scope @@ -314,12 +232,12 @@ Accepted, and its catalogue rows registered, before its first line of code. | Packet | Contents | Cannot start until | |---|---|---| | **P02b-0** | Phase entry: every premise the register below cites re-verified against `HEAD` — the code, the corpus, the Hub repository — and the register corrected where Phase 02d moved it. It drafts no record: each gate closes in the decision pass of the first packet it shapes, and each glossary headword this phase needs — `inbox`, outbox lease, dead letter, audit frame, job activator, integration-event consumer — is written in the pass whose gate fixes its meaning | [Phase 02d](phase-02d-walking-skeleton.md) exits | -| **P02b-1** | **Complete and merged — [PR #29 closeout](#p02b-1-merge-and-closeout-2026-10-12).** Producer: `IOutbox`, the `OutboxFlushBehavior` invariant guard, successful-save domain-event collection and owner-only completion, and the first event with its enqueue path | G2, G3 (the key's derivation), G5 (the stored identities), G6, G18 (the payload rule), G19 Accepted | -| **P02b-2** | **Complete and merged — [PR #30 closeout](#p02b-2-merge-and-closeout-2026-10-13).** Dispatcher: the lease migration and grant extension, claim / publish / mark, backoff, the producer terminal state, the credential and its boot guard, the metrics and the health check | G1, G3, G4, G5, G7, G8, G17, G18 (`last_error`) Accepted; P02b-1 | -| **P02b-3** | **Complete and merged — [PR #31 closeout](#p02b-3-merge-and-closeout-2026-10-15).** Consumer: durable acceptance, shared inbox/ledger DDL and `IInboxGuard`, the common per-delivery transaction, both real default subscriptions and Seeder handoff, independent attempts and audited terminal state, targeted internal ledger replay | G1, G6, G7 Accepted; P02b-2 | -| **P02b-4** | **Complete and merged — [PR #32 closeout](#p02b-4-merge-and-closeout-2026-10-19).** Background jobs: accepted H1 transactional/external profiles, confined storage/wakeups, tenant capacity and recurrence/fan-out; all nine implementation steps and their review gates delivered; no production job/recurrence definition | G9 Accepted 2026-10-15; P02b-3 complete | -| **P02b-5** | **Complete and merged — [PR #33 closeout](#p02b-5-merge-and-closeout-2026-10-20).** Five steps and correction reviews complete under Accepted ADR-0064/0065/0066. API authentication: closed JWT profile, ordered reconciliation and attributed rejection recorder, additional subject quota and one physically read-only authenticated endpoint | G10, G11, G12 (the BFF's client), G14, G20 Accepted | -| **P02b-6** | **Implementation and local reviews complete — [Step 4 qualification](#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21).** Realm and seed: shared client scope/mappers, protected user-profile UUIDs agreeing with `SeedData`, safe warm reconciliation, narrow account self-service and real Keycloak/API proofs | G12, G13 (the access-token lifetime's authority) Accepted; P02b-5 | +| **P02b-1** | Producer: `IOutbox`, the `OutboxFlushBehavior` invariant guard, successful-save domain-event collection and owner-only completion, and the first event with its enqueue path | G2, G3 (the key's derivation), G5 (the stored identities), G6, G18 (the payload rule), G19 Accepted | +| **P02b-2** | Dispatcher: the lease migration and grant extension, claim / publish / mark, backoff, the producer terminal state, the credential and its boot guard, the metrics and the health check | G1, G3, G4, G5, G7, G8, G17, G18 (`last_error`) Accepted; P02b-1 | +| **P02b-3** | Consumer: durable acceptance, shared inbox/ledger DDL and `IInboxGuard`, the common per-delivery transaction, both real default subscriptions and Seeder handoff, independent attempts and audited terminal state, targeted internal ledger replay | G1, G6, G7 Accepted; P02b-2 | +| **P02b-4** | Background jobs: accepted H1 transactional/external profiles, confined storage/wakeups, tenant capacity and recurrence/fan-out; no production job/recurrence definition | G9 Accepted 2026-10-15; P02b-3 complete | +| **P02b-5** | API authentication: closed JWT profile, ordered reconciliation and attributed rejection recorder, additional subject quota and one physically read-only authenticated endpoint | G10, G11, G12 (the BFF's client), G14, G20 Accepted | +| **P02b-6** | Realm and seed: shared client scope/mappers, protected user-profile UUIDs agreeing with `SeedData`, safe warm reconciliation, narrow account self-service and real Keycloak/API proofs | G12, G13 (the access-token lifetime's authority) Accepted; P02b-5 | | **P02b-7** | BFF session: Auth.js, the cookie session, single-flight refresh, CSRF, logout, the studio guard, the SDK's bearer attachment | G13 Accepted; P02b-6 | | **P02b-8** | `LS0002`, the carrier reconciliations this phase owes, the re-verification that the behavioural check is still required under the name it reports, and the exit checks | G16, G18 (the erasure inventory) Accepted | @@ -344,17290 +262,751 @@ premise a row cites is re-verified at that pass rather than trusted. | # | Question | Leaning | Vehicle | Blocks | Status | |---|---|---|---|---|---| -| G1 | What is the subscriber's fate when its handler exhausts retries, and what is the inbox table — one shared or per module, keyed `event_id` or `(tenant_id, consumer, event_id)`, claimed by the handler or by the transport? Three arms travel with it: the class of consumer whose effect cannot share the inbox transaction (an external call, the platform-scope erasure handler the Audit spec already carries) and what "effectively once" means for it; whether an event without the organization marker is delivered tenant-wide regardless of the producing request's organization; and whether the inbox entity joins [ADR-0044 § 7](../decisions/0044-audit-write-path.md)'s named audit-capture exclusion list once a delivery declares intents | One shared tenant-owned `inbox_messages` keyed by tenant/stable subscription/event, transport-claimed before construction; a separate delivery ledger owns retries, terminal state and targeted replay; completion shares the business/audit/outbox transaction | **ADR-0046** + a dated **ADR-0006 Amendment** (or an explicit supersession note in ADR-0046 naming Amendment 1's consumer-side paragraph, which fixes the per-module inbox) + a dated **ADR-0010 Amendment**, because its § Idempotency makes two things mandatory that the shared-table leaning changes — the inbox is "the module's **own** inbox table", and the guard is called by the consumer — + the `Integration_Event_Handlers_Use_InboxGuard` assertion re-written in the same record to name whoever ends up owning the call, since a transport-claimed delivery fails a structural rule that looks for the call inside the handler + Database Standards § Inbox + an ADR-0041 erratum beside ADR-0023's minting list | P02b-2 (the record and its amendments: the dispatcher's retry state and a failed delivery's next attempt are one state machine), P02b-3 (Database Standards § Inbox and the ADR-0023 erratum) | Accepted — 2026-10-12; decision/amendments delivered; P02b-3 Steps 1–6 implement subscriber runtime, inbox, defaults and production enforcement; complete and merged; [merge closeout](#p02b-3-merge-and-closeout-2026-10-15) owns final verification | +| G1 | What is the subscriber's fate when its handler exhausts retries, and what is the inbox table — one shared or per module, keyed `event_id` or `(tenant_id, consumer, event_id)`, claimed by the handler or by the transport? Three arms travel with it: the class of consumer whose effect cannot share the inbox transaction (an external call, the platform-scope erasure handler the Audit spec already carries) and what "effectively once" means for it; whether an event without the organization marker is delivered tenant-wide regardless of the producing request's organization; and whether the inbox entity joins [ADR-0044 § 7](../decisions/0044-audit-write-path.md)'s named audit-capture exclusion list once a delivery declares intents | One shared tenant-owned `inbox_messages` keyed by tenant/stable subscription/event, transport-claimed before construction; a separate delivery ledger owns retries, terminal state and targeted replay; completion shares the business/audit/outbox transaction | **ADR-0046** + a dated **ADR-0006 Amendment** (or an explicit supersession note in ADR-0046 naming Amendment 1's consumer-side paragraph, which fixes the per-module inbox) + a dated **ADR-0010 Amendment**, because its § Idempotency makes two things mandatory that the shared-table leaning changes — the inbox is "the module's **own** inbox table", and the guard is called by the consumer — + the `Integration_Event_Handlers_Use_InboxGuard` assertion re-written in the same record to name whoever ends up owning the call, since a transport-claimed delivery fails a structural rule that looks for the call inside the handler + Database Standards § Inbox + an ADR-0041 erratum beside ADR-0023's minting list | P02b-2 (the record and its amendments: the dispatcher's retry state and a failed delivery's next attempt are one state machine), P02b-3 (Database Standards § Inbox and the ADR-0023 erratum) | Accepted — 2026-10-12; decision/amendments delivered; P02b-3 Steps 1–6 implement subscriber runtime, inbox, defaults and production enforcement; complete and merged; [merge closeout](phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification | | G2 | Does `IOutbox.EnqueueAsync` write the row immediately on the ambient transaction, or buffer for `OutboxFlushBehavior` at step 7 — and what is the flush point for the two paths that have no step 7? | Immediate write, with the behavior asserting no buffered message survives the handler | [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) bounded supersession of ADR-0032 Sub-decision 2's step-7 completion role, with a dated supersession disclosure in ADR-0032 under this acceptance; phase-doc + [Events and Outbox § Producer pattern](../architecture/15-event-and-outbox.md#producer-pattern) | P02b-1 | Accepted — immediate enqueue/owner completion | -| G3 | What replaces the unconditional same-key publish-order promise — a scoped bound, or strict per-key head-of-line blocking — and is the key's derivation checkable structurally, given that [§ Ordering](../architecture/15-event-and-outbox.md#ordering) admits an aggregate id or a deliberately declared tenant-wide key and nothing else? | Scope it: no column in `outbox_messages` carries an unconditional per-key guarantee, so the honest bound is one processor, no failure, deterministic eligible selection; no enqueue/commit-order guarantee | Derivation: [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md). Ordering: Accepted ADR-0046 and the P02b-2 package, followed by [§ Ordering](../architecture/15-event-and-outbox.md#ordering) alignment under this acceptance | P02b-1 (whether the key's derivation is checked structurally: the first event declares a key), P02b-2 (the ordering bound) | Derivation and ordering Accepted; scoped ordering runtime [implemented in P02b-2](#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12); complete and merged; [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state | -| G4 | What counts as an attempt, what is `MaxAttempts` bound to, and what marker keeps a terminal row terminal as the clock advances? | Six attempts (one immediate plus the five documented delays) and an explicit terminal column, because a pushed-out `available_after` stops being terminal and never leaves the pending gauge | Accepted ADR-0046 + dated ADR-0006 disclosure under this acceptance; Database Standards § Outbox DDL, index and grant edits | P02b-2 | Accepted — 2026-10-12; producer attempts/terminal state [implemented](#p02b-2-step-2--durable-transitions-and-terminal-audit-2026-10-12) | -| G5 | Does the stored event identity stay the assembly-qualified type name with declared compatibility mappings, and what happens to an unresolvable type, a retired type and an event with no subscriber? And what is the **row's** identity — a surrogate `id` plus an `event_id` column, or `EventId` as the key — given that two documents list an `event_id` the canonical DDL does not have? | Keep the type identity, add a bounded resolver reading through `PayloadJsonOptions` and declared mappings; dead-letter a retired type at once rather than spending its attempt budget; reconcile the row's column list in one direction | Stored identities: [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) bounded supersession of ADR-0032 Sub-decision 12 and the Phase 02b deliverables table in Implementation Notes, with a dated supersession disclosure under this acceptance; Database Standards alignment. ADR-0046 accepts declared resolution, Pending holds and intentional absence; dispatch runtime remains P02b-2 | P02b-1 (the stored type identity and the row's identity, both written at enqueue), P02b-2 (unresolvable, retired and unsubscribed types) | Stored identities and resolution outcomes Accepted; resolver/readiness runtime [implemented](#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12); both real durable subscriptions Active in P02b-3 Step 5 | +| G3 | What replaces the unconditional same-key publish-order promise — a scoped bound, or strict per-key head-of-line blocking — and is the key's derivation checkable structurally, given that [§ Ordering](../architecture/15-event-and-outbox.md#ordering) admits an aggregate id or a deliberately declared tenant-wide key and nothing else? | Scope it: no column in `outbox_messages` carries an unconditional per-key guarantee, so the honest bound is one processor, no failure, deterministic eligible selection; no enqueue/commit-order guarantee | Derivation: [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md). Ordering: Accepted ADR-0046 and the P02b-2 package, followed by [§ Ordering](../architecture/15-event-and-outbox.md#ordering) alignment under this acceptance | P02b-1 (whether the key's derivation is checked structurally: the first event declares a key), P02b-2 (the ordering bound) | Derivation and ordering Accepted; scoped ordering runtime [implemented in P02b-2](phase-02b-delivery-log.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12); complete and merged; [merge closeout](phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state | +| G4 | What counts as an attempt, what is `MaxAttempts` bound to, and what marker keeps a terminal row terminal as the clock advances? | Six attempts (one immediate plus the five documented delays) and an explicit terminal column, because a pushed-out `available_after` stops being terminal and never leaves the pending gauge | Accepted ADR-0046 + dated ADR-0006 disclosure under this acceptance; Database Standards § Outbox DDL, index and grant edits | P02b-2 | Accepted — 2026-10-12; producer attempts/terminal state [implemented](phase-02b-delivery-log.md#p02b-2-step-2--durable-transitions-and-terminal-audit-2026-10-12) | +| G5 | Does the stored event identity stay the assembly-qualified type name with declared compatibility mappings, and what happens to an unresolvable type, a retired type and an event with no subscriber? And what is the **row's** identity — a surrogate `id` plus an `event_id` column, or `EventId` as the key — given that two documents list an `event_id` the canonical DDL does not have? | Keep the type identity, add a bounded resolver reading through `PayloadJsonOptions` and declared mappings; dead-letter a retired type at once rather than spending its attempt budget; reconcile the row's column list in one direction | Stored identities: [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) bounded supersession of ADR-0032 Sub-decision 12 and the Phase 02b deliverables table in Implementation Notes, with a dated supersession disclosure under this acceptance; Database Standards alignment. ADR-0046 accepts declared resolution, Pending holds and intentional absence; dispatch runtime remains P02b-2 | P02b-1 (the stored type identity and the row's identity, both written at enqueue), P02b-2 (unresolvable, retired and unsubscribed types) | Stored identities and resolution outcomes Accepted; resolver/readiness runtime [implemented](phase-02b-delivery-log.md#p02b-2-step-3--hosted-lifecycle-and-observability-2026-10-12); both real durable subscriptions Active in P02b-3 Step 5 | | G6 | When the unit-of-work owner is not an `AuditLogBehavior`, who performs the four owner-side audit acts and enters the outermost audit frame — and does a state-mutating delivery declare its own intents, keyed by handler type? | The transport opens the outermost frame beside its transaction; a delivery declares its own intents and an unregistered handler is refused as an unregistered request is | [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md): bounded ADR-0040 nested-failure supersession; separately enumerated additive UoW read-seam amendment; clarifying ADR-0044/0033 common-owner amendments. G1-dependent production delivery/inbox implementation remains P02b-3 | P02b-1, P02b-3 | Producer/common owner delivered; delivery/inbox contract Accepted; common owner and execution implemented by P02b-3 Steps 2–3 | -| G7 | For a dead-letter transition: what class, what `OperationType`, what slug, on which transaction, in what order against the state change, with what failure posture — and may a second non-MediatR caller reach `IAuditStore.WriteStandaloneAsync`? | MUST `security-event`; producer `platform.outbox.dead_letter` and reserved P3 `platform.delivery.dead_letter`; fenced terminal transition and audit INSERT on the same short transaction through a narrow fifth write seam; failed audit retries terminalization without publication | Accepted ADR-0046 + bounded ADR-0044 audit-grant replacement, separate additive fifth-writer seam amendment and ADR-0033 same-transaction clarification under this acceptance; `DeclareOffPath` registration and Audit Coverage baseline | P02b-2 (the producer dead-letter row its criteria assert), P02b-3 | Accepted — 2026-10-12; producer terminal audit [implemented](#p02b-2-step-2--durable-transitions-and-terminal-audit-2026-10-12); subscriber terminal audit implemented by P02b-3 Step 4; job part Accepted — 2026-10-15 under ADR-0047: `platform.job.dead_letter`, actual-row sixth write and same-transaction MUST audit; job terminal/MUST audit implemented; [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | -| G8 | Does the dispatcher's `BYPASSRLS` use carry a per-invocation `security-event` row, or is it exempt — and on what written terms? | Exempt, on three terms: the bypass is grant-bounded and code-path-confined, dispatch attempts are logged rather than audited, and the dead-letter transitions are the audited events | Accepted ADR-0046 explicitly replaces the routine-dispatch coverage rule and bounds the ADR-0003 grant extension; dated disclosures under this acceptance, not an ADR-0041 correction | P02b-2 | Accepted — 2026-10-12; confined dispatcher exception/census [implemented](#p02b-2-step-4--enforcement-and-closeout-2026-10-12); complete and merged; [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state; job/recurrence part Accepted — 2026-10-15 under ADR-0047, conditional on exact grants/censuses, diagnostics, observation and terminal MUST audit; job/recurrence confinement, diagnostics, observation and terminal MUST controls implemented; [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | -| G9 | Which record decides the background-job runtime — its storage under the closed four-role model, the single tenant-context writer, the job frame's transaction owner, the enqueue-site rule *and who may enqueue whose job type*, the retry contract (whose class, slug and posture adopt **G7**'s), the tenantless platform-job class a purge needs, the ADR-0035 classification, the queue grammar, and the package pins with their licence verdict? | One record answering all of it; business execution uses the existing announced request owner through `ISender`, retaining the eight setters; the chosen storage/scheduler authority is separately explicit | **ADR-0047** + a dated **ADR-0003 Amendment** for any schema/role/grant-confinement extension (not merely a new tenant table under the existing policy) + a dated **ADR-0036 Amendment** disclosing the selected context-writer contract; then Standards 05/20. A decision change is not an erratum | P02b-4 | Accepted — 2026-10-15 under ADR-0047 and the nine-step P02b-4 package; bounded prior-ADR Amendments accompany acceptance; runtime and all nineteen canonical obligations implemented; [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | -| G10 | Does the active tenant travel as a scalar `tenant_id` claim, a `memberships` array, or both — and what value does `UserId` hold? | The scalar claim, whose 02b source is an admin-set user attribute; a second UUID-valued `user_id` attribute for the actor, with `sub` staying Keycloak's subject | Phase-doc: [ADR-0036 § What is out of scope](../decisions/0036-tenant-resolution-trusted-inputs.md#what-is-out-of-scope-and-what-is-not) hands the shape to this phase by name. Reconcile `architecture/13`'s array sketch in the same change | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](#p02b-5-decision-package-2026-10-19) | -| G11 | Which [ADR-0036 matrix](../decisions/0036-tenant-resolution-trusted-inputs.md#the-reconciliation-matrix) rows resolve in this phase, given that row 10 consults a reader that denies everyone — and what row covers a signature-valid token carrying no `tenant_id` claim on a tenant host? | Issue a matching organization claim for row 9. Rows 7/10/14 remain membership-dependent refusals until Phase 03; a claimless principal retains public-only HostOnly authority. Row 14 records no tenant audit without a confirmed host tenant, as bounded by ADR-0064 | A dated **ADR-0036** amendment plus errata beside § Staging across packets and the 2026-09-02 erratum, both of which assign row 10 to this phase without noting that its `M covers (T, O)` term is denied until Phase 03 — which groups it with rows 7 and 14 rather than with 6 and 9 | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](#p02b-5-decision-package-2026-10-19) | -| G12 | Which Keycloak client does the BFF exchange the code with, where does sign-in happen across two tenant hosts, and how do the client scope, the mappers and the seed users reach a Keycloak database that has already consumed the import? Native HTTPS on retained `*.learnstack.local` hosts, with manual hosts/trust setup, is delivered by Phase 02d and re-verified by P02b-0 | A confidential BFF client with one redirect URI per seed host, retaining native HTTPS and `Secure` cookies; and an idempotent reconciler shared by `make seed` and `make demo` — a mapper added only to the import reaches no existing workstation | Phase-doc + the realm JSON + `scripts/seed.sh` + `infra/keycloak/README.md`; a new ADR only if the reconciler becomes ADR-0004's `IIdentityProvider` | P02b-0 re-verifies [Phase 02d G32](phase-02d-walking-skeleton.md#the-decision-register), ADR-0053/0054 and ADR-0055; P02b-5 (which client the BFF redeems the code with: the API pins `azp` against it), P02b-6 | Accepted — BFF-client choice, 2026-10-19; realm/reconciliation/callback choices, [2026-10-21 package](#p02b-6-decision-package-2026-10-20) | -| G13 | What is the BFF session — its custody of the refresh token, its store, its idle and absolute lifetimes, its refresh serialisation under concurrent requests, its terminal `invalid_grant` behaviour, its CSRF control and its logout — and which document owns the access-token lifetime? | The `HttpOnly` cookie Security Standards already describes, encrypted by the session adapter, read only by server code, with single-flight refresh and one authority for the TTL | Phase-doc + one reconciled [Security Standards § Authentication](../standards/11-security.md#authentication); [ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) is the dedicated development-issuance authority; a new session ADR is required for a server-side store | P02b-6 (which document owns the access-token lifetime: the realm export and its reconciler write it), P02b-7 | Accepted — issuance-TTL part, [2026-10-21 package](#p02b-6-decision-package-2026-10-20) and separate ADR-0067 acceptance on 2026-10-21; session part Open for P02b-7 | -| G14 | What bounds the request types reachable over HTTP while `AuthorizationBehavior` is `return next()`, and what is the shape of the token-keyed rate-limit stage behind a shared BFF connection? | An enumerated read-only routable set held by a catalogue-registered rule, and a limiter stage after `UseAuthentication` keyed on the validated subject. The early anonymous stage already runs before authentication: P02d-5 delivers 60/min per canonical direct or authenticated-hop visitor IP plus 600/min peer acquisitions/allocations under ADR-0053 and ADR-0054. Exhausted known visitors refuse before peer debit; unknown visitor allocation remains peer-gated. These remain IP/peer quotas, not token quotas; a request they reject never reaches the token stage. Re-verify the [P5 remediation decision](phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) before choosing authenticated accounting, preserving pre-classification protection against unknown-host abuse | Phase-doc + catalogue registration; a dated ADR-0032 Amendment for a deny-by-default step instead | P02b-5 (the token-keyed stage and the early stage's treatment of validated callers); G34's anonymous-hop policy and ADR-0054's bounded accounting replacement are Accepted and delivered in P02d-5 | Accepted — 2026-10-19; [P02b-5 package](#p02b-5-decision-package-2026-10-19) | +| G7 | For a dead-letter transition: what class, what `OperationType`, what slug, on which transaction, in what order against the state change, with what failure posture — and may a second non-MediatR caller reach `IAuditStore.WriteStandaloneAsync`? | MUST `security-event`; producer `platform.outbox.dead_letter` and reserved P3 `platform.delivery.dead_letter`; fenced terminal transition and audit INSERT on the same short transaction through a narrow fifth write seam; failed audit retries terminalization without publication | Accepted ADR-0046 + bounded ADR-0044 audit-grant replacement, separate additive fifth-writer seam amendment and ADR-0033 same-transaction clarification under this acceptance; `DeclareOffPath` registration and Audit Coverage baseline | P02b-2 (the producer dead-letter row its criteria assert), P02b-3 | Accepted — 2026-10-12; producer terminal audit [implemented](phase-02b-delivery-log.md#p02b-2-step-2--durable-transitions-and-terminal-audit-2026-10-12); subscriber terminal audit implemented by P02b-3 Step 4; job part Accepted — 2026-10-15 under ADR-0047: `platform.job.dead_letter`, actual-row sixth write and same-transaction MUST audit; job terminal/MUST audit implemented; [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | +| G8 | Does the dispatcher's `BYPASSRLS` use carry a per-invocation `security-event` row, or is it exempt — and on what written terms? | Exempt, on three terms: the bypass is grant-bounded and code-path-confined, dispatch attempts are logged rather than audited, and the dead-letter transitions are the audited events | Accepted ADR-0046 explicitly replaces the routine-dispatch coverage rule and bounds the ADR-0003 grant extension; dated disclosures under this acceptance, not an ADR-0041 correction | P02b-2 | Accepted — 2026-10-12; confined dispatcher exception/census [implemented](phase-02b-delivery-log.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12); complete and merged; [merge closeout](phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state; job/recurrence part Accepted — 2026-10-15 under ADR-0047, conditional on exact grants/censuses, diagnostics, observation and terminal MUST audit; job/recurrence confinement, diagnostics, observation and terminal MUST controls implemented; [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | +| G9 | Which record decides the background-job runtime — its storage under the closed four-role model, the single tenant-context writer, the job frame's transaction owner, the enqueue-site rule *and who may enqueue whose job type*, the retry contract (whose class, slug and posture adopt **G7**'s), the tenantless platform-job class a purge needs, the ADR-0035 classification, the queue grammar, and the package pins with their licence verdict? | One record answering all of it; business execution uses the existing announced request owner through `ISender`, retaining the eight setters; the chosen storage/scheduler authority is separately explicit | **ADR-0047** + a dated **ADR-0003 Amendment** for any schema/role/grant-confinement extension (not merely a new tenant table under the existing policy) + a dated **ADR-0036 Amendment** disclosing the selected context-writer contract; then Standards 05/20. A decision change is not an erratum | P02b-4 | Accepted — 2026-10-15 under ADR-0047 and the nine-step P02b-4 package; bounded prior-ADR Amendments accompany acceptance; runtime and all nineteen canonical obligations implemented; [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | +| G10 | Does the active tenant travel as a scalar `tenant_id` claim, a `memberships` array, or both — and what value does `UserId` hold? | The scalar claim, whose 02b source is an admin-set user attribute; a second UUID-valued `user_id` attribute for the actor, with `sub` staying Keycloak's subject | Phase-doc: [ADR-0036 § What is out of scope](../decisions/0036-tenant-resolution-trusted-inputs.md#what-is-out-of-scope-and-what-is-not) hands the shape to this phase by name. Reconcile `architecture/13`'s array sketch in the same change | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) | +| G11 | Which [ADR-0036 matrix](../decisions/0036-tenant-resolution-trusted-inputs.md#the-reconciliation-matrix) rows resolve in this phase, given that row 10 consults a reader that denies everyone — and what row covers a signature-valid token carrying no `tenant_id` claim on a tenant host? | Issue a matching organization claim for row 9. Rows 7/10/14 remain membership-dependent refusals until Phase 03; a claimless principal retains public-only HostOnly authority. Row 14 records no tenant audit without a confirmed host tenant, as bounded by ADR-0064 | A dated **ADR-0036** amendment plus errata beside § Staging across packets and the 2026-09-02 erratum, both of which assign row 10 to this phase without noting that its `M covers (T, O)` term is denied until Phase 03 — which groups it with rows 7 and 14 rather than with 6 and 9 | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) | +| G12 | Which Keycloak client does the BFF exchange the code with, where does sign-in happen across two tenant hosts, and how do the client scope, the mappers and the seed users reach a Keycloak database that has already consumed the import? Native HTTPS on retained `*.learnstack.local` hosts, with manual hosts/trust setup, is delivered by Phase 02d and re-verified by P02b-0 | A confidential BFF client with one redirect URI per seed host, retaining native HTTPS and `Secure` cookies; and an idempotent reconciler shared by `make seed` and `make demo` — a mapper added only to the import reaches no existing workstation | Phase-doc + the realm JSON + `scripts/seed.sh` + `infra/keycloak/README.md`; a new ADR only if the reconciler becomes ADR-0004's `IIdentityProvider` | P02b-0 re-verifies [Phase 02d G32](phase-02d-walking-skeleton.md#the-decision-register), ADR-0053/0054 and ADR-0055; P02b-5 (which client the BFF redeems the code with: the API pins `azp` against it), P02b-6 | Accepted — BFF-client choice, 2026-10-19; realm/reconciliation/callback choices, [2026-10-21 package](phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) | +| G13 | What is the BFF session — its custody of the refresh token, its store, its idle and absolute lifetimes, its refresh serialisation under concurrent requests, its terminal `invalid_grant` behaviour, its CSRF control and its logout — and which document owns the access-token lifetime? | The `HttpOnly` cookie Security Standards already describes, encrypted by the session adapter, read only by server code, with single-flight refresh and one authority for the TTL | Phase-doc + one reconciled [Security Standards § Authentication](../standards/11-security.md#authentication); [ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) is the dedicated development-issuance authority; a new session ADR is required for a server-side store | P02b-6 (which document owns the access-token lifetime: the realm export and its reconciler write it), P02b-7 | Accepted — issuance-TTL part, [2026-10-21 package](phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) and separate ADR-0067 acceptance on 2026-10-21; session part Open for P02b-7 | +| G14 | What bounds the request types reachable over HTTP while `AuthorizationBehavior` is `return next()`, and what is the shape of the token-keyed rate-limit stage behind a shared BFF connection? | An enumerated read-only routable set held by a catalogue-registered rule, and a limiter stage after `UseAuthentication` keyed on the validated subject. The early anonymous stage already runs before authentication: P02d-5 delivers 60/min per canonical direct or authenticated-hop visitor IP plus 600/min peer acquisitions/allocations under ADR-0053 and ADR-0054. Exhausted known visitors refuse before peer debit; unknown visitor allocation remains peer-gated. These remain IP/peer quotas, not token quotas; a request they reject never reaches the token stage. Re-verify the [P5 remediation decision](phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) before choosing authenticated accounting, preserving pre-classification protection against unknown-host abuse | Phase-doc + catalogue registration; a dated ADR-0032 Amendment for a deny-by-default step instead | P02b-5 (the token-keyed stage and the early stage's treatment of validated callers); G34's anonymous-hop policy and ADR-0054's bounded accounting replacement are Accepted and delivered in P02d-5 | Accepted — 2026-10-19; [P02b-5 package](phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) | | G15 | What initiates a replay in this phase? | Targeted internal subscriber replay in P02b-3; producer/operator reset and fencing require a separate Phase 03 contract | Phase-doc; the URL space is its own decision record, per ADR-0036 | — (answered in § The consumer side; recorded so the question travels with the deferral) | Accepted — internal subscriber replay implemented by P02b-3 Step 4; operator contract Phase 03 | | G16 | What is `LS0002`'s rule name, which project trees does it run over, what does it inspect, and what escalates it to Error? | The name and scope recorded the way Amendment 1 recorded `LS0001`, with the scope reaching the assemblies that actually handle tokens | A dated **ADR-0032** amendment + a catalogue entry + an `AnalyzerReleases` row | P02b-8 | Open | -| G17 | What are the label sets for the event and job metrics, is the tenant axis permitted, and is it spelled `tenant` or `tenant_id`? | One note in the document that owns metric names, no raw tenant label on a per-event series, and an oldest-eligible-row age metric separate from the pending count | [Observability Standards § Required Metrics](../standards/10-observability.md#required-metrics) edit | P02b-2 (the first series ships there, and a label added afterwards touches every emitter already written) | Event metrics Accepted — 2026-10-12; runtime/guards [implemented](#p02b-2-step-4--enforcement-and-closeout-2026-10-12); complete and merged; [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state; job label/observation contract Accepted — 2026-10-15 under ADR-0047; job instruments/guards implemented; [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | -| G18 | May an integration-event payload or a job argument carry personal data, what may `last_error` contain, and do the four new durable stores enter the erasure scope? | Identifiers only, a sanitized and length-bounded failure descriptor, and the stores named in the erasure inventory | [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) decides the new producer payload/NULL JSON metadata policy and application byte cap; a dated ADR-0038 cross-reference under this acceptance. [Data Protection § Right to Erasure](../architecture/23-data-protection.md#right-to-erasure-right-to-be-forgotten), P02b-8 and Phase 11 retain erasure ownership | P02b-1 (the payload rule: the first payload ships there), P02b-2 (the `last_error` rule and its DDL bound), P02b-8 (the erasure inventory) | Payload and failure descriptors Accepted and implemented; job identifier-only payload/checkpoint and failure-descriptor bounds Accepted — 2026-10-15 under ADR-0047; job payload/checkpoint/failure bounds implemented; [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final qualification; erasure inventory open P02b-8 | +| G17 | What are the label sets for the event and job metrics, is the tenant axis permitted, and is it spelled `tenant` or `tenant_id`? | One note in the document that owns metric names, no raw tenant label on a per-event series, and an oldest-eligible-row age metric separate from the pending count | [Observability Standards § Required Metrics](../standards/10-observability.md#required-metrics) edit | P02b-2 (the first series ships there, and a label added afterwards touches every emitter already written) | Event metrics Accepted — 2026-10-12; runtime/guards [implemented](phase-02b-delivery-log.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12); complete and merged; [merge closeout](phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/review/merge state; job label/observation contract Accepted — 2026-10-15 under ADR-0047; job instruments/guards implemented; [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification and merge | +| G18 | May an integration-event payload or a job argument carry personal data, what may `last_error` contain, and do the four new durable stores enter the erasure scope? | Identifiers only, a sanitized and length-bounded failure descriptor, and the stores named in the erasure inventory | [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) decides the new producer payload/NULL JSON metadata policy and application byte cap; a dated ADR-0038 cross-reference under this acceptance. [Data Protection § Right to Erasure](../architecture/23-data-protection.md#right-to-erasure-right-to-be-forgotten), P02b-8 and Phase 11 retain erasure ownership | P02b-1 (the payload rule: the first payload ships there), P02b-2 (the `last_error` rule and its DDL bound), P02b-8 (the erasure inventory) | Payload and failure descriptors Accepted and implemented; job identifier-only payload/checkpoint and failure-descriptor bounds Accepted — 2026-10-15 under ADR-0047; job payload/checkpoint/failure bounds implemented; [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification; erasure inventory open P02b-8 | | G19 | Where do the sample flow's publisher and consumer live — a fixture pair in the integration assembly, or a real event a shipped module consumes? | A real event between two shipped domain modules, because a test-assembly-only consumer leaves every module-scoped sweep with zero subjects | [Accepted ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) and the P02b-1 package; reconcile Tenancy/Customization/Audit specs under this acceptance. ADR-0046 accepts distinct subscription deduplication and envelope delivery scope; P02b-3 implements the two effects and Seeder handoff. The provisioning publisher must prove enqueue from its transaction announcement while ambient context remains unresolved | P02b-1 | Flow and delivery contract Accepted; subscriptions/semantic Seeder handoff implemented by P02b-3 Step 5 | -| G20 | What does an anonymous request to a **routed non-public** request type on a live tenant host answer — and does the catalogued `Backend_RequiresJwt_OnAllAuthenticatedRoutes` narrow to a surface outside tenant resolution? A second half rides with it: the shipped assertion middleware says that from this phase the refusal code differs by caller, `tenant_mismatch` for an authenticated one and `not_found` for an anonymous one, written by the middleware itself | AccountSite absent credentials give masked `not_found` 404 on tenant/organization/platform hosts. Invalid present credentials on known hosts give 401, including public routes. Rows 8/11/12 and authenticated assertions use `tenant_mismatch`; membership refusals and anonymous assertions use `not_found`; the generic unresolved MediatR gate is unchanged | The dated **ADR-0036** amendment G11 needs + a catalogue edit to that rule's Asserts line | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](#p02b-5-decision-package-2026-10-19) | - -### P02b-0 entry verification (2026-10-12) - -**Complete.** This packet verifies entry premises and corrects current-state -claims. It writes no runtime code, drafts no ADR, accepts no later packet's gate -and introduces no glossary definition ahead of its owning decision pass. - -#### Baseline and inherited enforcement - -The audit used LearnStack `development` at -`3e86041dc32009ae6120c8cbb1533fd5d1325465`, tree -`7aac9df1ed19f0826b042fbd1a303dc92c9ab11a`. That commit reconciles the merged -P02d-7 source with PR #28's squash on `main`; the -[P7 merge closeout](phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) -owns the merge/tree comparison and the completed phase exit. - -The post-merge [CI run 38129121225](https://github.com/HodeTech/LearnStack/actions/runs/38129121225) -completed successfully on `main` at -`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`. A fresh branch-protection API read -on 2026-10-12 confirmed strict up-to-date protection and all seven required -contexts: `backend (build + unit + arch + contract)`, `frontend (typecheck + lint -+ build + test)`, `secret scan (leakwatch)`, `meta (compose + commit hygiene + -link audit)`, `backend integration (Testcontainers)`, `openapi diff`, and -`public demo + lighthouse`. This receipt does not claim a new local full-stack -run or change those settings. - -The Hub checkout was inspected read-only at -`6adf93638e76114eda9c18a5095d0fe3c0fd43b1`; fetched `origin/main` was -`310f718e5f2bad0dfb51e2c307c1ec361dab5952`. The checkout is an ancestor of that -main and their trees are identical: -`c5c380cfee42c6a32923d26d604ada7da2d5dc45`. Its roadmap still freezes P02c-2 -onward pending the documented billing/plan-gate demand and ADR-0034 invariants. -Its P02c-3 waits on LearnStack's durable event path, not the BFF session. -This audit neither opens that track nor changes its contract surface. - -The retained public baseline is native HTTPS, signed ingress, one live -middleware bootstrap and request-local immutable admission. Anonymous public -reads use the host boundary, physical read-only transactions, query filters and -RLS. They do not forward cookies or bearer credentials. The early limiter still -coordinates 60/min canonical visitors and 600/min physical-peer acquisitions/ -allocations; known visitor refusals do not debit that peer budget. P02b-5 must -decide authenticated accounting without weakening this pre-classification bound. - -#### Gate-premise audit - -All twenty register rows were checked against their cited records and the -current implementation. **Verified** below means the premise is confirmed; -it does not mean the proposed answer is Accepted. G15 remains the register's -already-answered replay boundary. Every other row retains its decision vehicle -and first dependent packet above. - -| Gate | Verified current premise and disposition | First decision consumer | -|---|---|---| -| G1 | No `IInboxGuard` declaration, inbox table or durable subscription failure state exists. ADR-0006/0010 still require a per-module, consumer-called inbox. Shared transport ownership remains a proposal requiring the registered record/amendments. | P02b-2 record; P02b-3 DDL | -| G2 | `OutboxFlushBehavior` only calls `next()`; no `IOutbox` exists. Immediate enqueue versus a buffer/flush policy remains undecided, including paths outside MediatR. | P02b-1 | -| G3 | The envelope requires a partition key and the in-process serializer orders invocation per key. The table has no durable sequence or retry ordering guarantee; key derivation and the dispatcher bound remain separate decisions. | P02b-1 derivation; P02b-2 bound | -| G4 | The table has `attempts`, `available_after` and `processed_at`, but no explicit terminal marker or lease columns. Five published retry delays do not themselves settle attempt counting or terminal state. | P02b-2 | -| G5 | Canonical DDL has a surrogate `id` but no `event_id`; ADR-0032 lists both. No durable type resolver or enqueue implementation resolves that mismatch yet. | P02b-1 identities; P02b-2 resolution | -| G6 | The bus restores the accessor and creates handler scopes without opening a transaction or audit frame. Pipeline audit ownership cannot simply be assumed for delivery/domain-event owners. No aggregate currently raises a domain event. | P02b-1; P02b-3 | -| G7 | No producer/subscriber terminal writer exists. The MUST durability contract, off-path caller restriction and transaction atomicity still apply; a multi-transaction alternative needs the vehicle the register names. | P02b-2; P02b-3 | -| G8 | The outbox-admin role and its bounded grants exist; a running dispatcher does not. No Accepted dispatcher-specific audit exemption has been added by this audit. | P02b-2 | -| G9 | No job runtime, package pin, storage, activator or enqueue guard is shipped. The closed four-role and tenant-context-writer contracts remain constraints, not implicit permission for a new runtime. | P02b-4, after P02b-3 | -| G10 | The API has no JwtBearer wiring. Dev users carry slug-valued tenant attributes without explicit protocol mappers; the scalar/array and actor-UUID choices remain open. | P02b-5 | -| G11 | The resolver's claim insertion point is reserved; membership reads still deny everyone. Tenant-only authentication on an organization host and a claimless valid token need explicit outcomes before activation. | P02b-5 | -| G12 | Delivered HTTPS/host/hop/bootstrap behavior is retained. Dev redirects still target localhost HTTP, and `make seed` polls realm readiness without reconciling mappers or warm users. | P02b-5 client; P02b-6 realm | -| G13 | No Auth.js session/helper exists. Access-token lifetimes in the realm and target documents differ; storage, refresh, CSRF and logout remain decisions before their first writes. | P02b-6 TTL; P02b-7 session | -| G14 | `AuthorizationBehavior` remains pass-through. Current HTTP product operations are public reads; anonymous coordinated admission already runs before classification. A protected read census and validated-subject quota do not yet exist. | P02b-5 | -| G15 | Replay remains an internal dispatcher operation for this phase; the operator URL/permission belongs to Phase 03. No recovery endpoint is shipped or authorized here. | Answered; P02b-3 implements | -| G16 | Only `LS0001` is shipped. `LS0002` needs scope, token-source parity, severity/escalation and its release/catalogue entries; it is not a current build-breaking guard. | P02b-8 | -| G17 | Metric carriers disagree on tenant-label spelling and cardinality. Dispatcher heartbeat and oldest-eligible-row age have no emitter yet. Resolve the label set before the first series ships. | P02b-2 | -| G18 | No shipped integration payload/job argument commits this phase to PII. `last_error` is unbounded text today; the future outbox, inbox, subscriber-failure and job stores need the registered erasure inventory. | P02b-1 payload; P02b-2 failure; P02b-8 erasure | -| G19 | No production integration event is published/consumed. Tenancy books three future topics while Audit consumes none. Typed settings are uncached, so a settings-invalidation consumer needs a real effect rather than an artificial cache. Provisioning also has an unresolved ambient context despite its transaction announcement. | P02b-1 | -| G20 | Only public product reads are routed. Existing non-public 404/401 and authenticated assertion-code questions remain unresolved; authentication must not silently choose framework defaults over the matrix. | P02b-5 | - -Implementation evidence was read in the pipeline's `OutboxFlushBehavior`, -`TransactionBehavior` and `AuditLogBehavior`; the platform infrastructure -migration; `InProcessEventBus`, `IntegrationEventEnvelope` and -`EventTenantContext`; API startup, resolver and rate limiter; the Keycloak realm -exports and `scripts/seed.sh`; the uncached `TenantSettingsAccessor`; and the -web middleware, admission/resource loaders and configured caller. Existing -architecture and integration tests were inspected to distinguish accessor -restoration from database announcement and durable delivery. - -#### Reconciliation and next packet - -Current-state corrections in this packet cover the separate seeder executable, -the already-delivered public browser proof, absent API authentication, the -organization-claim choice still owned by G11, logical session-version wording, -future auth examples, absent delivery transactions/audit frames, planned LS0002 -severity and the existing required-check/zero-skip enforcement. Architecture 13 -now labels its identity/session diagrams as targets; Architecture 15 separates -the shipped transport from its future inbox/transaction obligations. Accepted -ADR bodies and historical Phase 02d delivery records remain unchanged. - -Other target sketches that depend on an open gate remain target sketches. -Their packet-owned reconciliation is explicit in the register and deliverables: -P02b-1 updates producer/domain-event/payload carriers and the sample module -specs; P02b-2/3 update delivery, inbox, roles/grants, failure and metric carriers; -P02b-4 owns job storage/runtime carriers; P02b-5–7 own authentication, realm, -session and auth-skill carriers; P02b-8 owns analyzer and erasure closeout. -The Hub's per-module inbox reference remains consistent with the current -Accepted baseline; a different G1 decision must reconcile the cross-repo -reference without thawing the Hub roadmap. - -**Next: P02b-1 decision pass.** Prepare G2, G3's derivation, G5's stored -identities, G6, G18's payload rule and G19 as one reviewable package, including -the domain-event mutation/dispatch boundary and every owning frame's audit -duties. Define the first real cross-module effect before choosing its event. -Any required ADR/amendment must be drafted and approved before implementation. -Only then register its tests, split the implementation into reviewable steps -and begin producer code. P02b-0 requires no new product or architecture choice -from the maintainer. - -#### Validation - -Local Release architecture tests: **203 passed, zero failed, zero skipped**. -ADR lifecycle/disclosure tests: **7 passed**. The changed-document sweep checked -590 relative links and 164 Markdown fragments, with no broken target. Added -prose satisfies the 88-column rule; `git diff --check` is clean. The residual -scan found only CLAUDE.md's unchanged prohibition on local analysis references, -not a new dependency on a private document. No local full integration, browser -or Lighthouse rerun was needed for this documentation-only packet; the exact -post-merge CI receipt above owns that inherited evidence. - -<a id="p02b-1-proposed-decision-package-2026-10-12"></a> - -### P02b-1 decision package (2026-10-12) - -**Accepted — 2026-10-12, @cemil.** The maintainer approves the revised package -and [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md). -This is the producer decision record. The -[Step 1 record](#p02b-1-step-1--shared-execution-lifecycle-2026-10-12) tracks -the first runtime delivery; acceptance alone closes no implementation step. The -[Step 4 record](#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns -final validation, reviews and the packet closeout. -Only the gate parts listed below are Accepted. ADR-0057 supplies the authority -for the coupled producer choices. It explicitly -replaces ADR-0032's step-7 flush/separate event-ID column and ADR-0040's -absorbable-failure rule only for successfully produced work. Other Accepted -rules and historical delivery records stay intact. - -#### Document and code audit - -The decision pass re-read the inherited event, transaction and audit decisions -(ADR-0006/0010/0032/0033/0038/0040/0042/0044), the producer/consumer architecture, -Database/Observability/Audit/Infrastructure standards, the three module specs -and their matrices, the production pipeline and persistence seams, the existing -transport and both composition roots, and the actual provisioning/Seeder paths. -The [entry audit](#p02b-0-entry-verification-2026-10-12) remains the authority for -P02b-0 evidence; it is not rewritten as a P02b-1 delivery claim. - -Two independent read-only audits examined producer/audit boundaries -(GPT-6-astra, xhigh) and real subscriber usefulness/seed compatibility -(GPT-6.1-sol, xhigh). These pre-implementation code facts shape the decision: - -- The outbox DDL already exists; it has `id`, not a separate `event_id`. - `IOutbox` is absent and step 7 is a pass-through. A shared SaveChanges is - neither necessary nor sufficient; the one ambient transaction is the boundary. -- Provisioning deliberately leaves `ITenantContext` unresolved and announces - its new tenant on the transaction. The Seeder has neither a guaranteed - correlation value nor an Activity listener. An HTTP-only enqueue check fails - its first real producer. -- Joined UoW frames are not savepoints. Discarding an inner event queue cannot - undo its saved state or already inserted outbox row. -- Audit entry/reconciliation is currently specific to `AuditLogBehavior`. - A direct delivery needs common ownership rather than pretending a nested - request owns a transaction it only joined. -- Typed settings are uncached; definition reads probe fresh generations. Neither - needs an invented invalidation consumer. Audit already durably records source - changes, so an asynchronous mirror adds no honest useful effect. -- The existing generic defaults are real data with a declared product purpose. - Their automatic installation changes orchestration ownership; it is not a - currently implemented consumer. Current seed verification pins their IDs, - so P02b-3 needs an explicit handoff before enabling delivery races. - -#### Accepted gate answers and implementation boundary - -The ADR owns exact semantics and bounds; this table owns gate timing. Maintainer -approval accepts this package and ADR-0057 together. The decision-only acceptance -commit and Registered catalogue obligations precede runtime code. Acceptance is -not an implementation or passing-test claim. +| G20 | What does an anonymous request to a **routed non-public** request type on a live tenant host answer — and does the catalogued `Backend_RequiresJwt_OnAllAuthenticatedRoutes` narrow to a surface outside tenant resolution? A second half rides with it: the shipped assertion middleware says that from this phase the refusal code differs by caller, `tenant_mismatch` for an authenticated one and `not_found` for an anonymous one, written by the middleware itself | AccountSite absent credentials give masked `not_found` 404 on tenant/organization/platform hosts. Invalid present credentials on known hosts give 401, including public routes. Rows 8/11/12 and authenticated assertions use `tenant_mismatch`; membership refusals and anonymous assertions use `not_found`; the generic unresolved MediatR gate is unchanged | The dated **ADR-0036** amendment G11 needs + a catalogue edit to that rule's Asserts line | P02b-5 | Accepted — 2026-10-19; [P02b-5 package](phase-02b-delivery-log.md#p02b-5-decision-package-2026-10-19) | -| Gate / part | Accepted answer | Acceptance carrier / remaining owner | -|---|---|---| -| G2 | Immediate ambient INSERT; step 7 checks enrollment, while the owner drains domain events before MUST audit/commit | ADR-0057 bounded supersession of ADR-0032 Sub-decision 2; dated supersession disclosure and architecture producer-pattern reconciliation | -| G3 derivation | Explicit aggregate-ID or declared tenant-wide source; canonical key and falsifiable structural/behavioral proof | ADR-0057 and existing `Integration_Event_Declares_PartitionKey`; publish ordering remains P02b-2 | -| G5 stored identities | Assembly-qualified type; `id = EventId`, no extra column; runtime-type JSON with existing frozen options | ADR-0057 bounded supersession of ADR-0032 Sub-decision 12 and the Phase 02b deliverables table in Implementation Notes; dated supersession disclosure and Database Standards alignment; resolver failure policies remain P02b-2 | -| G6 producer/common owner | One collector/drain and reusable audit entry; outbox-only domain reactions; absorbed fail-after-produced-work poisons the unit, including descendant receipts | ADR-0057 bounded ADR-0040 nested-failure supersession; separate additive UoW snapshot-reader amendment and ADR-0044/0033 clarifications; production delivery/inbox atomicity remains P02b-3 after G1 | -| G18 payload | Identifier-only additional fields, inclusive 256 KiB canonical UTF-8 application cap, SQL NULL JSON metadata, no copied personal data or serializer escape | ADR-0057 new producer policy with dated ADR-0038 cross-reference; no outbox-size DDL CHECK claimed; sanitized errors P02b-2, erasure inventory P02b-8 | -| G19 | Completed tenant provisioning produces `TenantCreatedIntegrationEventV1`; two Customization subscribers initialize `card@1` and `plain@1` without overwriting | This package and ADR-0057; module-spec reconciliation at acceptance, publisher P02b-1; G1 must settle independent subscription identities before P02b-3 subscriptions and Seeder handoff | - -The additional nested-refusal protection is deliberate, not a correction to an -old statement: ADR-0040's prior rule was valid when accepted. Its exception and -ordinary event-free refusal semantics survive. No independent scope may bypass -the producer/audit coordinator by opening a raw transaction and calling outbox. - -The acceptance carriers disclose ADR-0057's exact bounded supersessions and -separate additive/clarifying amendments. Current producer guidance in -architecture 15, standards 02/05/10/18/20, module specs and event/review skills -uses owner-only completion and outbox-only domain reactions. The five new -catalogue obligations are Registered, with Implemented counts unchanged. -Consumer target guidance remains under its existing decisions until P02b-2's -G1 pass. Typed settings are uncached and definition reads probe fresh -generations; there is no useful settings-invalidation or Audit-mirror sample. -A later settings cache needs its own measured need and freshness decision. - -#### Four authorized implementation steps - -All work stays on `development`. Each step includes implementation tests and -an explicit commit, then **two independent review rounds with fresh agents**. -Each round covers security/isolation, correctness/lifecycle, architecture/audit, -test falsifiability and carrier accuracy. Use GPT-6-astra xhigh for transaction/ -audit risks and GPT-6.1-sol xhigh for independent structural/test/doc review; -adjust scope rather than weakening critical review. Verify every finding before -fixing and commit confirmed fixes; close both rounds before the next step. - -| Step | Deliverable | Required evidence before its review closeout | -|---|---|---| -| 1 — Shared execution lifecycle | Named `GetTenantContextAnnouncement` reader and immutable transaction-generation snapshot, producer invocation receipts, common audit entry/owner coordinator and guaranteed no-listener trace context; request pipeline retains existing outcomes | Owner/joiner and descendant receipts, event-free absorbed control, no context/setter expansion, same-scope cleanup, existing audit/public read-only regressions, controlled direct non-MediatR owner | -| 2 — Immediate outbox | `IOutbox`, ambient parameterized implementation, identity/metadata/payload admission and step-7 invariant guard; both compositions wired | Real `learnstack_app` INSERT/rollback and cross-tenant refusal, exact persisted envelope/runtime round-trip and SQL NULL JSON metadata, inclusive/multibyte byte-bound proofs, duplicate/oversized/malformed/stale/read-only refusal, no extra connection or publish, MUST-audit failure atomicity | -| 3 — Domain completion and real publisher | Successful-save collection, owner-only FIFO drain, outbox-only translation and completed-provisioning publisher used by API and Seeder | Multi-save/detach/delete, save failure/cancellation, absorbed direct/descendant producer refusal, bounded drain, no replay after rollback/scope reuse, exact one event per successful provision and zero on rollback; response version remains accurate | -| 4 — Enforcement and closeout | Production-subject architecture sweeps with planted controls, end-to-end producer regression, all affected docs/skills/catalogue states reconciled | Release/format and applicable complete backend suites with zero skips; exact test evidence, links/anchors and immutable ADR history; inspect required CI on the eventual PR without claiming unrun results | - -Use the implementation workflow's `add-integration-event`, -`add-mediatr-handler`, `add-integration-test` and `add-architecture-test` skills -for the relevant surfaces, plus `run-tests-locally`, `standards-check`, -`code-review` and `commit-and-pr`. No producer schema change is authorized; -unexpected schema needs reopen planning rather than borrowing P02b-2's lease work. - -No step is complete with review findings or required evidence pending. Partial -step commits are review checkpoints, not packet delivery claims. The final PR -remains for maintainer review; a local pass does not imply merge. - -#### Named handoff to P02b-3 - -P02b-1 is authorized to supply the production publisher and pending rows. -Steps 1–3 implement producer runtime; dispatcher claims and delivery belong to -P02b-2/P02b-3. P02b-3 must deliver both named defaults in -separate one-root subscriber transactions after G1 settles distinct subscription -identities and delivery scope, preserve any authored/lifecycle decision -(including deletion), and prove redelivery and sibling failure recovery. -It also switches built-in seed verification to owner-resolved key/version -identity while preserving warm IDs and exact authored curriculum IDs. Fresh -seed/dispatcher races, repeated-run neutrality, affected audit fixtures and the -seed inventory must be verified together before that packet closes. That packet -also updates `BuiltInCustomizations.cs`'s creator/Seeder/Hub installation remarks -to the delivered subscriber ownership; no consumer is claimed delivered now. - -G1/G3-ordering/G4/G5-resolution/G7/G8/G17 and G18's remaining parts remain open -for their named packets. This approval neither decides inbox ownership nor adds -jobs, authentication, Hub integration, Dapr or another worker process. - -#### Decision-draft review and validation - -Two fresh independent draft reviewers (GPT-6-astra xhigh for runtime/transaction -semantics; GPT-6.1-sol xhigh for corpus/gates/seed scope) approved the proposal -for maintainer review. Neither found a blocking issue. The corpus review's -carrier reminder was verified and incorporated above: Backend Standards 02 and -this phase's domain-event sketch must be reconciled on approval. These are -decision-draft reviews, not the two review rounds each implementation step owes. - -**External-review revision — 2026-10-12.** The maintainer's review is not an -approval. ADR-0057 now classifies each normative supersession, additive seam -amendment and clarification separately; ADR-0041 correction mechanisms do not -authorize the changed decisions. It names the UoW snapshot getter and its -generation/cleanup obligations, closes the JSON metadata channel with SQL NULL, -and identifies the UTF-8 cap as application admission rather than a DDL CHECK. -G1 must settle independent subscription identities before consumer code; -P02b-3 explicitly owns the `BuiltInCustomizations.cs` remarks handoff. The event -version suffix already follows the authoring skill, so no event rename is -needed; its inconsistent input-order example is a named acceptance carrier. -Source-linked drivers, reopening criteria, deferred ownership and the missing -ADR references are also explicit. All P02b-1 gates remain open pending approval. - -Two fresh independent revision reviewers (GPT-6-astra xhigh for governance and -the UoW seam; GPT-6.1-sol xhigh for payload, G1/G19 and carriers) approve the -revised draft for maintainer review. The governance review caught an incorrect -provisioning-amendment attribution; the reference now points to the existing -`IUnitOfWork` provisioning seam, and the fix was rechecked. Neither reviewer -reports a remaining actionable finding. These reviews do not accept the ADR or -count as implementation-step reviews. - -The seven ADR lifecycle-parser tests pass. A local file-and-heading check resolves -all relative links/anchors in the changed draft carriers; it is not a new CI -anchor gate. Accepted ADR files and the P02b-0 entry record remain unchanged. -No backend runtime suite was needed or claimed for this documentation-only -preparation. Maintainer approval remains pending. - -#### Maintainer acceptance — 2026-10-12 - -The maintainer explicitly approved the externally revised ADR-0057 and this -package after the draft reviews recorded above. The pending-approval statements -in that dated draft history describe the earlier review state. This acceptance -closes only the six gate parts in the accepted table. Five canonical proofs are -Registered; no runtime implementation, step review or runtime test is claimed -by this decision record. - -### P02b-1 Step 1 — Shared execution lifecycle (2026-10-12) - -**Step 1 complete; both independent review rounds passed.** Work is -on `development`, following the Accepted four-step package. This is not P02b-1 -completion. No immediate enqueue, successful-save event collector, publisher or -production delivery is claimed by this step. - -- `IUnitOfWork.GetTenantContextAnnouncement` returns an immutable normalized - tenant/organization snapshot with its physical transaction generation. The - PostgreSQL unit captures the values actually sent to SQL, clears authority - before a fresh attempt and on every terminal path, and refuses absent/foreign - transactions. Joins reuse the owner's announcement without retargeting it. -- Scoped `ProducerExecution` records sticky successful-production receipts on - an invocation and every ancestor, separately from pending event counts. The - common transaction coordinator poisons a refusing invocation before resolving - its frame when it carries such a receipt. Ordinary event-free absorbed refusals - retain their previous behavior. Production needs a live writable announcement - and an enrolled owner. A W3C Activity exists even without telemetry listeners. -- `AuditLogBehavior` and `TransactionBehavior` are thin adapters over common - coordinators registered by the pipeline helper in both API and Seeder. Audit - classification precedes deferred direct-handler construction. Capture-owned - audit frames determine outer reconciliation; the UoW owner writes MUST rows - and reports actual commit durability. An independent DI scope has independent - ownership even inside another audit execution's async flow. -- Architecture/audit/security guidance and the glossary describe the common - ownership seams. The closed context-writer set, eight logical announcement - paths, pipeline order and public read-only mode are unchanged. - -**Verification before the implementation commit.** A fresh `CI=true` Release -build succeeds with zero warnings/errors. The focused pipeline unit run passes -83 cases; the complete unit rerun passes 1,713. The focused integration run -passes 125, including all UnitOfWork, -ambient UoW, tenant-context guard, audit pipeline/workflow/capture, public -read-only, provisioning, direct-producer and cross-cutting HTTP cases selected -for this step. Both runs report zero failures and zero skips. The integration -proofs use the application role; privileged connections only prepare fixtures. -The new direct-producer class contributes 13 cases. Its receipts are deliberately -recorded after positively observed writes; automatic INSERT/save-promotion -receipt sites are Step 2/3 obligations, not evidence supplied here. +### Durable outbox dispatch -The snapshot matrix adds 21 cases, including successful SQL values versus a -mutated source context, unresolved provisioning, join/foreign/stale transaction -checks, pooled same-session reuse, failed/cancelled announcement/setup and every -terminal path. The final complete architecture run passes 203 cases with zero -failures/skips. The local carrier check resolves 719 relative links and 153 -Markdown fragments with no broken target; added prose width and -`git diff --check` are clean. -Required CI and final packet counts are not claimed by this local checkpoint. +P02b-1 Steps 2/3 implement `IOutbox`, replace Packet 3's step-7 shell with +an enrollment/invariant guard, and supply owner-side domain collection and the +first publisher. P02b-2 delivers hosted producer dispatch and production-census +enforcement; P02b-3 delivers independent subscriber execution and enforcement. +The table shipped in Packet 6. -#### Step 1 review round 1 +A handler calls `IOutbox.EnqueueAsync` and the row commits on the same **transaction** +as the aggregate change — the ambient one `IUnitOfWork` owns +([ADR-0040](../decisions/0040-ambient-unit-of-work.md)), not a shared `SaveChanges`, a +formulation [ADR-0033](../decisions/0033-audit-durability-model.md) withdrew. [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) +accepts immediate INSERT through that connection/transaction. Step 7 is an +enrollment/invariant guard; the transaction owner drains domain events before +MUST audit and commit. Raw transactions without an enrolled producer frame +cannot enqueue. P02b-3 delivers production acceptance and subscriber execution wiring. -Two fresh independent reviewers examined `b157650..cbab31a`: GPT-6-astra xhigh -for lifecycle/security/audit and GPT-6.1-sol xhigh for proof/architecture/carriers. -Two findings were confirmed: public `BeginInvocation(true)` could assert raw -transaction ownership, and the receipt test did not distinguish all ancestors -from only the immediate parent. An isolated assembly mutant implementing that -weaker propagation still passed all original 13 direct-producer cases. +#### Process topology -Enrollment is now internal to core Application; only the common coordinator -opens frames. Raw announced owners and orphan joiners have explicit refusal -controls. A depth-four invocation case exercises receipt propagation past an -intervening successful ancestor. The UoW XML comment names the common coordinator -and adapter correctly. The reviewers' stale-ancestry observation was reproduced: -an old owner could lend ownership to a later transaction's joiner. The new test -failed on that behavior; inheritance now requires the parent's live announcement -generation to match. The same test passes only after that change, with outer -audit cleanup included. The fresh Release build has zero warnings/errors; -the expanded focused integration run passes 129 cases with zero failures/skips, -including all 17 direct-producer cases. The same isolated weak-propagation mutant -now fails exactly the depth-two-descendant case (1 failed, 16 passed); restoring -the unmodified assembly passes all 17. The complete architecture rerun passes -203 cases with zero failures/skips. The second independent review round remains -pending at this checkpoint. +`OutboxProcessor` is a `BackgroundService` — the shape +[Events and Outbox § OutboxProcessor](../architecture/15-event-and-outbox.md#outboxprocessor-backgroundservice), +ADR-0006 Amendment 1, ADR-0010 and the glossary all specify, with a 200 ms poll no job +schedule expresses. This phase hosts it in `LearnStack.Api`, the only web host. +`LearnStack.Tools.Seeder` is a separate one-shot executable, not a worker host. +P02b-2 Step 3 registers the mandatory hosted processor. The corpus's gateway +route table puts `/admin/hangfire*` on that +host ([API Gateway](../architecture/30-api-gateway.md), route id 3, upstream +`learnstack-api`), and the production image is +[Phase 11](phase-11-production-hardening.md)'s. A second worker host is not a +configuration change — a second process consuming an integration event is ADR-0035's +Dapr trigger verbatim — so it stays with Phase 11. -#### Step 1 review round 2 and closeout +- The phase declares itself **single-instance**. The cache-invalidation deferral above + depends on that premise, and so does the ordering bound in § Ordering. +- `ConnectionStrings:OutboxDispatcher` carries the `learnstack_outbox_admin` credential, + registered as a keyed guarded facade with an internal lazy pool and boot-time + role guard, on + the pattern `Platform_DataSource_Resolved_Only_By_PlatformAdminScope` already holds. + `LearnStack_OutboxAdmin_Role_OnlyUsedBy_OutboxProcessor` is **Implemented** + with P02b-2 Step 4's nonempty credential caller census and passing planted + controls. +- The three carriers that say the credential lives in "the worker host" — + [Database Standards § Database roles](../standards/05-database.md#database-roles), + `architecture/15` and `.env.example` — are derived cells, not a topology decision; + ADR-0003's own role table has no host column. They are corrected to name the API host + in the same change. -Two new independent reviewers examined `b157650..ab2c37d`: GPT-6-astra xhigh -for lifecycle/security/audit and GPT-6.1-sol xhigh for proof/architecture/carriers. -Both approve Step 1 with no Blocker/Major findings. Their independent reruns -pass 59 audit/transaction unit cases, 73 producer/UoW integration cases and -25 persistence architecture cases, with zero failures/skips. These are selected -subsets of the runs above, not additional distinct test totals. +#### The dispatcher -The confirmed minor carrier findings are corrected in this closeout: the -catalogue names coordinator delegation and the outer audit coordinator's clear -ownership; the Security derivation header includes ADR-0057. Canonical rule names, -statuses and counts remain unchanged. The full producer contracts still await -Steps 2–4; this closeout does not claim automatic production receipts, domain -collection or completed P02b-1 delivery. +- **The lease.** A committed normal claim uses a fresh canonical UUID token in + `locked_by`, database-time expiry and one just-in-time row. Every acknowledgement, + failure and terminal transition checks row ID, token and unexpired lease. + Recovery first replaces an expired token with a fresh one; it never publishes + or increments attempts. Stale callbacks cannot clear a later lease. +- **The migration** adds lease/terminal columns and exact status-column grants + together. [Database Standards § Outbox](../standards/05-database.md#outbox) owns + canonical DDL/checks/indexes. Audit-chain INSERT-only privilege enables the + separate fifth audit writer on the same confined transaction. +- **Retry** counts six committed normal claims, including claim-before-crash. + The five delays are 1 s, 5 s, 30 s, 5 min and 1 h. Failure clears the lease; + exhausted or invalid rows request terminalization without another publication. + A failed terminal MUST audit rolls back terminal state and retries only + terminalization. Stored descriptors are closed codes capped at 256 UTF-8 bytes. +- **The SQL form.** Parameterized commands use only the confined data source; + no EF materialization or set-based API owns dispatcher status. Required Pending + subscriptions and their aliases are excluded before claim/payload validation; + intentional absence is the only known-type zero-subscriber acknowledgement. +- **Deadlines.** The accepted bounds are in the P02b-2 package. Ignored + cancellation retains and observes the task, blocks its local partition and + makes health unhealthy; four retained overruns stop new claims. Late work + cannot acknowledge the row. There is no forced task termination promise. -### P02b-1 Step 2 — Immediate outbox production (2026-10-12) +#### Ordering -**Implemented; both independent review rounds complete.** -`IOutbox.EnqueueAsync` persists immediately through the admitted producer's -existing connection and transaction. API and Seeder register `PostgresOutbox`; -no transport, extra connection, commit or schema migration is added. +ADR-0046 accepts deterministic eligible selection by +`(available_after, occurred_at, id)` within one processor. It promises no enqueue, +commit, retry, cross-process or unconditional same-key publish order. Interleaved +transactions and retry deferral are proof subjects. Partition-key derivation +remains the separately delivered ADR-0057 contract; a key alone proves no durable +sequence. See [Ordering](../architecture/15-event-and-outbox.md#ordering). -- Admission checks the unit's identity, live announcement/generation, writable - non-poisoned frame and event tenant before serialization and again immediately - before INSERT. Explicit aggregate or tenant-wide partition declarations must - match the actual canonical GUID key. Organization comes from announced SQL - authority, while the invocation captures the causal actor and full W3C span. -- The row retains producer `EventId`, concrete assembly-qualified type and all - admitted identifier payload properties. Serializer escape shapes are refused; - the complete canonical UTF-8 payload has an inclusive 262,144-byte bound. - JSON metadata is SQL NULL. A duplicate INSERT is an error. -- Only a successful INSERT records a sticky receipt in the invocation and all - ancestors. Step 7 checks live enrollment before and after dispatch; it does - not flush a buffer or dispatch domain events. Event-free unresolved and - public read-only work retain their admission semantics. +#### Domain events collected and dispatched -**Verification before the implementation commit.** The `CI=true` Release build -passes with zero warnings/errors. All 1,757 unit and 203 architecture cases pass -with zero failures/skips. The new real-PostgreSQL outbox class passes all 29 -cases, including immediate visibility, atomic commit/rollback with business and -MUST audit rows, provisioning, stale transaction-object reuse, distinct-unit -refusal and exact canonical UTF-8 boundary values. Initial failures exposed two -fixture assumptions (telemetry subscription and SystemActor identity); both -fixtures were corrected before the passing run. No runtime defect is hidden by -those corrections. Domain-save collection and its first publisher are Step 3; -no dispatch or consumer delivery is claimed here. -The separate existing-flow regression passes 166 integration cases, including -the convergent seeder, audit, provisioning, UoW and public read-only paths, with -zero failures/skips. The carrier audit resolves 1,158 relative links and 216 -Markdown fragments with no broken target; added prose width, formatting and -`git diff --check` are clean. Required CI is not claimed by this local checkpoint. +**Implemented by P02b-1 Step 3 — ADR-0057.** The shared SaveChanges +interceptor stages source events and promotes them only after successful +persistence, in both API and Seeder compositions. Failed/canceled saves promote +nothing. Collection retains source/frame attribution and transaction generation; +repeated saves, detach and delete cannot lose or duplicate a successful event. -#### Step 2 review round 1 +Only the transaction owner drains the collected FIFO queue, at one dispatch site, +before producer invariant checks, MUST audit composition/write and commit. At most +256 domain events belong to one transaction; exceeding this total fails the whole +unit. This is a total count, not recursive cascade support. -Two fresh independent reviewers examined `7541b73..db882e0`: GPT-6-astra xhigh -for transaction/security/envelope correctness and GPT-6.1-sol xhigh for -proof/architecture/carrier integrity. Both approve with no Blocker/Major -findings. The confirmed minor finding was an undated inherited-absence paragraph -still describing `IOutbox` and step 7 as absent. It now distinguishes the P02b-0 -entry baseline from Step 2 delivery; the frozen entry audit is unchanged. +Domain-event handlers translate facts into outbox messages only. They do not +mutate roots, use write stores, send nested requests, raise further events, +publish notifications or invoke external providers. Unexpected enqueue/contract +faults throw and roll back. Expected business decisions stay in commands or later +integration consumers, preserving the returned version and one-root boundary. -The lifecycle reviewer independently passes 79 focused unit and 29 real outbox -integration cases, with zero failures/skips. These overlap the implementation -runs above. The corpus reviewer independently resolves 723 relative links and -165 fragments in changed carriers, with no unresolved target. The second fresh -review round remains pending at this checkpoint. +Each producer invocation keeps a sticky receipt after a successful outbox INSERT +or successful-save promotion, also recorded in every ancestor. A `Result.Fail` +from any frame with that work poisons the shared unit before its UoW frame is +resolved, even when an ancestor absorbs the refusal. Ordinary event-free refusals +retain ADR-0040's semantics. Joiners neither dispatch nor clear the owner's queue; +every terminal path clears transaction-scoped source/collector state exactly once. -#### Step 2 review round 2 and closeout +#### The consumer side -Two new independent reviewers examined `7541b73..37d95bd`: GPT-6-astra xhigh -for runtime/security and GPT-6.1-sol xhigh for proof/architecture/carriers. -Both approve with no Blocker/Major findings. Each independently passes 61 -focused unit, 203 architecture and 29 outbox integration cases, with zero -failures/skips. These overlap earlier runs and are not additive suite totals. +**Delivered by P02b-3 Steps 1–6 under Accepted ADR-0046.** Construction-free manifests +carry stable versioned subscription IDs, compatible aliases and required +Pending/Active readiness. Active publication durably accepts every matching +delivery without running business handlers. The independent executor owns retry +budgets, leases and terminal state in a separate delivery ledger. -The confirmed minor test gap was transport silence: an unsubscribed event would -not expose an accidental publish. A real API-root test now resolves a counting -transport, positively observes the pending and committed row, and proves zero -publishes through enqueue and owner completion. Calling that same resolved -transport afterwards proves the counter works. The fresh Release build has zero -warnings/errors; all 30 outbox cases pass with zero failures/skips. -Step 4 still owns the transitive producer/helper fence against publication, -extra connections and commit ownership, alongside the complete production -censuses. Step 3's save collector, domain causation and publisher remain pending. +One shared `inbox_messages` is keyed by `(tenant_id, subscription_id, event_id)`. +The transport opens the app-role unit of work, announces envelope tenant and +organization, then claims before handler construction. Completed duplicates skip +construction. Business state, completed inbox, produced outbox, MUST audit and +fenced ledger completion share one physical transaction. Rollback removes a new +claim; completed inbox rows never reset. Ordinary delivery uses SystemActor and +refuses privileged work; Phase 03 owns erasure's separate audited boundary. -### P02b-1 Step 3 — Domain completion and provisioning publisher (2026-10-12) +Timeout poisons the business owner, preventing late success. An uncertain COMMIT +is Indeterminate, including the final claim; atomic ledger/inbox state decides +recovery. The bypass scheduler sees only enumerated identity/routing/status +columns, never envelope payload. P02b-3 supplies canonical DDL, exact RLS/grants, +capture exclusions and the ADR-0023 minting correction before runtime. -**Implemented; both independent review rounds complete.** +A poisoned subscription leaves siblings untouched. Its fenced terminal state and +Tenancy-owned `platform.delivery.dead_letter` MUST security-event commit together. +Internal replay resets only that ledger pair and invokes its executor, never +`PublishAsync`. Phase 03 retains producer reset and operator permission/reason, +fencing and surface contracts. Phase 11 retains purge intervals and broker +binding. External effects need subscription/event idempotency or an outbox intent. -- A shared SaveChanges interceptor snapshots only changed sources of its saving - context, then promotes facts after nonzero successful persistence. Failed, - canceled, suppressed and zero-row saves promote nothing. Separate source - retention clears uncollected or detached facts; it cannot promote them on an - unrelated save. Repeat saves do not duplicate successfully promoted facts. -- The transaction owner alone drains the FIFO queue before producer invariants, - MUST audit and commit. Saved facts retain their saving invocation, generation, - W3C span and causal human through child disposal. Translation mints a new - integration identity and records the domain identity as causation. Successful - promotion marks every ancestor; a produced-work refusal poisons before its - frame resolves. Total production is bounded at 256 domain events. -- API and Seeder install the same collector/interceptor. Owner termination and - scope disposal clear source lists, staged/queued facts and promotion state; - later successful transactions in the same DI scope cannot replay facts. -- The tenant's initial default-organization assignment raises - `TenantCreatedDomainEvent`. The final successful provisioning save qualifies - it for outbox-only translation into `TenantCreatedIntegrationEventV1`. - One pending row commits with tenant, default organization/back-reference and - both existing MUST audit rows. No dispatch or default subscriber is delivered; - existing seed orchestration remains unchanged until P02b-3's named handoff. +#### Observability -**Verification before the implementation commit.** The fresh `CI=true` Release -build passes with zero warnings/errors; all 1,764 unit and 203 architecture cases -pass with zero failures/skips. The final focused producer/provisioning integration -run passes 68 cases with zero failures/skips, including both real API/Seeder -roots, exact metadata and successful/failed MUST provisioning. A separate -existing-flow run passes 152 integration cases with zero failures/skips, -covering audit, UoW, public read-only and convergent seed behavior. The focused -post-format unit rerun passes 28 provisioning/domain cases; it overlaps the full -unit total above. +[Observability Standards § Required Metrics](../standards/10-observability.md#required-metrics) +is the sole inventory of names and dimensions. P02b-2 supplies producer duration, +failure, terminal and lease-loss diagnostics, immutable backlog/eligible-age/ +deferred/heartbeat snapshots and registered `outbox` health. No metric has a +tenant label; event-type labels come only from the bounded registry. Required +Pending rows, completed and terminal rows are excluded from normal eligibility. +P02b-3 delivers independent subscriber terminal/dedup signals and minimizes the old +transport diagnostics. Separate producer/subscriber failure signals describe +separate budgets. Health is registered, not mapped; `/healthz` stays liveness and +Phase 11 owns `/readyz` and production alert windows. -The initial focused integration run exposed two fixture defects: EF refused a -duplicate alternate key before SQL, and two fault cases tried to reuse an -irreversibly poisoned UoW. The corrected cases reach the real database uniqueness -failure and verify poisoned-scope refusal; a separate successful-owner case -proves later-generation reuse without replay. The full focused rerun above is -green. These corrections change no runtime policy and conceal no failing case. -Step 4 still owns complete structural enforcement and catalogue promotion; -required CI and packet completion are not claimed at this checkpoint. +### Background jobs -#### Step 3 independent reviews +P02b-4 delivers this scope under Accepted ADR-0047/0058/0059/0060/0061; its +[decision package](phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15) holds the accepted +answers. The pre-acceptance checklist below is historical preparation, not +current authority. -Round 1 reviewed `937e36a..d6fbd85` with separate GPT-6-astra xhigh -runtime/transaction and GPT-6.1-sol xhigh proof/corpus reviewers. Both approved -without a verified actionable finding. The proof reviewer independently reran -28 domain/provisioning integration and 28 focused unit cases with zero -failures/skips. Round 2 used two new agents with the same separate lenses; -both approved, and its proof reviewer independently repeated those same -28 integration and 28 unit cases with zero failures/skips. These focused repeats -overlap the implementation evidence; they are not added to its totals. +**Historical pre-acceptance preparation (not current authority).** -The reviews checked real SQL/save qualification, retained child metadata, -ancestor receipts, FIFO/count bounds, owner/audit atomicity, terminal cleanup, -response versions and both production registrations. No runtime fix was needed. -Complete production censuses and catalogue promotion remain Step 4 work. +No Accepted record selects the general background-job runtime. ADR-0028 selects +Hangfire specifically for future audit maintenance; that narrower decision must +be retained or explicitly superseded, rather than described as absent. **G9** and +**ADR-0047** are the first work item; runtime implementation waits for acceptance. +The record has to close, at minimum: -### P02b-1 Step 4 — Producer enforcement and closeout (2026-10-12) +- **Storage under the closed four-role model.** Infrastructure Stack Standards + prescribes a `hangfire` schema; Database Standards says the database has one schema, + `public`; all four roles are `NOCREATEDB` and none holds `CREATE` on the database, so + no role can create that schema, and every structural Row Level Security sweep reads + `public` only. Each default here breaks a written rule, which is why the storage + decision owes a dated ADR-0003 Amendment for a changed schema/role/grant boundary, + not merely for a tenant table following the existing policy. +- **One writer of `ITenantContextAccessor.Current` on the job path.** ADR-0036 § Rules + names the Hangfire `JobActivator`; `architecture/09` names a `LearnStackJob<TParams>` + base class; the catalogue carries both spellings. The writer allow-list in + `TenantContextConstructionTests` currently names HTTP, bus and delivery-executor + files (two logical entry classes). The job writer is added deliberately, and + whichever competing job spelling loses is retired rather than left in place. +- **Who owns a job frame's transaction and announces `app.tenant_id` on it.** Restoring + the accessor announces no GUC, and a job touching a module `DbContext` therefore + throws. ADR-0040 has exactly two entry points and eight setters, and the set is + closed: the `ISender` shape keeps it at eight, a runner-owned transaction makes it + nine and owes an amendment. +- **The enqueue-site rule.** Enqueuing a job from inside a handler is the dual write the + outbox exists to prevent, and the corpus currently draws it as a sibling of + `IOutbox.EnqueueAsync` off the same handler. `IUnitOfWork` has no post-commit seam. +- **The retry and dead-letter contract**, one taxonomy shared with dispatch and + delivery, with its counter registered in Observability Standards and its audit row + under **G7**. +- **The ADR-0035 classification.** The job *tenant contract* is a one-way door — it is + in ADR-0035's own list of things that touch every job payload — and the runner is + additive. Ship the contract and the port; the classification decides whether the + vendor adapter is gated, and no scheduling port name exists in the corpus to inherit. +- **The queue grammar and job-id convention.** Infrastructure Stack Standards carries a + dotted job-name rule; two ADR bodies spell the same thing with colons, and no document + defines a queue grammar at all — while Phase 08a's dependency table inherits a "queue + policy" from this phase and its own Notifications section says that phase defines "its + queue and its retry policy", a tension the record resolves. Queue names and job ids + are separate concepts and the record distinguishes them. +- **The package pins and the licence verdict** for Self-Hosted redistribution. Nothing + is pinned today. -**Step 4 complete; both independent review rounds passed.** Work remains on -`development`. The packet closeout below records full local verification; -the PR's required checks own fresh CI evidence. PR approval and merge remain -pending. +What this phase ships once that record is Accepted: -- `IntegrationEventContractTests` independently checks the complete production - project/module-layer census, base record/required members, declared partition - sources and identifier-only payloads. Stored-source IL and independently - varied tenant/event/aggregate identifiers exercise key derivation. Invalid - declarations, unrelated/constant keys, hidden members, serialization overrides - and disallowed payload shapes have dirty/clean controls; concrete runtime JSON - round-trips preserve approved identifiers. Unsupported computed partition - derivations fail loudly rather than silently leaving the proof's scope. -- `DomainEventHandlerTests` follows assembly-scoped helpers, inherited/generic - interfaces and generated async/lambda bodies across every production project. - Planted roots/helpers exercise every module layer. Root/write-store mutation, - nested requests, further facts/notifications, connection/UoW access, provider - ports and service location are rejected; clean outbox translation stays clean. - Static IL analysis does not claim arbitrary reflection/dynamic-code coverage; - new provider ports need explicit capability controls. -- `OutboxProducerConventionTests` complements real transaction proofs with - transitive no-new-connection, no-commit and no-publication controls. The - topic-convention census now requires production events and rejects trailing - newlines. Eight producer catalogue rules move to Implemented; delivery/inbox, - dispatcher, jobs and auth rules keep their named later packets. -- Current carriers and event/architecture/review skills distinguish delivered - production from remaining dispatcher/inbox work. ADR-0057's dated Amendment 1 - links delivery without rewriting its Accepted body or prior decision records. +- The runner in its own `LearnStack.Infrastructure.*` assembly, registered at the + composition root, with its storage created on the DDL path ADR-0047 names. +- The tenant-context restoration hook: one writer, its Origin, the system-actor and + causal-actor split, the `Guid.Empty` and `TenantId.PlatformSentinel` refusals, an + `Activity` started from the stamped `traceparent`, and a `finally` that restores the + previous accessor value so the next job on the worker does not inherit it. +- An enqueue-time guard over `tenant_id`, `organization_id?`, a `traceparent`-shaped + `correlation_id` and the causal actor. Job payloads missing any one of them **fail at + enqueue time**, not at activation: the failure is loud and belongs to the caller who + can fix it. The catalogued rule reads "missing `tenant_id` **or** `correlation_id`", + so a payload missing exactly one of them fails too, and the guard checks provenance + rather than mere presence — the platform stamps these values from the resolved + context. +- A behavioural rule that a job runs under its restored tenant. The catalogued + structural rule asserts statement order and is green whether restoration works or not. +- **No job definition and no dashboard route** (§ Explicitly not in this phase). -**Verification checkpoint.** The Release build has zero warnings/errors and the -complete solution's format verification passes. All 1,764 unit, 261 architecture, -four contract and 1,148 integration cases pass: 3,177 total, zero failures/skips. -TRX counters were inspected per assembly; the 59 focused producer-guard cases -overlap the architecture total. The first full integration run had five failures -in two older test setups that called persistence registration without the -application pipeline, leaving the new collector dependency absent. Both fixtures -now install the shared application registration; the complete integration rerun -above passes. No runtime policy was weakened. Review fixes below have their own -verification and supersede affected counts at this checkpoint. +### Identity integration — the `learnstack` realm +The LearnStack identity **domain** (`User`, `Membership`, `Role`, `Permission`, +`Invitation`) lands in [Phase 03](phase-03-identity-admin.md). This phase delivers the +authentication plumbing for the tenant-facing `learnstack` realm, and adds nothing to +the rules its carriers own: +[Identity and Auth § Token Flow](../architecture/13-identity-and-auth.md#token-flow) +owns the OAuth role split, +[Security Standards § Authentication](../standards/11-security.md#authentication) owns +token custody and lifetimes, +[Frontend Architecture Standards § Auth](../standards/07-frontend-architecture.md#auth) +owns the session mechanism, and +[ADR-0036 § Staging across packets](../decisions/0036-tenant-resolution-trusted-inputs.md#staging-across-packets) +stages the wiring into this phase by name. Where this phase disagreed with one of them, +it was the phase that was wrong. -#### Step 4 independent review round 1 +LearnStack does not implement password hashing, password-reset rendering, MFA enrolment, +or refresh-token rotation. Those live in Keycloak; the split is described in +[Identity and Auth](../architecture/13-identity-and-auth.md). -Round 1 reviewed `3473843..b6e3932` with separate GPT-6-astra xhigh -runtime/security and GPT-6.1-sol xhigh proof/corpus reviewers. The runtime review -found one Major structural backstop gap: both guard walks expanded interface -implementations but missed overrides reached through abstract or non-sealed -base-class helpers. No production handler currently uses the escaping path. -Both walks now include derived implementations and have separate dirty/clean -abstract and virtual dispatch controls. Reverting the walk to interface-only -makes two domain-handler controls and one outbox control fail; restored source passes -all 63 focused producer-guard cases and all 265 architecture cases, zero -failures/skips. Release build has zero warnings/errors and changed C# formatting -passes. These four additional architecture cases bring the complete backend -verification to 3,181 cases; unchanged unit/contract/integration evidence is the -full run above, not an additional rerun claim. - -The proof reviewer independently passed 261 architecture and 41 focused unit -cases at the implementation checkpoint. Its one Minor carrier finding is fixed: -the P02b-2 error/lease migration must account for existing P02b-1 producer rows; -its decision pass still owns descriptor handling. Both findings were verified -against source. The fixes were committed in `98c22a8`; the runtime reviewer -independently reran its exact twelve dirty/clean probes and confirmed both -formerly escaping paths are caught while clean paths remain legal. - -#### Step 4 independent review round 2 +- **The authentication wiring ADR-0036 stages here**, and its insertion order: + `UseAuthentication` above tenant resolution so a validated claim exists when the + resolver builds its attempt, `UseAuthorization` below the tenant assertions. Two + insertions, not one block, with an ordering rule and a planted-order companion + registered in the catalogue. The claim signal is populated at the one site the + resolver's comment reserves, from a validated `learnstack`-realm principal only. +- **One JWT authority for `/api/v1/*`**, the `learnstack` realm, with the issuer, the + audience, the algorithm allow-list, the clock skew, `azp`, and the rejection of ID + tokens all pinned. `Api_Registers_Only_The_Tenant_Realm_Authority` is catalogued to + this phase and its own note says the structural half passes while issuer validation is + disabled in configuration — the integration half is the load-bearing one. A + `learnstack-hub` token on a tenant-facing endpoint is refused here, not in + demand-gated Phase 02c. +- **The claim shape and the actor's identity**, under **G10**. The pipeline carries a + `UserId` from this phase on, and the resolver already dereferences one when a tenant + claim arrives with a subject, so the value is load-bearing rather than cosmetic. Phase + 03 owns the durable `sub` → `UserId` mapping; this phase owns where the claim comes + from and must not mint a fresh identifier per login. +- **Which matrix rows go live**, under **G11**. `demo-english` is a tenant-wide host and + `demo-yoga` maps to its default organization, so a tenant-only token on the yoga host + is a row that consults `ITenantMembershipReader` — registered as + `DenyAllTenantMembershipReader` until Phase 03. Whichever way G11 resolves, the + outcome is asserted rather than discovered: a successful Keycloak callback on its own + conceals it. +- **The host/JWT tenant cross-check.** A request whose host-derived tenant disagrees + with its JWT tenant returns 404 — not 403, which would confirm the resource exists — + through the **same** recorder and the **same** operation key Packet 9 shipped, with + `metadata.assertionSource = jwt-claim`, per + [ADR-0036 § Recording a rejected assertion](../decisions/0036-tenant-resolution-trusted-inputs.md#recording-a-rejected-assertion). + Not a second detector. The shipped types cannot carry that metadata yet — the + rejection record has no source, actor or correlation field, the recorder hard-codes a + null actor, and the resolver's refusal path only logs — so those are this phase's + edits. The organization dimension follows G11. The cross-check is a fault detector, + not an authorization control, and not the first isolation layer: Row Level Security + and the query filters precede it. +- **What an anonymous request to a routed endpoint answers**, under **G20**. The + catalogued `Backend_RequiresJwt_OnAllAuthenticatedRoutes` is booked to this phase and + says every endpoint outside the public allow-list answers 401 without a bearer token; + [ADR-0036's matrix](../decisions/0036-tenant-resolution-trusted-inputs.md#the-reconciliation-matrix) + row 2 says a non-`[PublicSurface]` request on a tenant host with no credential answers + 404, byte-identical to an unknown host's. Both cannot hold for the same request, and + the default `UseAuthorization` wiring answers the one the matrix forbids. The same + gate carries the refusal **code** split the shipped assertion middleware assigns to + this phase by name — `tenant_mismatch` for an authenticated caller, `not_found` for an + anonymous one, written by the middleware rather than left to the status-code pages. +- **Absence is not disagreement.** A token with no `tenant_id` claim resolves under the + host-only ceiling by design. What this phase must not do is let that be silent: with + the realm as it stands every token is claimless, so a lost mapper looks exactly like + an anonymous visitor. The claimless-token case on a tenant host has no matrix row at + all, and G11 gives it one. +- **The authenticated tier's bound**, under **G14**. Authentication goes live while + `AuthorizationBehavior` is still `return next()`, so without a bound any tenant user + reaches every routed request type until Phase 03. The token-keyed budgets that + [Security Standards § Rate Limiting](../standards/11-security.md#rate-limiting), + Standards 04 and the shipped limiter's own remarks assign to this phase go live with + authentication — they are also the bound ADR-0036 names for its per-occurrence + mismatch row, so activating that path activates this dependency. +- **Seed users**, under **G12**: tenant users only. Operators are the `learnstack-hub` + population and ADR-0004 Amendment 1 makes the separation a hard invariant — the + `learnstack` realm declares no platform-admin role and should not gain one. The + current dev export has no organization claim. **G11** decides whether this phase + mints one or deliberately refuses the authenticated organization-host case; + "across both organizations" is not yet an accepted promise. +- **Keycloak realm roles.** The realm ships three `tenant-*` roles with full scope on + both clients, so they appear in every token, while roles live in LearnStack and not in + Keycloak. Either they leave the realm or they are declared inert with a rule proving + no LearnStack assembly reads a role claim. A documentation link is not a mitigation + for a leak the realm actively causes. -Two fresh reviewers (GPT-6-astra xhigh for runtime/security; GPT-6.1-sol xhigh -for proof/corpus) reviewed `3473843..98c22a8` and the adjacent producer/audit -lifecycle. Both approve with no additional runtime or guard finding. The runtime -reviewer independently passed all 63 focused architecture cases; the proof -reviewer independently passed all 265 architecture and 59 focused messaging -unit cases, zero failures/skips. These cases overlap the complete run above. -The proof reviewer's only Minor confirms the final carrier sweep: Architecture -15's stale conditional partition-proof wording now describes the delivered -persisted-value proof. +#### Correction: the realm emits no `tenant_id` claim at all -### P02b-1 packet closeout (2026-10-12) +This is an unimplemented prerequisite of this phase's authenticated cross-check. +`infra/keycloak/realms/learnstack.json` stores `tenant_id` as a **user attribute** and +declares **zero protocol mappers**. Keycloak does not put user attributes into tokens +unless a mapper says so. The API also has no JwtBearer registration or +`UseAuthentication` today: it does not validate those tokens or populate the +resolver's reserved claim signal. Current public requests use the delivered +host-only admission, query filters and Row Level Security. Authenticated behavior +must not go live until G10–G12 settle the token and resolution contract. -**Complete on `development`; PR review and merge remain pending.** All four -implementation steps completed their commits, both independent review rounds -and verified fixes. Accepted ADR-0057 governs the delivered scope: +Three changes, and the third is the one that makes the first two take effect: -- Shared producer/audit execution and immutable successful transaction - announcements, preserving ordinary event-free refusals while poisoning - failures after direct or descendant successful production. -- Immediate parameterized outbox INSERT on the existing announced writable - transaction, exact envelope/routing/identifier payload admission and no new - connection, commit or transport publication. -- Successful-save domain collection, bounded owner-only FIFO completion before - MUST audit/commit and one completed-provisioning publisher in API and Seeder. -- Nonempty production censuses with independent dirty/clean and mutation - controls; eight producer catalogue rules are Implemented. Current architecture, - standards, module specs, glossary and skills reflect the delivered boundary. +- An **`oidc-usermodel-attribute-mapper`** on a client scope shared by the API and the + BFF's client, projecting the attribute into the access token and the ID token, typed + as `String`, with an explicit audience mapper beside it. A mapper on the API's client + alone shapes nothing in a token minted for another client, which is the client the BFF + redeems the code with. +- The seeded value changed from the slug `"tenant-a"` to the seed tenant's **UUID**. The + claim is consumed as a `TenantId` — a Vogen value object over `Guid` from + [Phase 02a Packet 6](phase-02a-kernel-tenancy.md) — so a slug cannot be parsed. The + attribute is declared **admin-only** in the realm's user-profile configuration: it + alone raises a request to the host-and-claim authority ceiling, so a + self-service-writable attribute is a privilege-escalation path. +- A **reconciliation mechanism**, under **G12**. Keycloak consumes the realm import + once, at first start, and re-import overwrites nothing that already exists. A change + made only in the import reaches no existing workstation, and a Keycloak database wipe + is not the upgrade path — `make seed` today only polls each realm's discovery endpoint + and never writes to Keycloak. Without this step the token-shape test below is green in + CI on a fresh container while every warm workstation issues claimless tokens. -**Local verification:** Release build has zero warnings/errors; complete solution -format verification and changed-code formatting pass. Per-assembly TRX counters -record 1,764 unit, 265 architecture, four contract and 1,148 integration cases: -**3,181 passed, zero failed/skipped**. Integration includes actual PostgreSQL -`learnstack_app` isolation/atomicity and the existing seed/public-renderer -regressions. Unit/contract/integration ran at the Step 4 implementation -checkpoint; the subsequent proof-only class-dispatch fix added four architecture -cases and reran that complete suite. Focused repeats and deliberately failing -mutation experiments are not added to the passing total. The five corpus checks -and seven ADR lifecycle tests pass. A local sweep of 33 changed Markdown files -checks 2,900 relative links and 700 fragments with no broken target; this is -manual/local validation, not a new CI anchor gate. Added closeout prose satisfies -the 88-column rule and `git diff --check` passes. +The test asserts the shape rather than the configuration file: a token issued by the dev +realm for a seed user carries a `tenant_id` claim that parses to that seed tenant's +`TenantId`, and the realm export's seeded value equals `SeedData`'s literal. A realm +export that loses the mapper fails it. -No frontend production source, OpenAPI contract or schema migration changes. The PR's -seven required checks provide fresh CI evidence, including frontend and the -public demo/Lighthouse lifecycle; local success alone does not claim CI approval -or merge. Existing Accepted ADR changes are insertion-only dated disclosures; -ADR-0057's original acceptance content and P02b-0's entry record are preserved. +#### The BFF session -#### PR #29 CI verification +The session is the first thing in the repository that holds a user credential, and its +properties are required rather than inherited from an adapter's defaults. **G13** +settles it; what the phase ships either way: -The first full [PR run](https://github.com/HodeTech/LearnStack/actions/runs/38228839007) -at `1e799a8` passes six of seven required jobs, including the public demo and -Lighthouse lifecycle. Docker integration reports 967 passed and one failed: -the existing stock-browser admission proof exits during its `browser 429` -phase. All other integration cases pass. The same focused proof passes locally; -the original CI diagnostic does not identify the failing browser operation. +- **OIDC Authorization Code flow with PKCE between the browser, the BFF and Keycloak.** + The BFF is the code-exchange client; the API is a resource server that validates a + bearer token and is not a party to the flow. +- **Custody.** Security Standards puts refresh tokens in `HttpOnly`, `Secure`, + `SameSite=Lax` cookies and that document owns the rule; what this phase adds is that + only server code reads them, and that no response body, RSC payload, session JSON or + log line carries one. +- **Lifetimes and refresh.** One authority for the access-token TTL — four documents + currently give four numbers, and this phase links the authority rather than adding a + fifth. Concurrent requests arriving with a near-expiry token produce exactly one token + request and one logical replacement session version, including any cookie chunks; + a terminal `invalid_grant` clears the session and the + visitor gets the public page anonymously rather than an error. +- **Cookie scoping and CSRF.** Host-only cookies with no `Domain`, so two tenant hosts + do not share a session, plus an `Origin` check and a session-bound token on every + mutating route. `SameSite=Lax` does not separate hosts under one registrable domain, + which is exactly the SaaS subdomain shape, and no CSRF rule exists in the catalogue + today. +- **Login topology**, under **G12**: login is served on the visitor's tenant host, + requiring one registered redirect URI per seed host. Phase 02d retains + `demo-english.learnstack.local` and `demo-yoga.learnstack.local` under the native + HTTPS launcher; hosts entries and certificate trust remain manual prerequisites. + `P02b-0` re-verifies [G32](phase-02d-walking-skeleton.md#the-decision-register) + and the ADR-0053/0054/0055 ingress, visitor/peer and single-bootstrap boundaries. + G12 still settles the BFF client, callback and post-logout URLs; it preserves + `Secure`. The login transaction's `state`, `nonce` and `code_verifier` live in a + host-only transaction cookie, and return URLs are validated. +- **Logout**, which + [Identity and Auth § Logout](../architecture/13-identity-and-auth.md#logout) describes + and Phase 03 expects: the session cleared, the end-session endpoint called, and + back-navigation not restoring an authenticated view. +- **Something that consumes the session.** One authenticated `/api/v1/*` read and one + guarded page, both in the OpenAPI document and the regenerated SDK. Without them "a + login completes" cannot be demonstrated, and + `Backend_RequiresJwt_OnAllAuthenticatedRoutes` sweeps an empty route set. +- **Auth.js and `auth()` placed in `apps/web`**, the `(studio)` / `(portal)` redirect, + the server SDK's bearer attachment, and server-only environment keys. The + `add-frontend-route` and `add-feature-gated-ui` skills contain future auth + illustrations rather than shipped helpers; P02b-7 replaces them with the real + session API when it lands. -Test-only browser diagnostics now expose closed phase names for startup, -hydration, navigation, wire assertions and cleanup. Raw exceptions, browser -output, URLs and private values remain excluded. A verified review follow-up -also preserves the first proof failure if shutdown fails, while always running -cleanup. Assertions, deadlines and production behavior are unchanged. +### Useful provisioning flow -At `11871a2`, the [diagnostic run](https://github.com/HodeTech/LearnStack/actions/runs/38231443960) -passes all 968 Docker integration cases. Its non-Docker artifacts record 1,764 -unit, 265 architecture, four contract and 180 integration cases: 3,181 backend -cases pass with zero failures/skips across both jobs. The original stock-browser -failure did not recur; its cause remains unestablished, not claimed fixed. +[ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) +accepts completed provisioning as the producer: `TenantCreatedIntegrationEventV1` +on `learnstack.tenancy.tenant`, partitioned by `TenantId`, with no extra payload +fields and null envelope organization. P02b-1 emits it only after tenant/default +organization/back-reference completion and persists pending rows. -Both diagnostics and first-failure preservation completed two fresh independent -review rounds. Focused browser checks pass 18 cases; final guarded frontend tests -pass 1,542 cases across two packages with zero skips/todos. Lint/typecheck and -the real admission integration proof pass locally. Verified CodeRabbit findings -also reconcile delivered producer work, pending inbox delivery and process-local -versus durable ordering in architecture/glossary/XML guidance. Five corpus -checks and the changed-document link/anchor sweep pass after those corrections. -The [PR's required checks](https://github.com/HodeTech/LearnStack/pull/29/checks) -own the final-head CI verdict; passing local or intermediate evidence does not -claim approval or merge. +Under ADR-0046, P02b-3 supplies independent Customization subscriptions for the +`card@1` content type and `plain@1` taxonomy. Each create-only effect owns one root, +generation update and MUST +audit on its inbox transaction, preserves authored/lifecycle/deletion decisions, +and resolves incomplete pairs through retry. P02b-3 owns semantic key/version +Seeder verification, preserved warm IDs and fresh seed/delivery convergence. +Typed settings stay uncached; definition generations are freshly probed. This +phase promises no eager settings invalidation or asynchronous Audit mirror. -**Next: P02b-2 decision pass.** Reverify G1, G3 ordering, G4, G5 resolver policy, -G7/G8, G17 and G18 error descriptors before implementation. ADR-0046 remains -reserved and undrafted; any new decision package/ADR needs maintainer approval. -That packet owns lease/grant migration, existing-row handling, dispatcher -credential/boot guard, claim/publish/mark, retry/terminal policy and metrics/health. -P02b-3 subsequently owns inbox/subscriptions, both Customization defaults and -the Seeder identity handoff after G1. Pending outbox rows do not claim delivered -consumption; no producer work is silently transferred to those packets. +### Audit coverage wiring -#### PR #29 external-review proof follow-up (2026-10-12) +The audit pipeline lit up in +[Phase 02a Packet 9](phase-02a-kernel-tenancy.md#delivery-record-packet-9) under +[ADR-0033](../decisions/0033-audit-durability-model.md). This phase adds the entry +points it does not reach, and both of Packet 9's hand-offs land here. -The review of `d37f46c..cb2bb6d` found three Minor proof gaps and no -Blocker/Major runtime finding. Commit `d8fd919` strengthens the existing cases: +- **The delivery path owns its transaction and audit frame.** + [ADR-0040](../decisions/0040-ambient-unit-of-work.md#consumers-do-not-have-a-request-and-still-need-all-of-this) + assigns `Begin → SetTenantContext → handler → Commit` to this phase. P02b-3 + prepares the app-role transaction, restores validated event context, claims the + inbox and enters the common audit owner before handler construction. Handler + identity is classified even for a direct business write; an unregistered handler + is refused. This closes the old accessor-only transport's missing audit frame. + **G6's common-owner contract is Accepted under ADR-0057**; P02b-3 implements + it in production delivery under ADR-0046. Its proof is a MUST-classified direct-write + consumer, + not only a consumer that sends a command. +- **The audit frame's owner on a non-pipeline entry point.** What is *already* decided + is not reopened here: + [ADR-0033 Amendment 2 § 2](../decisions/0033-audit-durability-model.md) and + [ADR-0044 § 4](../decisions/0044-audit-write-path.md) both say only the owning frame + writes, signals the boundary, reconciles and clears, and a joiner does none of it. + ADR-0057 accepts common entry coordination for **G6**. `AuditLogBehavior` takes + its owner + flag from an audit-frame counter rather than from unit-of-work ownership, and + [Audit Subsystem](../architecture/31-audit-subsystem.md) records that split as + deliberate for the HTTP path — at step 3 no transaction is open to answer the + question. P02b-3 explicitly opens the outer audit frame around subscriber execution; + nested commands join it and cannot reconcile or clear before delivery completion. + The shared transaction owner flushes MUST rows before commit, then the outer audit + owner alone reconciles and clears. P02b-1's controlled fixture and P02b-3's actual + consumer and direct-write proofs enforce ADR-0044/0033's common ownership. +- **The discriminating case.** The pair this phase used to name — a consumer's + MUST-class command recording `success` on the delivery's transaction, and a + rolled-back delivery recording it standalone as `failed` — passes under **both** + ownership designs. ADR-0057's cases distinguish an ordinary event-free refusal + absorbed by a committing delivery from a produced-work refusal that poisons it, + a faulted `COMMIT` producing exactly one + `indeterminate` row, and `Clear()` running exactly once per delivery. +- **Dead-letter transitions — Accepted ADR-0046.** Producer terminal state and + Tenancy-owned `platform.outbox.dead_letter` MUST security-event commit on one + short confined-role transaction. `WriteEventTerminalAsync` validates its + restricted `EventTerminalTransition` witness against the actual fenced UPDATE + and draft identity. Audit failure rolls back state and retries terminalization, + without another publication. P02b-3 Step 4 delivers the corresponding subscriber + operation and its off-path registration with the writer. +- **Routine dispatcher bypass — Accepted ADR-0046.** The confined credential, + exact grants, bounded diagnostics and atomic terminal audit explicitly exempt + routine polls/claims/acknowledgements/retries from per-invocation security audit. + Existing `EnterPlatformAdminScope` entry audit and all other bypass obligations + remain unchanged. This is no general background-job exemption. +- **The rejected-assertion row names its actor once there is one.** The recorder writes + a null actor on the authenticated tier today, because no principal exists in the + process and `IsAuthenticated` is a tier rather than an identity. ADR-0036 makes the + actor the finding on that tier, so the realm integration above populates it from the + validated token's user — the observable that also proves the assertion middleware runs + after authentication. +- **Causal actor and causation.** P02b-3 supplies the validated incoming event ID + to consumer audit intents and follow-up outbox production; causal actor remains + separate from effective SystemActor. Nested commands inherit these identifiers, + while a newly drained domain event supplies its own causation ID. The Accepted + **G6** producer/common-owner contract owns these bounded metadata keys. +- **Classification for the operations this phase introduces** — the sample flow's + command, the first authenticated read, login, logout and refresh — registered in their + owning module's catalogue source and matrix before their handlers ship, because an + operation the catalogue does not classify is refused, and the join is total in both + directions. The authenticated read carries no permission key until Phase 03. -- The shared execution test enqueues through the registered `IOutbox` at - descendant depths 0, 1 and 2. It observes both business and outbox rows inside - the transaction, then verifies both disappear after the absorbed refusal. -- The committed-MUST reconciliation test requires one declared intent inside - the handler before checking that reconciliation writes no duplicate. -- The nested transaction test observes zero joiner writes and one owner write - in the same execution, including the actual commit-state transition. +The `AuditEntry` aggregate is owned by the **Audit** module and shipped in Phase 02a; +rows arrive through the store's parameterised inserts, and +[Phase 03](phase-03-identity-admin.md) registers the Identity module's catalogue source +and coverage matrix against it. See +[Audit Coverage Standards](../standards/18-audit-coverage.md). -Three temporary mutations independently remove the real outbox receipt, audit -declaration and owner audit write. Their respective three, one and one target -cases fail. Production files are restored byte-for-byte, then all 62 audit/ -transaction unit cases and 71 producer integration cases pass again. +### Compile-time secret leakage (carried out of Phase 02a Packet 3) -Release build has zero warnings/errors; changed C# formatting and -`git diff --check` pass. The complete 1,764 unit and 265 architecture cases and -the 71 focused PostgreSQL cases pass with zero failures/skips; focused repeats -overlap these counts. This follow-up changes no production code or case count. +Packet 3 shipped runtime redaction — the Serilog enricher and the local error tracker +both scrub the same set through the single `SensitiveTokenCatalog`. It covers logs, OTLP +and error-tracker tags. It does not cover a value already interpolated into an exception +**message**, and this phase adds three durable sinks for one: an outbox row's +`last_error`, a subscriber-side failure record, and a job's persisted failure state. +Those sinks, not a Problem Details body, are the threat this phase's diagnostic answers +— the response factory builds no free text from an exception message. -The public-receipt suggestion needs no visibility change here: `PostgresOutbox` -is a real cross-assembly caller; invocation receipts also serve existing -integration proofs. A temporary probe of compiled `BeginInvocation` confirms -that a hierarchical ambient Activity receives a valid W3C child and is restored -on disposal. The suggested non-W3C fallback failure does not reproduce. +`LS0002` is planned, not shipped; its initial Warning severity does not itself +make a build fail. A roadmap document is not its diagnostic registry. +**G16** records it the way ADR-0032 Amendment 1 recorded `LS0001`: its +`LearnStackException-<Topic>` rule name, the project trees it runs over, what it +inspects, its `AnalyzerReleases` row, its catalogue entry, and the condition that +escalates it from Warning to Error. Two things the record has to settle rather than +inherit: -Two fresh independent review rounds cover `cb2bb6d..d8fd919` and this follow-up -record. Each pairs GPT-6-astra high runtime/fixture review with GPT-6.1-sol high -proof/corpus review; all four reviewers approve without verified findings. -Five corpus checks, seven ADR lifecycle tests and the changed-document -link/anchor sweep pass. The PR checks own fresh final-head CI evidence. +- **Its scope.** `LS0001`'s `Domain` + `Application` reference set excludes the + assemblies where this phase handles tokens and provider errors, which is where the + sinks are. +- **Its token source.** The analyzer targets a different framework from the assembly + that holds `SensitiveTokenCatalog`, whose own remark says new tokens land there and + not in consuming projects, and the catalogue's public accessor exposes only part of + the set. A drift test is what makes "matches `SensitiveTokenCatalog`" true rather than + aspirational. -#### PR #29 systematic-review remediation (2026-10-12) +Its own tests assert the positive case, a clean case staying clean, a sensitive name +outside a `throw` staying clean, no `AD0001` crash — the failure mode ADR-0032 Amendment +1 records for `LS0001` — and that the analyzer's token set equals the catalogue's. -The review against `75fc79b` identifies a valid pre-COMMIT audit classification -fault. Commit `c7dae0c` distinguishes a still-live transaction from a physical -COMMIT whose acknowledgement failed. A live frame refusal now enters the guarded, -uncancelled rollback path; the original error survives cleanup failure. Actual -COMMIT faults retain the existing Indeterminate behavior. - -The PostgreSQL regression first fails against the old code: a leaked frame -produces a permanent `indeterminate` audit row despite never attempting COMMIT. -After the fix, owner and absorbed-joiner cases observe actual business/outbox -INSERTs, then prove their rollback, a single `failed` audit row, cleared authority -and refused same-scope reuse. Scope disposal already collapsed leaked frames in -the old code; the review's claim that they stayed live after unwinding is not -reproduced. Two unit cases also preserve the frame error when rollback succeeds -or throws. API and Seeder tests document and enforce producer enrollment before -event-bearing saves, with successful event-free raw-save controls. - -Other verified changes reconcile the current uncached-settings handoff without -promising a settings event, correct ADR-0032 clause locators through ADR-0041 -errata, refresh amendment/index/example links and name concrete proof methods. -The parallelism census includes shared Application, Infrastructure and the -separate audit infrastructure project, with planted controls and exact-path -exceptions for singleton cache and pre-admission host lookup flights. Test-only -browser diagnostics distinguish launch, DevTools readiness and private-carrier -failures; cleanup preserves the first -failure and exposes only closed phase tokens. - -The remaining runtime suggestions do not demonstrate a current failing path: -domain dispatch validates enrollment before owner access; outbox ancestry and -JSON shape are guarded before serialization checks; the Seeder test positively -observes promotion before its deliberate refusal; reflection and log-trigger -changes fail their existing controls loudly. Provider-port recognition remains -an explicitly enumerated limitation, not a future-port discovery claim. No -runtime visibility/marker, serializer, scheduling or ConfigureAwait refactor is -needed. The final announcement check remains defense in depth after drain. -The earlier temporary mutations are recorded manual experiments; their target -regression cases are permanent, without a new automated mutation-runner claim. - -Two fresh independent review rounds pair GPT-6-astra xhigh runtime review with -GPT-6.1-sol xhigh proof/corpus review. Round 1 checks `75fc79b..3f4c121` and -identifies one additional Minor in the outer browser proof: a caller-supplied -closed phase token can masquerade as a sanitized error. Commit `9b2fcf6` requires -the existing private brand at that boundary. Its paired actual-export cases -first fail for the forged token, then pass while retaining genuine branded -error identity. The first-round proof reviewer verifies the fix. Both fresh -Round 2 reviewers approve `75fc79b..9b2fcf6` without findings. - -Full local verification passes 1,766 unit, 266 architecture, four contract and -1,152 integration cases: 3,188 backend cases, zero failed/skipped. Focused -verification passes 75 producer integration and 64 audit/transaction unit cases, -overlapping those totals. Guarded frontend tests pass 1,550 cases across two -packages, including 26 browser diagnostics cases, with zero skips/todos. Release -build has zero warnings/errors; solution format, frontend lint/typecheck, seven -ADR lifecycle checks, the changed-document link/anchor sweep and -`git diff --check` pass. Original Accepted Status/Decision/prior amendments and -the frozen P02b-0 entry record remain byte-preserved. The -[PR checks](https://github.com/HodeTech/LearnStack/pull/29/checks) own the exact-head -CI verdict; local results do not establish that verdict or merge approval. -PR review and merge remain pending. - -#### PR #29 outbox INSERT and ownership follow-up (2026-10-12) - -All four follow-up comments reproduce against `b561c8f`. Commit `96e6f4d` -marks the existing unit rollback-only when the immediate outbox INSERT throws, -then rethrows the same exception. Only a successful INSERT records produced -work; validation refusals before execution retain their existing behavior. - -The existing duplicate-EventId regression now covers propagation and absorption -of a real PostgreSQL INSERT failure. Both cases first fail against the old code -at the immediate rollback-only assertion, before coordinator unwinding can -poison the unit. The fixed cases retain the successful parent's receipt, create -no failed-child receipt, prove original exception identity or absorbed-error -refusal, and verify rollback and shared-state cleanup. All 31 outbox cases pass. - -Architecture 31 records Steps 2–3's delivered enqueue, successful-save -collection/promotion and owner-only drain. Standards 02/18 distinguish UoW-owned -domain collector/source cleanup from reconciliation and audit capture cleanup -owned exclusively by the outermost `AuditExecutionCoordinator` frame. The -catalogue no longer claims inbox parity for `InProcessEventBus`. Dispatch and -consumer delivery/inbox remain P02b-2 and P02b-3; no ADR decision changes. - -Two fresh independent review rounds pair GPT-6-astra xhigh runtime review with -GPT-6.1-sol xhigh proof/corpus review. Round 1 approves `b561c8f..96e6f4d` -without findings. Round 2 covers the same code/document changes and this dated -closeout; both reviewers approve without findings. - -Full local verification passes 1,766 unit, 266 architecture, four contract and -1,153 integration cases: 3,189 backend cases, zero failed/skipped. Focused outbox -repeats overlap that total. Release build has zero warnings/errors; solution -format, seven ADR lifecycle checks, the changed-document link/anchor sweep and -`git diff --check` pass. No frontend source, schema, credential or accepted ADR -changes. The [PR checks](https://github.com/HodeTech/LearnStack/pull/29/checks) -own final-head CI evidence; PR review and merge remain pending. - -### P02b-1 merge and closeout (2026-10-12) - -The maintainer merged [PR #29](https://github.com/HodeTech/LearnStack/pull/29) at -2026-10-12 13:47:58 UTC. GitHub records final PR source -`8a97cd2b7c19bf54a1b0b1f1ad75175256417c9c` and squash merge -`b1f6f21cab556ee7ba497dfc0d64e51b8cf1dad8`, whose parent is the previous main -`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`. Source and squash merge have the -identical tree `ba6f9b552c17598ec219ec9d2fc04ef5f235eec0`. Development incorporates -the main merge without switching branches or rewriting published history. - -All seven required checks pass in the -[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38255804801) -for that source; CodeRabbit also reports success. The tested synthetic merge is -`50fe60560b7966a23c14ab359531aadfbf59a442`. Verified downloaded artifacts record: - -- **3,189 backend passes**, zero failures/skips: 1,766 unit, 266 architecture, - four contract, 180 Docker-free integration and 973 Docker integration cases. -- **1,550 guarded frontend passes**: 1,490 web and 60 SDK, zero - failures/skips/todos; frontend lint, typecheck and builds also pass. -- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, nine - screenshots and matching source/checkout identities and report digests. - Automated accessibility is 1 throughout, CLS is 0 and maximum normalized - initial JS gzip is 106,552 bytes. Owned cleanup passes; timing medians remain - advisory. These are final PR-run results, not a claim about a post-merge run. - -**P02b-1 is closed.** All four steps and verified review fixes are delivered; -their two independent review rounds remain recorded in the -[packet closeout and follow-ups](#p02b-1-packet-closeout-2026-10-12). Earlier dated -delivery/review records retain their historical pre-merge wording. Accepted ADRs -and P02b-0's entry record are unchanged. Phase 02b remains in progress. - -**Next: P02b-2 decision pass.** Reverify G1, G3 ordering, G4, G5 resolver policy, -G7/G8, G17 and G18 failure descriptors before dispatcher implementation. -ADR-0046 remains reserved and undrafted; the decision package and any new ADR -require maintainer approval before implementation. P02b-2 owns the lease/grant -migration, existing-row handling, dispatcher credentials/boot guard, -claim/publish/mark, retry/terminal policy and metrics/health. P02b-3 owns inbox -delivery, the two Customization defaults subscriptions and the Seeder handoff. -Producer rows are durable but do not yet claim delivered consumption. Background -jobs, API authentication, realm reconciliation, BFF sessions and phase-exit -enforcement remain with P02b-4–8 in the [packet table](#packets-and-decision-gates). - -**Documentation-only closeout validation.** All 266 local Release architecture -cases and seven ADR lifecycle/workflow controls pass, zero failures/skips. The -five changed Markdown files resolve 585 relative links and 186 fragments without -errors; added prose wrapping and whitespace checks pass. Prior dated delivery -records and all Accepted ADR files are byte-preserved. Full runtime suites are -not rerun locally for this documentation-only change; the final PR artifacts -above supply their evidence. - -### P02b-2 decision package (2026-10-12) - -**Accepted — 2026-10-12, @cemil.** The revised decision package and ADR-0046 -are approved, including all four implementation steps and their review loop. -The documentation/code audit used `development` -at `b1f6df34b1d0db9dff77b355743d7bf8885947b3`, the P02b-1 merge closeout. -Three independent read-only audits covered delivery, privilege/audit and runtime/ -observability. They ran no tests and changed no files. The accepted package uses -[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); earlier -Accepted ADR bodies and prior dated delivery records remain intact. The dated -acceptance record below distinguishes approval from implementation evidence. - -The dated P02b-1 closeouts' "Next" and "reserved and undrafted" descriptions -record the state before this package. This current package and the Active index -replace those historical navigation instructions; the old records remain intact. - -#### Review findings and accepted answers - -The current bus's zero-handler success is unsafe for P1's real provisioning rows: -their consumers do not exist until P3. Separately, the outbox role cannot write -the MUST audit required by terminalization, and cancellation alone cannot bound -a callback that ignores its token. ADR-0046 explicitly resolves these gaps. - -| Gate / concern | Accepted answer | Delivery owner | -|---|---|---| -| G1 subscriber identity and isolation | Shared transport-owned inbox keyed by tenant, stable subscription ID and event ID; separate delivery ledger owns attempts, terminal state and targeted replay | Contract now; implementation P02b-3 | -| G3 ordering | Deterministic eligible selection by availability, occurrence and ID within one processor; no enqueue, commit, retry or cross-process ordering promise | P02b-2 | -| G4 attempts and terminal state | Six committed normal claims; five published retry delays; fresh-token crash recovery; explicit terminal request and audited terminal timestamp; no seventh publish | P02b-2 | -| G5 type and zero-subscriber policy | Declared concrete types/compatible aliases only; invalid/retired/unknown records terminalize; Pending required subscriptions preserve rows; only intentional absence acknowledges without publication | P02b-2; Active durable subscribers P02b-3 | -| G7 terminal audit | Fenced state transition plus MUST security-event on one transaction through `WriteEventTerminalAsync`, with a restricted transition witness binding audit tenant/org/event to the actual UPDATE result; `platform.outbox.dead_letter` now, reserved Tenancy-owned `platform.delivery.dead_letter` when P3's writer ships; failed audit retries terminalization without delivery | P02b-2 producer; P02b-3 subscriber | -| G8 bypass | Explicit routine-dispatch exception, confined credential and exact grants; existing platform-scope entry audit unchanged | P02b-2 | -| G17 metric dimensions | No tenant labels; registry-bounded event types; separate backlog, eligible age, deferred backlog and heartbeat; immutable gauge snapshots | P02b-2 | -| G18 failure storage | Closed descriptor, at most 256 UTF-8 bytes with CHECK; replace free-form legacy descriptors without changing fact/state | P02b-2; erasure inventory P02b-8 | -| Credential topology | API-owned keyed lazy source; exact physical outbox-role checks; boot connectivity; no Seeder/web credential propagation | P02b-2 | -| G6/G19 dependency | Preserve common owner, envelope organization and effective SystemActor; activate both real defaults subscriptions only with durable acceptance and Seeder handoff | P02b-3 | - -The exact normative replacements and additive audit seam are enumerated in -[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#bounded-supersession-and-additive-seams). -They are not ADR-0041 errata. At acceptance, append dated disclosures to -ADR-0006/0010/0038, ADR-0003's unchanged role model and extended grant-budget -navigation, the bounded audit-grant replacement disclosure and -separate fifth-writer seam amendment to ADR-0044, and the same-transaction -clarification to ADR-0033. Keep original acceptance blocks, -decisions and earlier amendments byte-preserved. G1's rule changes are recorded -now but their implementation remains Registered for P3. - -#### Runtime bounds and observation - -These approved bounds are not implemented defaults yet. Options reject invalid -or unbounded values at composition; tests can inject time and tighter positive -bounds. Lease ownership always uses PostgreSQL time, never a caller's clock. - -| Setting / policy | Approved initial bound | -|---|---| -| Worker and claim capacity | One worker; one just-in-time normal claim | -| Idle poll | 200 ms | -| SQL operation / complete terminal transaction deadline | 5 s | -| Publish wait deadline | 10 s | -| Lease | 30 s; validate margin for publish plus fenced transition | -| Progress health bound | 45 s without actual completed progress | -| Snapshot refresh | After completed iterations; idle target 5 s; stale at the 45 s health bound | -| Cancellation-ignoring callbacks | At most four retained tasks; block their partitions; unhealthy while any remain; stop new claims at four | -| Shutdown wait | At most 30 s; retain live task-owned resources until completion or process exit | -| Attempts and backoff | Six normal claims total; 1 s, 5 s, 30 s, 5 min, 1 h | -| Durable failure descriptor | Closed vocabulary, at most 256 UTF-8 bytes | - -A publish timeout cancels the callback and persists its fenced failure, or leaves -an unknown outcome for expired-lease recovery if persistence fails. The callback -keeps ownership of its scope until actual completion; its late result cannot -acknowledge the row. Exclude its partition from new local claims until it finishes. -Unrelated partitions can progress within the four-task allowance. Saturation -stops acquisition and reports unhealthy; no unbounded detached-task replacement -or forced managed-task termination is claimed. P3 must also fence its business -transaction before enabling Active production subscribers. - -Its completion gate must reject a canceled/timed-out attempt before COMMIT even -if failure persistence did not replace its token. Cancellation after physical -COMMIT starts remains Indeterminate under ADR-0033; P3 recovers from atomic -business/inbox/ledger state rather than promise rollback at that boundary. - -Pending count includes all unprocessed, nonterminal rows, including delayed, -leased, terminal-requested and manifest-deferred work. Eligible age uses the exact -normal-publication claim predicate: it excludes terminal requests, exhausted -attempts, future availability, live or unrecovered expired claims, and held/locally -blocked partitions. It is zero when none qualify and never negative. Deferred -count exposes manifest-held work. -Heartbeat advances only after actual bounded loop work, including an empty poll, -not from an independent timer. Failed refresh retains the last snapshot and -marks observation stale. Terminal-audit failure is unhealthy, never a fabricated -successful empty queue. `/healthz` remains liveness-only. - -Standards 10 owns the final metric inventory at acceptance. Preserve existing -outbox duration/failure/dead-letter/lease-loss names with registry-bounded -`event_type` where applicable. Add unlabelled -`learnstack_outbox_oldest_eligible_age_seconds`, -`learnstack_outbox_deferred_count` and -`learnstack_outbox_heartbeat_age_seconds`; pending count becomes unlabelled. -Inbox counters remain reserved for P3, and job metrics for P4. Gauge callbacks -perform no SQL. Dispatcher-owned logs, traces and failure descriptors use validated -correlation and bounded outcomes, without exception text, payload, raw stored type -or connection data. Current bus/consumer exception telemetry is a separate P3 -reconciliation obligation before Active production subscriptions; this packet -does not claim that existing transport diagnostics are already minimized. - -#### Four approved implementation steps - -Each step implements and commits on `development`, then runs two fresh independent -review rounds. Verify findings against current code, fix valid findings, validate -and commit fixes before the next round/step. A clean review needs no empty commit. -The loop continues automatically unless a blocker or new maintainer decision -requires input. No branch switch or history rewrite is part of this package. - -1. **Decision reconciliation, schema and confined composition.** Accept ADR-0046 - and the gate parts above before code. Register catalogue obligations; update - canonical Outbox DDL/indexes/grants, metric labels, audit policy, architecture - and glossary. Add Platform-chain lease/terminal/descriptor/identity migration - and Audit-chain INSERT-grant migration. Declare registry/aliases/readiness, - keyed credential validation and physical-role guard. Adapt test-owned host - composition explicitly; production registration stays enabled. Validate exact - privilege sets, forward/down/reapply and invalid legacy input. No handler or - arbitrary type is constructed to discover subscription metadata. -2. **Durable transitions and terminal audit.** Implement parameterized claim, - recovery, success, backoff, terminal-request and atomic terminal-audit paths. - Add the confined fifth store method, off-path catalogue/matrix row and narrow - call-site/transition-witness guards. Prove token/expiry fences, same-worker - reclaim, six-claim crash, - no seventh publish, uncertain completion and audit rollback on real PostgreSQL - using actual outbox/application roles. Intentional absence and Pending holds - must have distinct non-vacuous controls. -3. **Hosted lifecycle and observability.** Activate the API BackgroundService; - implement bounded waits/overruns/shutdown, progress health, safe traces and - snapshot metrics. Adapt the API launcher/demo environment allowlist and its - proofs without forwarding the credential to web/Seeder. Prove production - registration, startup rejection/valid controls, poison-row progress, ignored - cancellation, safe disposal and continued unrelated work within the bound. -4. **Enforcement and closeout.** Complete production-census and planted controls, - full Release regression/format, mandatory Docker proofs and applicable demo/ - frontend tooling checks. Reconcile current-state docs, actual test counts, - catalogue status and seven existing CI checks at the exact PR head. Create the - PR for maintainer review only after every step/review is complete; claim no - merge or P3 delivery from P2 closeout. - -#### Decisive proof obligations - -- Two independent processors contend under live leases; a release-on-read mutant - fails. Expiry allows redelivery; both stale success and stale failure lose the - token fence, including reacquisition by the same worker identity. This is not - a claim of two separate processes or exactly-once publication. -- Retry boundaries use controllable time/database availability, not wall-clock - sleeps. Crash recovery after claim six and audit refusal cannot cause a seventh - publish. Reconcile lost/uncertain terminal COMMIT before retrying so a completed - terminal audit is not duplicated. Terminal, delayed, leased, deferred and due - rows distinguish all queue gauges. -- Audit refusal on a terminal request with fewer than six attempts never makes - that row publishable again. Its pending contribution remains; its contribution - to oldest publish-eligible age is excluded. -- Known V1 payloads remain readable after declared deployment aliases. Reverse - commits, equal occurrence times and retry overtaking falsify stronger ordering. - Unknown/retired/malformed/mismatched rows do not trigger arbitrary type loading. -- Real TenantCreated rows survive repeated Pending polls without attempts or - constructions. P3's activation proof must later deliver them to both stable IDs. -- Missing/malformed/wrong-user credentials refuse without secret text; valid - configuration is lazy; real physical guards reject elevated/transitive roles. - Audit INSERT is allowed; audit read/update/delete and business access are not. -- Against the real bypass role, replace an audit draft's tenant, organization or - event while retaining the successful fenced transition's restricted witness. - Each mismatch must leave neither terminal state nor audit row committed. Prove - a matching organization-scoped success and rejection of stale/wrong-transaction - witnesses; GUC/RLS assertions cannot substitute for these controls. -- Cancellation-ignoring operations retain safe resource ownership, cannot write - late acknowledgements and cannot grow beyond the approved bound. A blocked or - saturated loop becomes unhealthy while `/healthz` still returns 200. -- Before P3 activates subscribers, its proof must include failed timeout - persistence followed by late business completion and timeout during physical - COMMIT on the final subscriber claim; atomic ledger/inbox state decides recovery. -- Structural censuses include production subjects and planted clean/dirty cases - for each key's resolution, publication, type loading and write confinement. - Behavioural controls mutate lease/terminal/audit safeguards to prove sensitivity. - -The P02b-2 publication proof uses the shipped BackgroundService, registry and -transition/audit stores on real PostgreSQL and actual roles. Keep real TenantCreated -subscriptions Pending. Only isolated test composition supplies an Active synthetic -contract and controlled transport/handler to exercise publish/mark, failures, -recovery and deadlines; intentional absence is a separate control. Assert nonempty -production machinery, without inventing a production subscriber. P3 owns handler -and durable-acceptance censuses when those production subjects exist. - -#### Scope retained by later owners - -P3 owns shared Inbox/delivery DDL and RLS, per-subscription business/audit frames, -retries, terminal audit and targeted replay, both Customization defaults and -Seeder identity handoff. That boundary is required by the packet dependency, -not an unowned deferral. The companion Hub roadmap's per-module inbox reference -needs a coordinated dependency-pointer update before P3 closeout; Hub remains -roadmap owner and this package adds no Hub endpoint or runtime work. P4 owns jobs; -Phase 03 owns operator routes/permissions; P02b-8 owns erasure inventory; Phase 11 -owns brokers, cross-process evidence, purge and readiness exposure. - -#### Proposal review and validation (2026-10-12) - -At proposal commit `cc5de26`, two independent review rounds completed before -maintainer approval. Round 1 used -separate GPT-6.1-sol xhigh delivery and security/corpus reviewers. Verified fixes -separate the audit-grant replacement from the additive fifth seam, allow safe -terminal auditing of malformed causal metadata, scope diagnostic minimization to -the dispatcher, and require atomic subscriber ledger completion plus a sticky -timeout gate. Cancellation after physical COMMIT starts remains Indeterminate. -Both reviewers approved the corrected proposal. - -Round 2 used fresh GPT-6.1-sol xhigh delivery and GPT-6-astra high corpus/privilege -reviewers. Both approved without actionable findings. Reviews were read-only; -they did not run runtime suites or claim implementation evidence. - -Documentation-only validation passes: 266 local Release architecture cases, -seven ADR lifecycle/workflow controls, 329 local links and 119 fragments across -the four changed Markdown files, prose wrapping and `git diff --check`. Prior -P02b-0/P02b-1 dated delivery records and all Accepted ADR files are byte-preserved. -Full runtime/Docker suites remain implementation-step obligations; no dispatcher, -inbox or gate delivery is claimed by this proposal. - -#### External proposal review reconciliation (2026-10-12) - -Two external reports were checked against the current draft, accepted contracts, -canonical DDL and production code. Their reported line numbers are not authority. -This revision remains Proposed and changes no runtime or Accepted ADR body. - -| Finding | Verified disposition | -|---|---| -| Erasure assigned to Phase 11 | Already corrected in `cc5de26`: privileged redaction and its bounded caller contract belong to Phase 03; only retention purge belongs to Phase 11 | -| Two subscription IDs conflict with `card@1` / `plain@1` | Rejected: `BuiltInCustomizations.Card` is a `BuiltInContentType`; `Plain` is a `BuiltInTaxonomy`. ADR-0057 freezes those two independent effects, not two content types. The ADR now maps each ID explicitly | -| Bypass audit INSERT lacks row-bound identity proof | Valid: the seam now receives a restricted witness from the actual fenced UPDATE result; draft tenant/org/event/subscription must match it. Forged-identity and matching-success proofs are explicit | -| Terminal-request normal eligibility and undefined release | Explicit predicates now exclude terminal requests/exhausted attempts; recovery is separate. Pending holds precede payload validation, even for malformed payloads. Removed the unexplained release transition; success/retry/terminal paths clear leases | -| Inbox completion, identity grammar and replay ambiguity | Clarified uncommitted claim and atomic completion/rollback; completed inbox rows never reset; subscription IDs version deduplication semantics | -| Grant locator, legacy batch/exactly-once/DLQ designs and metric/off-path carriers | Named exact authorities and acceptance replacements. ADR-0003's role model remains unchanged; Database Standards owns actual grants. No competing current dead-letter design remains after acceptance | -| Envelope storage, narrow P3 SELECT, subscriber audit owner and P2 proof subjects | P3 must name durable envelope copies/references before DDL and inventory them for erasure; scheduler cannot read payload; subscriber audit is Tenancy-owned. P2 exercises shipped machinery with isolated test contracts while real subscriptions stay Pending | -| Final acceptance/handler failure and roadmap target checks | Failed/unknown durable acceptance consumes producer attempts; only accepted deliveries isolate business retry budgets. The phase's own undated zero-subscriber/replay sketches are now named acceptance replacements | -| Missing references and historical Next navigation | Added applicable ADR links and the ADR-0047 reservation link; added current navigation without rewriting dated P1 records. ADR-0045 is not used by this ADR and needs no artificial reference | - -The internal executor performs delivery, not publication; it receives no exception -to the outbox-only publisher rule. SecurityEvent records a consequential bypass -terminal transition, not routine polling. The selected order receives matching -normal-claim and recovery/terminal indexes. These are contract clarifications, -not claims that the proposed mechanisms have shipped. - -The revision received read-only GPT-6-astra high audit/privilege verification and -a fresh GPT-6-sol xhigh delivery/corpus review. The latter identified the Pending -validation priority, acceptance-failure budget and phase-carrier gaps recorded -above. Both reviewers approved after the verified fixes; neither claimed runtime -execution evidence. - -Revision validation passes: 266 Release architecture cases, seven ADR workflow -controls, 337 local links and 124 fragments across the four proposal Markdown -files, prose wrapping and `git diff --check`. Accepted ADR files and dated -P02b-0/P02b-1 delivery records remain byte-preserved. Only this package and the -Proposed ADR changed in the revision. Maintainer approval still precedes runtime -implementation and acceptance-carrier edits. - -### P02b-2 acceptance (2026-10-12) - -**Accepted by @cemil.** The maintainer approves the revised ADR-0046 and this -decision package, and authorizes all four implementation steps on development -with two fresh independent review rounds per step. The accepted decision is -committed before runtime edits. G1, G3's ordering, G4, G5's resolver/readiness, -G7, G8, G17's event metrics and G18's failure-descriptor parts are Accepted. -P02b-3 still owns durable acceptance, inbox/ledger DDL, independent subscriber -execution/retries, both real default subscriptions and Seeder handoff; job and -erasure gates retain their later owners. - -Acceptance appends bounded supersession disclosures and additive seams to the -named Accepted ADRs, reconciles the current standards/architecture/glossary/skill -carriers, and registers six catalogue obligations. Original ADR acceptance -metadata, decisions and prior amendments remain intact. Dated P02b-0/P02b-1 -records remain byte-preserved. Registered rules and planned audit operations -claim no runtime enforcement; delivery evidence belongs to each step below. - -### P02b-2 Step 1 — Decision, schema and confined composition (2026-10-12) - -**Implemented; both independent review rounds and fresh fix review complete.** -Decision commit -`192810b` precedes runtime edits. Step 1 adds the Platform-chain migration -`20261012180355_add_outbox_dispatch_state` and Audit-chain migration -`20261012180433_grant_outbox_terminal_audit`. Existing migration bodies remain -unchanged. New state/identity/UTF-8 CHECKs and eligibility/recovery/terminal -indexes accompany exactly eight outbox status-column UPDATE privileges and -INSERT-only audit access. Legacy diagnostic replacement spans both tenants; -invalid legacy identities reject the migration and roll back its owner-only -backfill. Disposable-schema down/reapply preserves event facts and retains -redaction; live rollback requires a forward fix. - -The API registers a keyed, lazy, DI-owned outbox source with exact configured -username checks and physical session/current-role, attribute and membership -checks. Missing configuration fails upon resolution; Step 3's mandatory worker -startup will resolve it and prove connectivity. Seeder/web receive no new source. -The immutable contract/alias/readiness registry constructs no handlers. Real -TenantCreated has its two distinct Pending subscriptions; Active, intentional -absence, unknown and retired identities have separate controls. The two existing -connection-resolution censuses explicitly admit the approved dispatcher builder -and composition root, without wildcard exemptions. - -**Verification before review:** `CI=true` Release build has zero warnings/errors. -TRX counters and process exit codes record zero failed and zero skipped cases: - -| Suite | Passed | Scope | -|---|---:|---| -| Unit | 1,800 | Complete unit suite, including registry/composition/configuration controls | -| Architecture | 266 | Complete non-skippable suite | -| Contract | 4 | Served OpenAPI/public SDK contract suite | -| Integration, no Docker | 180 | Complete HTTP suite | -| Integration, Docker | 128 | Migration/role/schema/grant/rollback classes affected by Step 1 | - -The Docker slice includes `OutboxDispatchMigrationTests`, -`OutboxDispatcherRoleGuardTests`, `PlatformSchemaTests`, `TenancySchemaTests`, -`AuditSchemaTests` and `MigrationRollbackTests`. Role-mutation proofs own a -separate container; destructive schema probes own disposable databases. These -counts describe this step's completed checks, not a full Docker regression. -The six new catalogue rules remain Registered: transition/audit/worker proof -lands in later steps. No dispatcher execution or P02b-3 delivery is claimed. - -#### Step 1 review round 1 - -Fresh read-only GPT-6-astra xhigh security/schema and GPT-6.1-sol xhigh -corpus/test reviewers examined `192810b..d9bc77b`. Security review found no -actionable defect. Corpus review found a stale handler-owned inbox instruction -in the code-review skill and an unqualified historical per-module inbox note in -Architecture 10. Both were verified and reconciled to ADR-0046's transport-owned -P02b-3 target. Original dated notes remain intact. No runtime change was needed; -the existing test evidence above remains applicable. The correction passes local -file/fragment checks, prose wrapping and `git diff --check`. - -#### Step 1 review round 2 - -Fresh GPT-6.1-sol xhigh security/composition and GPT-6-astra high corpus/proof -reviewers examined `192810b..6a13455`. Corpus review approved without findings. -The composition review verified that an open generic Active handler could match -the discovery census despite being unconstructible. Active admission now requires -a closed type. A regression proves discovery sees the open generic offender, -refuses its matching manifest and accepts a closed generic control. The complete -Release unit suite passes 1,801 cases; the complete architecture suite passes -266, both with zero failures/skips. A fresh focused review checks this correction -before Step 2 begins. Removing the closed-type check makes the new regression -fail; restoring it makes all 17 registry cases pass. No migration, grant or -Pending policy changed. - -Fresh GPT-6.1-sol high focused review of `6a13455..b6fc714` approved the correction -without findings and independently checked its accepting/rejecting controls and -saved TRX counters. The completed Step 1 commits are `d9bc77b`, `6a13455` and -`b6fc714`; the next authorized implementation step is durable transitions and -terminal audit. - -### P02b-2 Step 2 — Durable transitions and terminal audit (2026-10-12) - -**Implemented; both independent review rounds complete.** `OutboxDispatchStore` uses -short parameterized database-time transitions. Normal acquisition commits one -fresh token and one attempt before returning; expired ownership requires a fresh -recovery token without another attempt. Success, failure, terminal request and -terminalization require the current token and an unexpired lease. Five backoffs -follow six counted normal claims; exhausted or requested work never reenters -normal publication. Pending identities and aliases are excluded before payload -validation in every acquisition path. Local blocked partitions receive the same -exclusion. - -`OutboxEnvelopeReader` uses only the registry's concrete type and frozen options. -It compares persisted fact/routing/time, tolerates PostgreSQL microsecond -truncation and checks the canonical reserialization byte cap, rather than jsonb -whitespace. Complete envelope admission precedes intentional acknowledgement; -Pending, unknown, retired and invalid outcomes remain distinct. - -The fifth `IAuditStore` method preserves the existing four writes. Only -`OutboxDispatchStore.TryTerminalizeAsync` derives the minting capability and calls -it. The private immutable witness reads all identity and causal values from the -actual fenced UPDATE result, including the old acquisition token. The real audit -store requires the declared producer MUST/SecurityEvent, matching draft identity -and the same live connection/transaction. Both writes commit together. Invalid -causal values are omitted; invalid correlation uses a validated attempt trace. -No audit SQL is added outside `PostgresAuditStore`. Tenancy registers the producer -operation; the subscriber operation remains planned for P02b-3. - -Terminal SQL plus audit share one five-second deadline. A lost COMMIT response -triggers a separate bounded durable-state read before returning/retrying; it -cannot insert a second audit into a completed terminal row. A test-owned TCP -proxy drops the real PostgreSQL COMMIT acknowledgement after physical commit, -proves reconnection and checks one durable terminal/audit pair. Production has no -fault hook. Failed audit retains the terminal request, including below attempt -six, and never permits another publication. - -Tests use actual `learnstack_app` inserts with announced tenant/org and the -guarded `learnstack_outbox_admin` source for transitions. Disposable databases -isolate grant and state mutations. Nonempty whole-production Cecil censuses and -clean/dirty controls cover witness shape, minting/fifth-write callers, async and -delegate helpers, required catalogue injection and named dynamic type-loading -APIs. This is a bounded IL capability check, not arbitrary reflection/dataflow -analysis. SharedKernel has no friend assembly. - -Four behavioural mutation controls each fail as intended: removing lease expiry, -admitting terminal requests for publication, omitting MUST audit and discarding -successful uncertain-COMMIT reconciliation. Every edit is restored before the -clean validation run. Six-attempt tests start at zero and commit all six claims; -they cover both an explicit sixth failure and an expired sixth claim. Snapshot -proofs distinguish due, future, leased, expired, requested, exhausted, deferred, -locally blocked, processed and completed-terminal rows. - -The four transition/audit/type catalogue rules are Implemented. Hosted lifecycle, -publication/overrun proofs, credential caller enforcement and observation remain -Steps 3–4. Real default subscriptions stay Pending; no P02b-3 business effect, -inbox or delivery ledger is claimed. - -**Verification before review:** Release solution build has zero warnings/errors; -formatting covers all 21 changed C# files. TRX counters and process exit codes -record zero failures/skips: complete unit 1,825, complete architecture 273, -contract 4, complete Docker-free integration 180 and affected Docker integration -110. The Docker slice covers `OutboxDispatchStoreTests`, `AuditStoreTests`, -`PlatformAdminScopeTests`, `TenantAssertionAuditTests` and -`PublicReadTransactionTests`; it is not a full Docker-suite claim. All four -behavioural mutants fail their named tests, then the restored code passes. -Local file/fragment, historical-record/Accepted-ADR preservation, prose-width and -`git diff --check` controls pass. - -#### Step 2 review round 1 - -Fresh read-only GPT-6-astra xhigh security/concurrency and GPT-6.1-sol xhigh -proof/corpus reviewers examined `c6ceaa9..7976113`. The proof review approved; -its independent rerun passed 273 architecture and 24 focused unit cases. The -security review reproduced a stored-routing gap: deserialization regenerates -get-only Topic/PartitionKey values, masking changed or absent payload members. -The reader now checks those required string members in the original JSON before -using the declared CLR contract, then compares the reconstructed routing with -the row. Ten unit mutation cases and four real-database cases cover changed, -missing and malformed routing, terminal-only progression and minimized audit. -The unchanged payload remains an admitted control. Removing the original-field -check makes all ten new unit cases fail. After restoration, the complete unit -suite passes 1,835 cases, architecture passes 273 and the four new Docker cases -pass, all with zero failures/skips. Round 2 follows the verified correction; -hosted lifecycle remains Step 3. - -#### Step 2 review round 2 - -Fresh read-only GPT-6.1-sol xhigh security/concurrency and GPT-6-astra high -proof/corpus reviewers examined `c6ceaa9..ffce05f`. Both approved without verified -findings. Independent Release no-build reruns passed 34 envelope/options unit -cases, 19 dispatch/audit architecture cases and all 53 dispatch-store Docker -cases, with zero failures/skips. The proof reviewer independently passed all seven -dispatch capability facts and checked the real COMMIT-response-loss result in -the restored database receipt. Both inspected the actual row-bound audit and -routing correction rather than accepting review notes as evidence. Step 2 is -closed; Step 3 may activate the mandatory worker and observation. No P3 delivery -or inbox effect is claimed. - -### P02b-2 Step 3 — Hosted lifecycle and observability (2026-10-12) - -**Complete; both independent review rounds passed.** The API owns -its mandatory `OutboxProcessor` BackgroundService, guarded dispatcher-source -startup resolution/connectivity, bounded publication lifecycle and retained -overrun ownership. Observation supplies immutable gauge snapshots, bounded -producer diagnostics and the registered, unmapped `outbox` health check. -`/healthz` remains liveness-only. Paired API launchers supply application and -confined dispatcher credentials; every Seeder invocation uses an explicit -application-only environment, and web receives neither database credential. - -**Verification before review:** the Release solution build reports zero -warnings/errors. TRX counters record zero failures/skips in the complete unit -suite (1,845), contract suite (4), Docker-free integration suite (182), restored -architecture suite (273), and the actual-host PostgreSQL `OutboxProcessorTests` -slice (16). Worker helper/observation unit cases are included in the unit total. -The initial architecture run exposed the newly registered worker in the global -keyed-resolution allowlist; the exact outbox-key allowance is corrected and the -restored 273-case run passes. This is a focused Docker-runtime receipt, not a -full Docker-suite claim. All three actual API-launcher cases also pass after -correcting the environment reader to accept the explicit dispatcher credential. -The two affected frontend files pass 116 tests; web lint and typecheck pass. -Whitespace verification passes for all 39 changed C# files; affected TypeScript -and runtime-script Prettier checks, script syntax, diff whitespace and 2,172 -relative links/396 fragments pass. Historical producer delivery records and -Accepted ADR bodies remain byte-preserved. - -`OutboxProcessorTests` covers actual registration/guarded boot, invalid credential -refusal, real provisioning Pending holds, poison/ordinary failure progression, -explicit intentional absence, retained callback/cleanup ownership, four-task -saturation and finite shutdown. Observation tests cover monotonic stale health, -failed-refresh retention, terminal-audit failure, finite metric labels and fresh -trace identity, with bounded canonical correlation reconstructed from parsed -identity rather than optional traceparent extensions. Two independent actual API -workers prove no second publication/claim while the first live lease is held. -Never-blocks, live-ownership and Pending catalogue rules are Implemented. The full -health production census/planted controls remain Step 4; that rule is Registered. - -Two behavioural mutations fail in the intended executed test: removing local -partition admission permits a sibling claim before retained cleanup completes; -removing live-lease admission permits a competing worker to claim the held row. -Both source files are byte-restored before the clean build/unit/worker rerun. -Step 3 completed both independent rounds and the verified corrections below. -Steps 1–2 completed both rounds in their -records above. Step 4 owns full credential/publication censuses, catalogue -enforcement and packet closeout. P02b-3 still owns durable acceptance, shared -inbox/ledger, independent subscriber retries, both real default subscriptions and -Seeder handoff. Real required subscriptions remain Pending; no consumer business -effect is claimed. - -#### Step 3 review round 1 - -Fresh read-only GPT-6-astra xhigh security/lifecycle and GPT-6.1-sol xhigh -proof/corpus reviewers examined `d4c06a46..756c8523`. Security approved without -verified findings. The proof reviewer found that the demo's pre-existing -`--validate-demo-config` invocation forwarded all four credentials to Seeder, -contradicting the new confinement claim. Validation now runs inside the launcher -with a closed local connection grammar; the obsolete Seeder mode is removed. -Manifest and convergence modes share the same explicit child allowlist, and -standalone `make seed` uses it too, excluding ambient aliases and role passwords. -Stale role/password/database/host/port and malformed configuration controls move -with their owner instead of weakening the check. The complete Docker integration -regression at the implementation commit passes 1,083 cases with zero failures or -skips. This supplements the focused pre-review receipt above; final packet -verification will rerun the changed tooling and actual PR-head CI. -The correction's Release build has zero warnings/errors; the Docker-free -integration run passes 175 cases after seven obsolete parser cases moved to the -launcher suite. The guarded complete frontend run passes 1,608 cases (1,548 web -and 60 SDK), with zero skips/todos; 91 demo lifecycle cases include all four-role -configuration and actual shell/child-environment controls. Typecheck, affected -formatting, script syntax, diff whitespace and the delivery-record link check -pass. These are correction receipts, not a new full-Docker rerun. - -#### Step 3 review round 2 - -Fresh read-only GPT-6.1-sol xhigh security/lifecycle and GPT-6-astra xhigh -proof/corpus reviewers examined `d4c06a46..da637e35`. Neither found a Blocker or -Major. Security identified one operability gap: the safe startup refusal omitted -the configuration key/form required by the accepted completion criterion. The -fixed message now names `ConnectionStrings:OutboxDispatcher`, Npgsql key/value -syntax and `learnstack_outbox_admin`, without provider or supplied-value text. -The real-host negative theory asserts that guidance for missing configuration; -all four credential cases pass after the correction. Independent review reruns -passed 91 demo lifecycle cases, 11 focused outbox unit cases and two construction -host cases; the security reviewer separately passed nine helper/observation cases. -Both inspected the prior receipts and production paths. They did not claim a new -full build or Docker rerun. Step 3 is closed; Step 4 may add the complete -credential/publication/health censuses and close the packet. - -### P02b-2 Step 4 — Enforcement and closeout (2026-10-12) - -**Implementation and local closeout complete; both independent review rounds -passed.** Current CI/review/merge state belongs to the -[PR handoff](#p02b-2-pr-handoff-2026-10-12). -Steps 1–3 completed both independent review rounds; Step 3 is closed at `02540d0`. -Step 4 adds nonempty whole-production credential/publication censuses, exact -keyed factories and consumer bindings, and planted helper/delegate/async controls. -Only the processor constructs the task-owned publication attempt; its private -callback is the sole event-bus publication path. The existing canonical module -bus rule now also enforces that complete production fence. - -The five-subject observation graph follows async and production-owned -polymorphic contracts, rejects persistence/service-locator capabilities, and -inspects actual gauge callbacks. Actual DI controls reject missing/duplicate -workers/checks and wrong factories. Round 2 fixes at `606362b` pin exact credential -reader signatures, the external System clock and actual health/observation binding. -All 26 focused/corpus cases and both fresh fix reviews pass. -The literal-SQL census admits only exact producer enqueue, dispatcher -status-transition and migration backfill methods; quoted/schema/case/CTE and -missing/extra-writer controls prove its reach. These are bounded IL/literal-SQL -checks, not arbitrary reflection or dynamic-SQL dataflow analysis. - -**Verification before review:** the full Release solution build reports zero -warnings/errors, and solution-wide `dotnet format --verify-no-changes --no-restore` -passes. All 21 focused census/publication cases pass with zero skips, -including compiled actual production subjects and every planted control. Role -and Health catalogue rules are Implemented; Retry also names its canonical -architecture method. The source/catalogue recount is 193 architecture test -methods, 192 Implemented rules, 118 in that assembly and 74 elsewhere. - -The full Release backend regression passes 3,393 cases with zero failures/skips: -1,845 unit, 286 architecture, four contract, 175 Docker-free integration and -1,083 Docker integration. TRX counters were inspected directly; the nonempty-run -guard passes. The three additional case-insensitive credential-alias controls -also pass in the focused seven-case run. Step 3's corrected launcher/frontend -receipt remains the applicable local evidence: 91 lifecycle cases and 1,608 -frontend cases. These checks are not claimed as new Step 4 frontend reruns. -The full PR-range documentation check passes 2,555 relative links/459 fragments, -and all seven ADR-status script tests pass. Historical records and Accepted ADR -text remain preserved. All four implementation steps and both independent review -rounds are locally complete; post-fix verification is recorded below. The -[PR handoff](#p02b-2-pr-handoff-2026-10-12) owns current CI/review/merge state. - -P02b-3 still owns durable acceptance, shared inbox/ledger, independent subscriber -retries, both real default subscriptions and Seeder handoff. Required production -subscriptions remain Pending; test-owned Active contracts prove producer runtime -without claiming consumer business effects. - -#### Step 4 review round 1 - -Fresh read-only GPT-6-astra xhigh boundary and GPT-6.1-sol xhigh proof/corpus -reviewers examined `02540d05..d2531f2`. They reproduced three structural test gaps, -without finding a current production dispatcher defect. Captured key/provider -fields could be reassigned after their original capture; valid comment-separated -SQL and a later `TRUNCATE` target escaped the literal matcher; an additional -factory-based hosted worker escaped the descriptor type filter. - -The fixes close all three: captured-field mutations are restricted to the exact -factory parameter assignment, SQL recognizes those literal token separators and -all listed truncate targets, and the actual hosted descriptor set includes only -the singleton dispatcher and framework health publisher. Added dirty controls -cover key/provider writes in the factory, callback and helper, field/argument -address escapes and argument reassignment, SQL variants, and factory/instance -worker duplicates. No test method or catalogue count is added. All 21 focused -cases pass after the three corrections; the final seven boundary cases pass -again after the adjacent argument-mutation controls, with zero failures/skips. -The full regression above predates these test-only changes. The proof reviewer -independently passed 26 existing focused/corpus cases, with zero failures/skips; -neither reviewer claimed a new full suite. Round 2 remains pending. - -#### Step 4 review round 2 - -Fresh read-only GPT-6.1-sol xhigh boundary and GPT-6-astra xhigh proof reviewers -examined `02540d05..2f8693e`. They verified three test-guard gaps without finding -a current production defect. Named worker/store source-reader overloads could -self-authorize; an external `TimeProvider` subclass was invisible to the -production-owned contract graph and DI checks; a same-type health factory detached -from the singleton observation passed the returned-type check. - -The fixes are delivered at `606362b`: pin unique literal source-reader method -signatures, visibility and staticness with overload controls; require the actual -`TimeProvider.System` singleton instance with missing/duplicate/alternate-instance -and factory controls; and exercise the actual DI-registered health check through -Healthy → Unhealthy → Healthy against the singleton observation, with a detached -factory dirty control. The polymorphic graph covers production-owned contracts; -the external clock is admitted only through the explicit System-instance pin. -No test method, catalogue rule or published count is added. - -Post-round-1 verification at `2f8693e` passes the full 286-case architecture suite -and five Corpus cases; the Release build has zero warnings/errors. After the -round-2 fixes at `606362b`, all 26 focused/corpus cases pass with zero -failures/skips. Fresh GPT-6.1-sol xhigh boundary and GPT-6-astra xhigh observation -fix reviewers both approve with no remaining verified findings. The boundary -reviewer independently rejects both named-method overload plants (two offenders -each), observes zero clean/restored offenders and passes three focused Release -cases. The observation reviewer independently detects the SQL-capable external -clock and detached same-type health factory, observes zero restored graph -offenders and passes two focused Release cases. Neither claims a new full suite. - -The full post-fix Release build has zero warnings/errors, all 286 architecture -cases pass with zero failures/skips, and solution-wide format verification -passes. The final local documentation check passes 2,575 relative links and -479 fragments with zero errors. The 3,393-case regression above predates these -test-only guard fixes; its -TRX counters and the 26-case focused/corpus counters were checked directly. No -test method, catalogue rule or published count changes. All four P02b-2 -implementation steps and both independent review rounds are locally complete. -PR-head CI and merge remain pending; this closes producer dispatch/enforcement -without claiming any P02b-3 consumer delivery. - -### P02b-2 PR handoff (2026-10-12) - -[PR #30](https://github.com/HodeTech/LearnStack/pull/30) opens development → main -from local closeout `7bf14a0`. All four implementation steps and both independent -review rounds per step are complete. The PR's checks and current-head evidence -in its description own live CI state; its review and merge state remain on the -same PR. Earlier pending statements in dated local receipts are as-of records, -not the current check verdict. No merge is claimed by opening the PR. - -The seven existing required contexts and strict up-to-date protection were read -back from GitHub unchanged. Final verification must use the PR's actual current -head, not an earlier passing run. The PR description records run URLs and suite -counters after that verification. Five final local corpus checks pass with zero -failures/skips; this is not a CI result. - -P02b-3 is next after P02b-2 review/merge and its own decision pass: shared inbox -and delivery ledger, durable acceptance, independent subscriber retries/audit, -both real defaults subscriptions and Seeder handoff. No consumer delivery, -background-job or authentication completion is claimed here. - -### P02b-2 PR review follow-up (2026-10-13) - -All seven required jobs pass on PR head `a80e06d`, including the complete -3,393-case backend regression and 1,608 frontend cases, with zero failures/skips. -[Run 38306262165](https://github.com/HodeTech/LearnStack/actions/runs/38306262165) -also supplies 27 matching Lighthouse JSON/HTML report pairs and nine screenshots. -All reports have zero CLS, accessibility score 1 and normalized gzip JavaScript -between 106,359 and 106,553 bytes. Proof finishes in 646.454 seconds; owned process, -Compose, private-file, environment and lock cleanup all pass. These are receipts -for that head, not evidence for a later correction. - -Automated PR review identified a local-launcher validation defect: omitting both -a role's connection-string password and its selected password variable compared -two absent values as equal. Independent reproduction accepts that invalid state -for all four roles. Four new regression cases fail against the previous validator -and pass after requiring a nonempty configured string password. Existing quoted -password, whitespace and alias controls remain green; diagnostics remain fixed -and contain no supplied configuration. No runtime dispatcher or API contract -changes. - -Local verification passes 95 lifecycle cases and the guarded frontend suite's -1,612 cases (1,552 web and 60 SDK), with zero failures/skips/todos; lifecycle cases -are a subset, not an additional suite count. Workspace lint/typecheck pass. -Fresh sequential GPT-6.1-sol high and GPT-6-sol high correction reviewers both -approve `a80e06d..a851b7c` with no findings. Each independently reproduces the four -parent/current differences and passes all 95 lifecycle cases. Five Corpus cases -and seven ADR-status script tests also pass; the final link check covers 2,586 -relative links and 490 fragments with zero errors. Final correction-head CI -remains pending in this local receipt. -The [PR handoff](#p02b-2-pr-handoff-2026-10-12) continues to own live PR state. - -### P02b-2 external review remediation (2026-10-13) - -Both external reports against `44089707` were treated as review evidence and -checked against current code and Accepted ADR-0046. No new decision, consumer -delivery or grant change is part of this correction. Existing migrations and -Accepted ADR bodies remain unchanged. - -- Recovery now states its index predicate explicitly, without relying on - PostgreSQL to infer the lease CHECK. A new Platform migration replaces only - the recovery index: both expired leases and unleased exhausted rows retain - `(available_after, occurred_at, id)` order. Real migrated-database plans with - 50,000 Pending rows distinguish the predecessor's scan from indexed recovery; - admission exclusions, ordering and down/reapply are asserted. -- A failed durability probe after uncertain terminal COMMIT preserves both - exceptions, in COMMIT/probe order. The real response-dropping proxy exercises - that failure and independently verifies one durable terminal/audit pair and - no duplicate on retry. The unused persisted shutdown outcome was removed; - shutdown continues to leave ownership for expiry recovery. -- The launcher exposes only the exact fixed local database diagnostic, with - secret-bearing prefix/unknown-message controls. Absent configuration uses the - same diagnostic. Root runtime-script formatting is restored. The audit marker - count, transport-owned inbox wording, historical batch discussion, catalogue - proof kind, glossary and later-phase navigation now match implementation. -- The generic iteration diagnostic no longer mislabels every exception as a - storage failure. Normal dispatch avoids its unused registry lookup. Contention - warms both independent hosts before its live-lease deadline. Shutdown advances - exactly one controlled deadline with four retained callbacks; an isolated - second-budget mutant fails, and the rebuilt clean control passes. - -The remaining report suggestions were checked rather than adopted as new policy: - -| Concern | Disposition | -|---|---| -| Final `44089707` CI remains outstanding | Already resolved: all seven required jobs pass in [run 38309098697](https://github.com/HodeTech/LearnStack/actions/runs/38309098697). The earlier local receipt is dated evidence, not live state; this correction needs its own head verification | -| Failure metric precedes a successful fence; gauges may straddle a refresh | Metrics observe attempts, not durable transitions. Every gauge reads an immutable snapshot; no scrape-wide atomicity is promised. The phase criterion below now names that exact invariant | -| Disabled test worker leaves outbox health unhealthy | Intentional and now documented in factory remarks. The private check reports the absent worker; static `/healthz` remains liveness-only | -| Invalid options are reported as credential failures | Not on the shipped DI path: the store validates the shared options before worker construction | -| Alternate worker registration, duplicate short type labels, permissive terminal-request kind | No current production violation: composition census pins the sole worker; the registry has one production contract; the worker requests terminal state only from Normal claims. Recovery is deliberately used by a store fixture | -| Witness acquisition is not compared with audit metadata | SQL fences the actual token and returns it into the transaction-bound witness. The audit draft has no acquisition field; adding one is not required by ADR-0046 | -| Invalid causal metadata changes the original correlation | Matches ADR-0046: invalid correlation/causation/actor uses a validated attempt trace and omits invalid causal values | -| Role guard should reject other principals inheriting dispatcher rights | The guard validates the dispatcher's effective role and escalating memberships. Reverse grant auditing is outside that connection contract; changing it would not sandbox compromised privileged SQL | -| Ambient local credentials, migration-child environment, quoted passwords | Ambient overrides are explicit existing loader policy and tested. The administrative migration child is distinct from the confined web/Seeder children. Single/double-quote parsing is the declared closed local grammar, with existing controls; no provider mismatch was demonstrated | -| Audit seam needs duplicate tests in another file; sub-microsecond and census optimization suggestions | The real transition tests already exercise the fifth seam and rollback substitutions. Quantization has explicit envelope controls. Duplicate tests or census caching do not repair a demonstrated contract violation | -| ADR navigation date, test placement and optional trace descriptor | Historical ADR navigation is preserved; local-loader tests sit with that loader. Standard 09 and ADR-0046 allow optional trace data without requiring its persistence | - -Local validation passes 1,845 unit, 286 architecture, four contract and 175 -Docker-free integration cases, plus 97 focused Docker cases (54 store, 27 -migration, 16 worker), with zero failures/skips. Guarded frontend passes 1,616 -cases (1,556 web, 60 SDK), with zero failures/skips/todos; lint/typecheck pass. -Release build reports zero warnings/errors; format, seven ADR-status script -controls, 2,587 relative links and 491 fragments pass. Planner predecessor and -isolated second-budget mutant controls fail; clean counterparts pass. Both fresh -independent correction review -rounds and complete correction-head CI remain pending in this local receipt; -the PR description owns live head/check evidence. - -#### External correction review round 1 - -Fresh GPT-6-astra xhigh store/security and GPT-6.1-sol xhigh proof/corpus -reviewers approve `44089707..13cd632` without introduced findings. Independent -verification passes seven focused PostgreSQL cases and 99 lifecycle cases. -The PostgreSQL rerun uses the existing Release binaries after a whitespace-only -source correction; a fresh committed-source build and CI remain separate checks. - -The corpus reviewer finds a pre-existing adjacent source-comment contradiction: -`IIntegrationEventHandler` still requires handler-owned per-module inboxes. -Its remarks now name ADR-0046's transport-owned shared inbox and P02b-3 boundary. -The adjacent `IIntegrationEvent` remarks also stop promising unconditional -partition ordering or describing the implemented contract guard as Registered. -These are documentation corrections, with no interface or runtime change. - -#### External correction review round 2 and local closeout - -Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus -reviewers independently approve `44089707..41ac2924`, with zero findings across -all 29 changed files. Both read the complete correction and the first round's -source-comment fix. The runtime reviewer independently inspects the completed -TRX counters; neither repeats the root's complete suites or mutation experiment. -Both correction review rounds are complete. No Accepted ADR text, grant or -consumer-delivery contract changes in this remediation. - -Complete local backend verification passes 3,396 cases: 1,845 unit, 286 -architecture, four contract, 175 Docker-free integration and 1,086 Docker -integration, with zero failures/skips. The 97 focused Docker cases above are a -subset, not additional cases. Guarded frontend passes 1,616 cases (1,556 web, -60 SDK), with zero failures/skips/todos; lint/typecheck pass. A fresh Release -build of `41ac2924` reports zero warnings/errors after the source-comment and -whitespace corrections. Five corpus controls, seven ADR-status script controls, -2,693 relative links and 500 fragments pass; historical P02b-0/P02b-1 records -and Accepted ADR text remain preserved. - -Correction-head PR CI and its real demo artifacts still require independent -verification after publication. This local receipt does not reuse the earlier -green head as evidence; the PR description owns live head/check evidence. - -### P02b-2 review of 3531a2eb (2026-10-13) - -The next external report was checked against `3531a2eb`, not adopted as an -instruction source. That baseline's seven required jobs and complete demo -artifacts pass in [run 38318773974](https://github.com/HodeTech/LearnStack/actions/runs/38318773974). -This follow-up requires its own review and CI evidence. No Accepted ADR body, -migration, grant, consumer-delivery contract or dependency changes here. - -- The earlier reverse-membership disposition is reconsidered using a real - direct/transitive `SET ROLE` control. The app guard already rejects elevated - memberships on new app connections; an administrator's later grant can still - elevate an existing app session. The dispatcher now detects incoming grants - on its next physical connection, enforcing the existing four-role boundary. - Superusers are excluded from that predicate because PostgreSQL implicitly - treats them as members of every role. This is grant-drift detection, not - continuous revocation. Four sync/async direct/transitive cases prove actual - escalation, refusal and healthy reconnection after restoration. An isolated - PostgreSQL comparison distinguishes the predecessor and corrected predicates. -- Credential census now rejects explicit configuration indexers with a - same-body `ConnectionStrings:` key/prefix, including compiled concatenation, - interpolation, formatting and static-readonly names. Unrelated configuration, - dictionary indexers and diagnostic text remain clean. This bounded check - does not claim arbitrary cross-method key dataflow. A separate planted control - closes `Assembly.CreateInstance`; `Activator.CreateInstanceFrom` was already - covered. Both omissions were reproduced against the predecessor detector. -- The constraint/RLS statement, shared-inbox and fifth-writer statuses, settled - ordering pointers and catalogue proof references now match current code. - Skills use a shipped public assembly marker in explicitly abridged examples. - The architecture method count is 194; Implemented rule count remains 192. -- Publication tests now cover successful/throwing completion, cleanup and - repeated/late cancellation. Wrong-kind store calls must leave the actual row - and audit unchanged. Test shutdown and publish timeouts use distinct values. - A source comment explains exact Npgsql microsecond truncation; the local API - environment comment names all three forwarded credentials. - -The remaining claims were checked against their actual scope: - -| Concern | Disposition | -|---|---| -| Startup options failure is reported as a credential error | Not on the shipped DI path: `OutboxDispatchStore` validates the same options before worker construction or source resolution | -| Broaden COMMIT catch to cure sticky terminal health | No demonstrated shipped exception escapes the existing provider/network/cancellation set. The dispatcher configures no custom driver logger. Failed reconciliation remains an unknown outcome even with catch-all; conservative health clears after successful terminalization | -| Non-admitted Normal claim hot-loops | Immutable registry and SQL exclude Pending identities before acquisition; unknown/retired/invalid rows already request terminalization. No current path reaches that invariant arm | -| Reject every unmapped JSON member | ADR-0046 explicitly uses the frozen payload options and compares declared facts; producer contracts enforce identifier-only fields. Unknown fields are not passed to the handler. A new stored-wire rejection policy is not inferred from this suggestion | -| Producer witness kind/subscription should anticipate subscriber minting | The current closed minting census admits only the producer store. P02b-3 owns a distinct subscriber capability and its identity controls; no subscriber factory is introduced early | -| Legacy-row diagnostics, blocking migration and attempt constants | Invalid facts deliberately refuse migration. Existing migrations remain immutable; checks/index creation need an owner maintenance window, with no online-migration claim. Tests pin six claims and the full backoff/DDL state; copying a new constant into historical migrations would not eliminate drift | -| UTF-8 SQL literals escape the literal census | Npgsql's command entrypoints accept strings. Decoding bytes is dynamic construction/dataflow outside this explicitly bounded literal census; raw byte data alone is not an executable SQL call | -| Platform credential rule is no longer independently sufficient | The whole-production credential/factory/consumer census independently pins both exact roots and their distinct sources. Repeating it inside the companion source rule adds no uncovered current boundary | -| COMMIT/probe stack assertions are redundant | Both failures are `NpgsqlException`; the stage-specific stack assertions distinguish their order. They supplement the physical outcome/no-duplicate proof and currently pass with the pinned driver | -| Ambient public-api overrides and seed validation should cover four credentials | Explicit ambient API overrides are an existing tested local-loader policy. Standalone seed consumes only Default and Migration; other ambient credentials never reach its child. Shared demo validates all four before startup | -| Forward proxy/cache/home environment into Seeder | The narrow child allowlist deliberately excludes ambient credentials/diagnostics; proxy values can themselves contain credentials. No failure on the documented restored-dependency path was demonstrated; the API's separate allowlist intentionally excludes `DOTNET_CLI_HOME` | -| Print the failed connection-string suffix | The fixed diagnostic is now safely visible. More detailed refusal messages are optional; values remain excluded and no further operational regression was reproduced | -| Ingress env tests depend on file order | Each loader test writes its own selected file before reading it; they are sequential, not concurrent. The later configuration test uses an explicit object, not that file | -| Duplicated construction-only factory helper | The remarks explain the intentionally absent worker/unhealthy private check. Sharing helpers across separate test assemblies would add a dependency without correcting behaviour | -| Skill index claims handler-owned inbox | Not reproduced: its generic inventory names an inbox guard but assigns no handler ownership; detailed skills now identify the shipped/P02b-3 boundary | -| Persist traceparent or measure recovery/terminal as publication duration | Trace persistence is optional. The duration histogram measures publication; recovery and terminal transitions do not publish and retain their own spans/outcomes | -| Retained partition also delays terminal acquisition | Deliberate local ownership: no further acquisition for that partition until callback and scope cleanup actually finish, including terminal work; ADR-0046's four-overrun saturation applies | -| Assembly-qualified identities, closed generics and invalid disposition label | Exact assembly-qualified identity plus explicit compatible aliases is Accepted. A declared closed generic is a concrete known type, not arbitrary loading. Invalid-envelope reason and the fixed `invalid` label remain distinct from unknown-type reason | -| Legacy non-NULL metadata should be backfilled | ADR-0057 requires new producer metadata to be SQL NULL; ADR-0046 deliberately terminalizes invalid legacy envelopes rather than silently rewriting their facts | -| Alternate health-registration dedupe and audit trigger | The sole production composition is pinned. A new trigger/privilege design is Phase 11 work, not an unreviewed replacement for the Accepted row-bound terminal seam | -| Squash migrations or mechanically gate published fragment counts | Existing migrations/history are preserved. Link/fragment totals are explicitly local checks, not CI enforcement claims; the prior and current source scans remain separate evidence | - -Local Release build reports zero warnings/errors; format verification passes. -Unit passes 1,847, architecture 287, contract four and Docker-free integration -175 cases, all with zero failures/skips. Twenty role controls and six focused -claim-kind/shutdown cases pass. The new compiled-probe helper's initial deferred -Cecil-body failure was corrected before the successful full architecture rerun; -the guard expectation was preserved. Seven ADR-status controls, 2,711 relative -links and 505 fragments pass. Historical delivery records and Accepted ADR text -remain unchanged. Complete Docker validation, both fresh independent review -rounds and correction-head CI remain pending in this initial local receipt; -the PR description owns final head/check evidence. - -#### Review of 3531a2eb: verification closeout - -Both fresh independent review rounds approve `3531a2eb..a5b1e723` with zero -findings across all 17 changed files. Each round uses a fresh GPT-6-astra xhigh -security/runtime reviewer and GPT-6.1-sol xhigh proof/corpus reviewer. All review -lenses were covered. Reviewers inspect source and TRX evidence without repeating -the root's full suites; the second proof reviewer independently confirms 194 -architecture methods, 192 Implemented rules and all 13 explicit method links. -No further runtime correction was required after the implementation commit. - -Complete local backend verification passes 3,408 cases: 1,847 unit, 287 -architecture, four contract, 175 Docker-free integration and 1,095 Docker -integration, with zero failures/skips. The 20 role and six focused claim-kind/ -shutdown cases are subsets of Docker integration, not additional cases. Release -build, format, seven ADR-status controls and the 2,711-link/505-fragment local -check pass. Historical delivery records and Accepted ADR text remain preserved. -No frontend source or dependency changed in this correction; the next real CI -run re-verifies frontend and demo artifacts along with the corrected backend. - -Both correction rounds and local validation are complete. Exact correction-head -CI remains pending in this local receipt; the PR description owns live checks -and artifact-backed evidence after publication. - -#### Snapshot interval correction (2026-10-13) - -The dispatch loop no longer forces a full queue snapshot after every successful -claim. It checks `SnapshotInterval` after completed iterations, while `didWork` -still controls idle polling. A controlled monotonic-clock integration case -dispatches three real rows: the initial snapshot survives successful work and -the last tick before the interval; the exact boundary refreshes it after the -next completed dispatch. Release build reports zero warnings/errors; format, -1,847 unit, 287 architecture and all 17 worker integration cases pass, with zero -failures/skips. Two fresh sequential independent reviews of `3620b421..3baf3a22` -approve with no findings. In an isolated tracked-source copy, reverting only the -production call to forced refresh makes the new case fail its retained-snapshot -assertion (one executed, one failed); the corrected case passes. New-head CI -remains pending in this local receipt; the PR description owns live checks and -artifact-backed evidence after publication. - -### P02b-2 merge and closeout (2026-10-13) - -The maintainer merged [PR #30](https://github.com/HodeTech/LearnStack/pull/30) at -2026-10-13 07:43:06 UTC. GitHub records final PR source -`4b4e3e40cf9147262934652c4eb9621258356f4c` and squash merge -`6a277770e46a7f4ea3574d9d6891d1802cb8fa90`, whose parent is previous main -`b1f6f21cab556ee7ba497dfc0d64e51b8cf1dad8`. Source and squash merge have the -identical tree `c3d02e3368365a108cb8321ccb3fcbc9cec2e575`. Development incorporates -the main merge without switching branches or rewriting published history. - -All seven required checks pass in the -[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38358520310) -for that source; CodeRabbit also reports success. The tested synthetic merge is -`d347a60a36fc0001656c3d95d7551bc35d818b91`. Verified artifacts record: - -- **3,409 backend passes**, zero failures/skips: 1,847 unit, 287 architecture, - four contract, 175 Docker-free integration and 1,096 Docker integration cases. - The snapshot-interval regression passes on that exact source. -- **1,616 guarded frontend passes**: 1,556 web and 60 SDK, zero - failures/skips/todos; frontend lint, typecheck and builds also pass. -- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, nine - screenshots and matching source/checkout identities and report digests. - Automated accessibility is 1 throughout, CLS is 0 and normalized initial JS - gzip is 106,357–106,552 bytes. Proof finishes in 631.094 seconds and owned - cleanup passes; timing medians remain advisory. -- OpenAPI base/head specifications are byte-identical, with SHA-256 - `69333252a95d4179e319512e5f45db2781d12eb003d405a509fa047d64e8e012`. - -These are final PR-head results, not a claim about a new post-merge or local -full-stack run. **P02b-2 is closed.** All four steps and verified review fixes -are delivered, including recovery-index alignment, credential confinement, -terminal COMMIT reconciliation and interval-bound observation. Two independent -review rounds per step and correction bundle remain recorded above. Earlier -dated receipts retain their pre-merge wording; all Accepted ADR files remain -unchanged by this closeout. Phase 02b remains in progress. - -**Next: P02b-3 decision pass.** Reverify the Accepted G1/G6/G7 subscriber -contract and G19 handoff against the merged code, then plan delivery and its -proofs before implementation. P02b-3 owns durable acceptance, shared inbox and -independent delivery ledger, subscriber retries/terminal MUST audit, targeted -internal replay, both real Customization defaults subscriptions and semantic -key/version Seeder handoff. The effects remain `card@1` content type and -`plain@1` taxonomy, preserving existing authored/lifecycle state. Required -production subscriptions remain Pending until that boundary is implemented; -producer dispatch does not claim durable consumer effects. - -Background jobs, API authentication, realm reconciliation, BFF sessions and -phase-exit enforcement remain P02b-4–8 in the -[packet table](#packets-and-decision-gates). Operator recovery permissions/routes -remain Phase 03; broker adapters and production readiness remain Phase 11 on -their recorded triggers. This closeout starts no later packet and makes no new -architectural decision. - -**Documentation-only closeout validation.** Five local Release corpus controls -and seven ADR lifecycle/workflow controls pass, zero failures/skips. The 14 -changed Markdown files resolve 1,577 relative links and 333 fragments without -errors; added prose wrapping and whitespace checks pass. All prior P02b -delivery/review receipts and every ADR file are byte-preserved. Runtime suites -are not rerun locally for this documentation-only change; the final PR artifacts -above supply their evidence. - -### P02b-3 decision package (2026-10-13) - -**Accepted — 2026-10-13, @cemil.** The maintainer approves the complete package -and six implementation steps, each with commit and two independent review rounds. -Acceptance precedes runtime implementation; it claims no delivered subscriber. -The audit baseline is `development` at -`652004290c9696e65e68817f223839d4a0f02137`, after PR #30's verified merge. -Three independent read-only audits covered the accepted contracts, storage/ -privilege/owner lifecycle, and Customization/Seeder convergence. Their findings -were checked against current source; they report inspection, not passing tests. - -[ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) -already accepts G1/G6/G7's shared transport-owned inbox, stable subscriptions, -durable acceptance, independent retries, atomic terminal audit and targeted -internal replay. [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) -accepts both create-only default effects and the Seeder handoff. This package -concretizes the storage, runtime and enforcement details those records assign to -P02b-3. It does not reopen their decisions or authorize jobs/authentication. - -#### Document and code review - -The review follows the roadmap entry reading, then ADR-0003/0006/0010/0017/0023/ -0033/0036/0038/0040/0042/0043/0044/0046/0057, applicable Backend, Database, -Testing, Observability, Security, Documentation, Audit, Infrastructure and -Architecture-test standards, architecture 03/09/10/15/29/31/32, the Tenancy/ -Customization/Audit specs and matrices, and event/seed/migration/test skills. -The actual producer, bus, registry, transaction/audit coordinators, terminal -witness/store, Customization writers/readers and Seeder are the implementation -premises. Acceptance history remains the authority for any proposed ADR erratum. - -| Verified premise | Required P02b-3 action | -|---|---| -| `InProcessEventBus` invokes and constructs handlers immediately; it owns no durable acceptance or inbox | Replace that publication outcome with durable acceptance; execute only through the independent delivery owner | -| `OutboxEventRegistry` owns stable IDs/readiness; the handler registry carries only concrete handler metadata | Preserve one manifest identity source; bind each Active ID to exactly its declared contract and handler | -| Common owner completion drains events, writes MUST audit and commits without a delivery completion participant | Add a closed delivery-specific final fence/gate while preserving request ownership and all existing announcement methods | -| `EventTerminalTransition` and the fifth audit seam accept only producer terminalization | Extend the restricted actual-row witness and operation census to the subscriber terminal writer | -| Customization's current readers exclude deleted rows and discover by ID or Active key | Add owner-local, tenant-protected concept history across every revision/status, including soft deletion | -| Register uniqueness protects one revision, not concurrent initialization versus another revision | Serialize initialization and concept registration on the same transaction-owned semantic key | -| Seeder requires fixed built-in IDs; its counts assume separate register/publish acts | Resolve built-ins semantically, preserve warm IDs, share initialization, and update inventory/fixtures without weakening authored-ID checks | -| Direct delivery production has no incoming-event causation source | Carry a trusted delivery entry through nested producer frames; keep tenant/org authority in the announcement | -| Existing aggregate/audit request censuses omit integration handlers | Add nonempty production-consumer coverage and planted violations before marking consumer rules Implemented | -| Existing bus logs raw exceptions and adds exception details to spans | Replace transport-owned diagnostics with bounded codes before enabling production subscriptions | - -These gaps are expected P02b-3 work; they are not retroactive P02b-2 failures. -Required production manifests stay Pending until acceptance, execution and Seeder -handoff are ready together. Test-owned Active contracts exercise earlier steps. - -#### Accepted storage and authority details - -1. **Two shared infrastructure tables.** `event_deliveries` retains one copy of - the validated producer envelope per `(tenant_id, subscription_id, event_id)`. - `inbox_messages` holds the completion identity for that same tuple, with no - surrogate UUID. Neither depends on a live producer row. A producer purge - cannot remove a pending delivery's payload. No third dead-letter store/topic - or arbitrary metadata is added. Retained copies and their retention dependency - enter the P02b-8 inventory; actual purging remains Phase 11. -2. **RLS and classes.** The ledger is tenant-owned and organization-scoped because - its envelope carries organization metadata and payload. Use the canonical - tenant-and-organization policy, ENABLE and FORCE, with explicit WITH CHECK. - The inbox is tenant-wide identity machinery with no payload/org authority. - Both use explicit tenant predicates in application SQL. No foreign key to - `outbox_messages` or cascade from business tables controls retention. The - executor restores the stored organization before reading the envelope; - an unmarked event never widens a present organization to null. -3. **Closed grant budget.** `learnstack_app` receives RLS-protected acceptance - INSERT/SELECT and only the ledger completion-column UPDATE. Inbox claim is an - INSERT of an immutable completion marker inside the uncommitted business - transaction; uniqueness serializes duplicates before construction. Only owner - success makes that marker durable; rollback removes it. Its timestamp records - the claim; ledger completion records business completion. Successful app-role - completion retains token/expiry as inert provenance because it cannot UPDATE - those fields. Completed rows are excluded from acquisition, recovery, - terminalization and replay. The bypass scheduler - receives column SELECT for tenant/subscription/event identity, organization, - declared type/topic/partition, occurrence, attempts, availability, lease, - completion, terminal/replay state and bounded diagnostics; UPDATE covers only - scheduling/status columns. It receives no payload or causal-envelope SELECT, - no ledger INSERT/DELETE and no inbox privilege. Application INSERT grants name - acceptance columns only, excluding caller-supplied scheduling/terminal state. - The existing Audit-chain - INSERT-only grant is reused; no fifth role or business-table grant is added. -4. **Canonical detail before code.** Standards 05 owns complete DDL, constraints, - exact column grants and matching pending/recovery/terminal indexes. A new - Platform-chain migration implements it; historical migrations stay intact. - Identity, subscription grammar, nonnegative attempts, lease pairing, - mutually exclusive completion/terminal state and the 256-byte error cap have - CHECKs. Completion and terminal UPDATE predicates match the actual grants; - tests run them as the real roles, not merely inspect grant text. No P3 role - purges these stores; Phase 11 must decide the minimal retention grants and - ordering before installing its purger. -5. **Accepted envelope is immutable.** Publication validates the envelope and - Active manifest, restores its scope, and inserts every required delivery in - one app-role acceptance transaction without constructing business handlers. - An existing identical identity/envelope is idempotent; a conflicting envelope - refuses acceptance without overwriting the first copy. Canonical serialized - data, including organization and causal metadata, determines equality, not - raw `jsonb` whitespace. An existing accepted subset can be completed safely. - An uncertain acceptance COMMIT leaves the producer retryable; subscriber - execution failures never flow back into the producer's retry budget. - -Scoped application completion is a constrained call path, not a claim that column -grants sandbox arbitrary compromised app SQL. Likewise, the terminal audit's -tenant binding is the row witness, not BYPASSRLS GUCs. No tenant-status lookup is -added as an asynchronous hold/drop policy; Phase 02c retains that decision. - -#### Accepted execution, retries and replay - -Each attempt owns a fresh app-role scope. Announce the validated routing tenant/ -organization before resolving a module context, read and revalidate the retained -envelope by its claimed identity/token under RLS, then claim the inbox before -handler construction. Completed duplicates skip construction. Effective actor is -SystemActor; original causal actor and incoming EventId remain trusted producer -metadata. Ordinary execution refuses privileged subscriptions. Phase 03's -erasure execution contract remains separate. - -The outer audit coordinator classifies the declared handler before construction; -nested commands retain their own classified intents. No module writes audit SQL. -The common transaction owner drains domain events, writes pending MUST audit, -performs the delivery completion UPDATE with tuple/token/unexpired database lease, -and atomically admits physical COMMIT against a sticky completion gate. A failed -fence or a gate closed by cancellation poisons and rolls back all work. The gate -arbitrates Open -> Closed versus Open -> Committing; cancellation after commit -admission is an unknown/Indeterminate outcome, not guaranteed rollback. Durable -inbox/ledger state decides recovery, including an uncertain sixth-attempt COMMIT. -This adds no IUnitOfWork session setter, retargeting or independent business commit. - -| Policy | Accepted initial bound | -|---|---| -| Host and acquisition | API-owned subscriber worker; one just-in-time normal claim; reuse the confined keyed dispatcher source | -| Normal claims | Six per subscription/event, including claims whose execution outcome is unknown | -| Five retry delays | 1 s, 5 s, 30 s, 5 min, 1 h, using database availability time | -| SQL / terminal transaction | 5 s | -| Complete execution wait | 10 s, including construction, handler and owned cleanup; timeout closes the commit gate | -| Lease | 30 s, with validated execution/transition margin; no renewal promise | -| Idle poll / snapshot interval | 200 ms / 5 s; successful work does not force a scan | -| Progress / stale health | 45 s | -| Cancellation-ignoring work | At most four retained tasks; block their local partition, unhealthy while retained, stop acquisition at capacity | -| Shutdown | One total 30 s wait; live task resources remain owned until actual completion or process exit | - -The worker retains and observes cancellation-ignoring tasks with their live scope; -it does not dispose a running callback or promise managed-code termination. -This is one additional in-process subscriber worker in the existing API host; -it neither creates a new host nor changes the producer's existing bounds. Its -four-task and 30 s bounds apply to this worker, not an added whole-host shutdown -guarantee. All stop waits also observe the host's shared shutdown cancellation. -If scope disposal faults or times out after acknowledged business COMMIT, the -completed ledger/inbox remain definitive; cleanup cannot undo or rerun that -effect. Unknown completion reconciles durable state. Overrunning cleanup remains -task-owned and consumes capacity until actual disposal finishes. -Recovery replaces expired ownership before transitions and spends no additional -attempt. Ordinary failed/unknown outcomes use independent backoff. Expired claim -six requests terminalization without a seventh invocation. Requests for terminal -state are never normal execution candidates. Audit refusal retries terminalization -alone. Closed reasons distinguish invalid envelope/subscription from exhaustion; -descriptors expose bounded stage/category codes, never raw exception text. - -Subscriber terminalization uses the same fifth audit seam and a subscriber witness -minted only from its successful fenced UPDATE result. It binds actual tuple, -organization, token, attempts, reason and live connection/transaction. The -Tenancy catalogue/matrix registers `platform.delivery.dead_letter` as off-path -MUST/SecurityEvent when this writer ships. Subscriber terminal audit uses the -validated attempt trace and bounded event/subscription/reason/attempt metadata; -it does not grant the bypass scheduler causal-envelope or payload access merely -to reuse the producer witness. Business execution retains original causality. - -Internal replay takes exactly one declared tenant/subscription/event tuple. It -admits an Active ordinary subscription and completed terminal ledger row only; -live claims, pending terminalization, unknown/retired/Pending subscriptions and -completed business deliveries are refused. The fenced reset clears that row's -terminal request/timestamp, attempts and bounded error, makes it due and invalidates -old ownership. It never deletes/resets an inbox or republishes a broadcast. -The scheduler later invokes only that subscription. A completed inbox still -short-circuits business construction if an earlier uncertain attempt committed. -No replay HTTP route, permission grant or operator producer reset ships here. - -Standards 10 owns subscriber metric names/dimensions and the registered, unmapped -health check. Keep no tenant/event/partition/trace labels; subscription/event-type -labels are finite declared-registry values only. Snapshot gauges perform no SQL; -refresh failure preserves the prior snapshot and reports stale/unhealthy state. -Producer and subscriber attempt/failure/terminal/dedup signals remain distinct. -The API's `/healthz` and anonymous public contract remain unchanged. - -#### Accepted defaults and Seeder handoff - -The two stable identities remain -`customization.initialize-content-type-default.v1` (`card@1` content type) and -`customization.initialize-taxonomy-default.v1` (`plain@1` level taxonomy). -Each effect owns exactly one root. New roots are validated, created and made -Active in one transaction/save, with a Customization-owned UUIDv7, one generation -increment and one classified initialization MUST audit. Shared owner-local -initialization commands let the Seeder use the same logic without a worker, -dispatcher credential, raw SQL or new tenant-context setter. Event handlers -coordinate only their own effect through those commands; they do not combine roots. - -A transaction-owned semantic concept lock serializes each initializer with the -ordinary registration writers for `(tenant, aggregate-kind, key)`. Under that -lock, any revision in Draft/Active/Deprecated or soft-deleted history means -preserve, not initialize. A successor-only concept also counts as touched. -Whichever writer commits first defines whether the concept was untouched; -initialization never overwrites, republishes, revives or fills a missing revision -of an already touched concept. Parameterized owner-local history reads retain -explicit tenant predicates and RLS; no query-filter bypass is introduced. -Same-key locks do not create a cross-tenant authority path. - -The initialization operation classifies preserved/no-op attempts explicitly; -it changes no root or generation. A new delivery may record an initialization -attempt without entity changes; a completed duplicate constructs no handler and -creates no second business audit. Seeder pre-verifies completed built-ins before -sending an initializer, so a completed rerun remains write/audit-neutral. -Fresh inventory counts reflect one initialization audit/bump per built-in, -not the old two register/publish acts. That is the uncontended creation count; -separately classified preserved attempts after a seed/delivery race may add an -audit without a generation bump. Tests distinguish creation from no-op attempts, -and count the actual deduplicated delivery identities rather than asserting that -every asynchronous interleaving has the Seeder-only audit total. Historical -receipts are not recounted. - -Built-in Seeder verification discovers semantic key/version, then validates exact -Active state and built-in shape while retaining the stored ID. Existing matching -non-demo IDs pass. Preserved Draft, deprecated, deleted, successor-only or -mismatched definitions remain untouched; if they cannot satisfy the declared -demo inventory, seeding refuses with a bounded mismatch instead of claiming -completion. Tenant-authored definitions/courses/lessons retain exact declared -IDs and exact pins. Consumer and fresh Seeder races converge in both winning -orders; an unexpected database failure is not a blind retry/overwrite. - -#### Decision vehicles and documentation actions - -No new architecture decision is proposed: these details fit ADR-0046/0057's -explicitly delegated P02b-3 boundary. If implementation disproves that fit, stop -and prepare a new decision for maintainer review before changing the contract. -Acceptance of this package authorizes the following already-required changes, -with original Accepted bodies/metadata and historical receipts preserved: - -- **ADR-0023:** verify the inbox minting-list wording at its acceptance commit; - add the ADR-0041 inline erratum and its own dated amendment, because inbox - identity reuses the producer EventId rather than minting a surrogate. This - corrects the listed table, not the UUIDv7 decision. -- **ADR-0044:** append the additive capture-exclusion clarification for the - shared inbox and delivery ledger; add subscriber fifth-seam/operation navigation - already authorized by ADR-0046. Explicit business intents remain audited. -- **ADR-0046/0038/0057:** dated delivery/navigation notes when their P3 obligations - actually ship; no premature completion claim or replacement of earlier bodies. -- **Mutable carriers:** canonical Inbox/ledger DDL and grant matrix in Standards - 05; lifecycle/diagnostics/audit rules in 02/09/10/11/18/20; canonical tests in 21; - architecture 03/09/10/15/29/31/32; glossary; module specs/matrices; event/seed/test - skills; Seeder inventory/fixtures and `BuiltInCustomizations` creator remarks. - Reconcile only touched claims; do not duplicate an ADR or RLS template. -- **Hub pointer:** verify the sibling repository's per-module inbox dependency - and coordinate its documentation pointer before P3 closeout, as ADR-0046 requires. - The current sibling `docs/roadmap/README.md` P02c-3 row still names per-module - inbox tables; replace only that dependency with a link to ADR-0046's shared - transport-owned inbox contract when coordinating the documentation change. - No Hub runtime, HTTPS contract or branch change is authorized by this package. - -At acceptance, Standards 21 registers the following additional canonical rules -as Registered, with their behavioural/structural owners; no passing enforcement -is claimed before code: - -- `Integration_Event_Publication_Is_Durable_Acceptance` — real-role acceptance, - immutable duplicate/collision handling, partial/unknown COMMIT and no construction. -- `Delivery_Retries_And_Replay_Are_Subscription_Scoped` — independent budgets, - terminalization, completion gates, final-claim recovery and targeted replay. -- `Delivery_Terminal_Audit_Identity_Is_Row_Bound` — restricted subscriber witness - census and atomic matching/mismatched identity/transaction proofs. -- `Delivery_Execution_And_Observation_Are_Bounded` — actual hosted execution, - retained resources, shutdown, closed diagnostics and snapshot/health emitters. -- `Customization_Default_Initialization_Preserves_Touched_Concepts` — one-root - useful creation, all lifecycle preservation and serialized registration races. -- `Seeder_BuiltIns_Use_Semantic_Identity` — generated/warm IDs, exact shape and - authored IDs, no-worker operation, rerun neutrality and real delivery races. - -Extend the existing `Integration_Event_Handlers_Use_InboxGuard` and -`Integration_Event_Handler_Restores_Tenant_Context` obligations rather than -inventing alternate names for their claim/owner/scope assertions. Extend the -existing credential confinement census only for the named subscriber scheduler/ -store; business handlers and application execution never receive bypass access. - -#### Six accepted implementation steps - -Each step commits on `development`, then completes two fresh independent review -rounds. Verify findings against current code, fix valid findings, validate and -commit fixes before the next round/step. A clean review needs no empty commit. -Continue automatically unless a real blocker or new maintainer decision arises. - -1. **Accepted detail, schema and privileges.** Record approval before runtime; - register canonical proof obligations, reconcile the named ADR instruments, - implement Platform migration/table classes/RLS/grants/indexes and test - forward/down/reapply, actual role permissions and tenant/org isolation. - Production subscriptions remain Pending. -2. **Durable acceptance and inbox primitives.** Replace immediate broadcast - execution with validated transactional acceptance; implement immutable envelope - collision/duplicate semantics and transport-owned inbox claims. Prove partial - and uncertain acceptance, independent identities, concurrent duplicates and - construction-free publication with real PostgreSQL. -3. **Business owner and completion gate.** Implement fresh application scopes, - restoration before resolution, classification, incoming-event causation, - common owner completion and sticky commit arbitration. Prove business/inbox/ - outbox/MUST-audit/ledger atomicity, canceled/expired/stale attempts, no-listener - metadata, owner cleanup and unknown COMMIT without activating production defaults. -4. **Subscriber scheduling, terminalization and replay.** Implement independent - leases/attempts/recovery, witnessed terminal MUST audit, targeted reset, bounded - task ownership, minimal diagnostics and snapshot health/metrics. Prove sibling - independence, sixth-claim recovery, late completion, audit rollback, identity - substitutions, safe shutdown and replay fences using the actual worker. -5. **Useful consumers and convergent seed.** Add the two one-root initializers, - concept serialization/history reads and semantic verification; migrate Seeder - and fixtures, then activate both real subscriptions together. Prove untouched - creation, every preservation lifecycle, warm IDs, strict authored pins, repeated - seeding and concurrent fresh seed/delivery in both winning orders. -6. **Enforcement and PR closeout.** Complete production-handler/call-path censuses - with planted clean/dirty controls, full Release build/format/backend regression, - affected frontend/launcher tests and real demo/Lighthouse proof. Reconcile all - current-state docs and accurate test counts; open the PR only after every step - and both reviews finish. Verify all seven required CI checks at the exact head; - never claim merge or delivery of P02b-4–8. - -#### Decisive acceptance proofs - -- Actual app-role tenant/org isolation and real bypass column grants: scheduler - payload/inbox reads and app retry/reset writes fail; allowed acceptance and - completion succeed. Completed inbox rows persist across replay and producer purge. -- Two same-module subscriptions and concurrent duplicates yield one business - effect each. A duplicate waits for the first transaction; rollback permits a - new claim. Handler construction failure is independent of acceptance success. -- Fenced ledger completion, business changes, produced events and MUST audit all - roll back on a stale/expired token or closed gate. Kill the fence/gate in a - controlled mutant to prove sensitivity, including timeout persistence failure - followed by an ignored-token late callback. -- Real lost-COMMIT acknowledgement recovery, including the final subscriber - claim, does not repeat committed business work or terminal audit. Cancellation - after commit admission never claims certain rollback. Postcommit disposal fault - and timeout controls retain durable completion, prevent effect replay and keep - live cleanup resources safely owned. -- Subscriber terminal draft tenant/org/event/subscription/operation/transaction - substitution rolls back both transition and audit; matching org-scoped work - commits. Audit refusal never makes terminal-requested work executable again. -- Targeted replay changes one terminal row only; completed sibling/inbox rows - and producer attempts stay unchanged. Stale pre-replay callbacks cannot complete. -- Nonempty production censuses cover every module layer and the actual handler, - manifest, owner, inbox, terminal-witness and credential sites. Planted direct/ - interface/helper bypasses and clean controls distinguish enforcement from an - empty or narrowed subject set. Extend one-root and audit-registration coverage - to integration handlers; do not only count request handlers. -- Logs/spans/descriptors/artifacts reject planted payload, secret, raw type and - exception values. Finite telemetry labels, prior-snapshot retention, exact - refresh cadence and no SQL gauge callbacks have positive/negative controls. -- Runtime proof includes actual TenantCreated backlog activation, both defaults, - ordinary app-role isolation and warm/fresh Seeder races. Test-only subscribers - alone cannot close the packet's useful-flow requirement. - -#### Decision-package reviews and validation - -Two fresh, sequential, read-only reviews examined the proposed working-tree -package against baseline `65200429` and the current accepted contracts/code: - -- **Round 1 — GPT-6-astra, high:** Approve, no Blocker/Major. Clarifications for - postcommit disposal, inert completed-row lease provenance and creation/no-op - audit counts were verified and incorporated before round 2. -- **Round 2 — GPT-6.1-sol, high:** Approve, no Blocker/Major/Minor. Independently - checked the completion/grant model, defaults/Seeder policy and ADR-0023's - acceptance-time natural inbox identity. It found no additional decision gap. - -Root validation passes all five `CorpusConsistencyTests` and seven ADR-status -controls, with zero failures/skips. The changed phase document has 184 checked -relative links and 98 fragments, with no missing targets/anchors. Added prose -passes the 88-column check with documented link/table exceptions; whitespace is -clean. Every Accepted ADR and all earlier P02b delivery/review receipts remain -byte-preserved. This is documentation validation, not a P02b-3 runtime test run. -The package remains Proposed until explicit maintainer approval; that approval -and the registered obligations precede the first runtime implementation commit. - -#### Maintainer acceptance (2026-10-13) - -The maintainer's explicit answer, "Paketi onaylıyorum; implementasyona geç", -accepts this package after both decision-package reviews. Their preceding receipt -records the pre-approval state. The six steps and two-round loop are authorized -on development. G1/G6/G7/G19 keep their accepted architectural answers; concrete -storage, authority, execution/replay, default and Seeder details now have this -accepted vehicle. Catalogue additions remain Registered until their proofs ship. -The decision acceptance, ADR-0023 erratum and ADR-0044 capture clarification are -committed before the first P02b-3 runtime change. - -### P02b-3 Step 1 — shared storage and privileges (2026-10-13) - -**Complete; both independent review rounds complete.** Decision acceptance -`63363ac` precedes this runtime change. EF generated Platform migration -`20261013083903_add_event_delivery_and_inbox`; its raw infrastructure tables add -no EF entity or model snapshot change. Standards 05 owns the complete applied -DDL, table classes, constraints, total-order indexes and exact column grants. - -The org-scoped ledger retains a subscription envelope independently of producer -retention. The tenant-wide inbox uses the producer event identity and subscription -without a surrogate; database guards refuse UPDATE, DELETE and TRUNCATE even as -the owner. No P3 role receives purge privileges. The app role accepts only immutable -envelope columns and completes only `processed_at`; the scheduler receives routing/ -status columns and nine scheduling UPDATE columns, excluding payload, causal -metadata, inbox access and business completion. Completed rows retain inert lease -provenance and are excluded from every scheduler index. Real subscriptions remain -Pending; this step claims no acceptance or business-delivery runtime. - -`EventDeliveryMigrationTests` exercises 73 real-PostgreSQL cases: permitted SQL, -exact grants and forbidden capabilities, tuple identity/ASCII grammar/state, -immutable guards with removed-trigger dirty controls, matching index/order plans, -producer-retention independence, canonical-document catalog parity and disposable -Down/reapply. The existing all-table fixture now seeds both stores for both tenants, -including distinct ledger organizations, and marks fixture ledger canaries complete. -The general tenant-isolation, foreign-write and grant sweeps include them. -Ledger-specific organization and scope-hatch proofs are recorded below. -Standalone Platform migration proofs install Tenancy's shared organization guard -first, matching the documented deployment sequence; historical migrations are intact. - -Validation before the implementation commit: Release build with `CI=true` has -zero warnings/errors; 164 focused schema/migration integration cases and all 287 -architecture cases pass, zero failures/skips. The seven ADR-status controls pass. -Format and whitespace validation pass; 1,180 relative links and 286 fragments -resolve without errors. Earlier receipts and Accepted ADR text remain intact. -Unit/frontend/runtime-worker suites are -not rerun for this schema-only step. Subsequent steps own acceptance, execution, -subscriber scheduling, useful defaults and full packet regression. - -#### Step 1 review round 1 - -Fresh GPT-6-astra/high reviewed every file in `63363ac..ad57a1b` through the -standards and code-review lenses. It requested changes for one missing required -proof: existing cross-organization/scope-hatch behavior tests name other tables, -so they do not establish the new ledger's organization boundary. Root independently -confirmed this gap; the current migration predicates were not found defective. - -The correction adds app-role ledger read, exact/null/mismatched acceptance and -fenced completion tests, with and without the tenant read hatch. Five live leased -canaries distinguish tenant-wide, own/sibling organization and foreign-tenant rows. -Own-scope controls remain writable. Disposable policy mutants prove a missing -organization read term leaks the sibling, a read hatch copied into WITH CHECK -admits forbidden acceptance, and removing only the restrictive UPDATE guard -changes zero matched rows into the remaining WITH CHECK's RLS refusal. The last -control does not claim a write bypasses both protections. No production policy or -grant changes are needed. The correction passes 125 focused ledger/organization -integration cases, zero failures/skips, with `CI=true` Release. Review round 2 -follows the correction commit. - -#### P02b-3 Step 1 review round 2 and closeout - -Fresh GPT-6-sol/high independently reviewed all 13 files in `63363ac..fe6f9c7`, -including the correction rather than only its receipt. Verdict: Approve, no -Blocker/Major/Minor. It verified the real-role organization proofs and weakened -policy controls, exact grants, RLS, immutable tuple inbox, ordered indexes, -canonical DDL parity, reversal and documentation scope. It made no edits and -inspected the tests; it did not independently rerun the reported suites. - -Root's correction run passes 125 ledger/organization integration cases, including -all 83 current `EventDeliveryMigrationTests`, zero failures/skips. Earlier Step 1 -verification passed the 164-case schema/migration group and 287 architecture cases. -The correction changes tests and their record only; format, documentation and -whitespace checks pass. Implementation commits are `6b1efef` and `ad57a1b`; -`fe6f9c7` closes the verified round-one proof gap. Step 2 follows automatically -under the accepted package; production subscriptions remain Pending. - -### P02b-3 Step 2 — durable acceptance and inbox primitives (2026-10-13) - -**Implemented; both independent review rounds complete.** `InProcessEventBus` now -validates the concrete canonical contract and required Active manifest, restores -publication context before creating a fresh application scope, and commits all -subscription envelope copies in one announced transaction. It constructs no -business handler. Exact identity plus canonical immutable fields distinguishes -idempotent duplicates from conflicting or inaccessible organization copies. -Matching subsets complete; a later collision rolls back earlier new copies. -Uncertain acceptance COMMIT remains producer-retryable. Only explicit intentional -absence may acknowledge without deliveries; Pending/unknown/retired contracts -refuse rather than silently reach zero handlers. - -`IInboxGuard`/`PostgresInboxGuard` claim only the tuple on the live, writable, -unpoisoned announced app-role transaction. PostgreSQL uniqueness waits for a -competing transaction: commit yields an existing identity; rollback permits a new -claim. The primitive owns neither connection nor commit. Business completion, -classification, independent execution and timeout gates remain Steps 3–4; -production default subscriptions remain Pending until Step 5's complete path. - -`DurableEventAcceptanceTests` and `InboxGuardTests` exercise 36 PostgreSQL cases: -construction-free acceptance, immutable-field collisions and JSON key-order -equivalence, matching/conflicting subsets, independent publishers and forced -unique-key waits in both commit/rollback orders, uncertain COMMIT acknowledgement, -actual tenant/org scope, fresh owner transactions, cancellation and inbox admission. -The fixture uses the production AsyncLocal accessor; a forced blocked publication -shares its provider with another tenant's independent successful publication. -Their blocker observers own finite cancellation deadlines. Root corrected the -initial duplicate test's shared process serializer before claiming SQL concurrency. -The canonical durable-acceptance catalogue rule is Implemented; the larger handler/ -inbox ownership and production census rules remain Registered. - -The former 32 immediate-handler bus unit cases no longer describe publish success. -Eight publication unit cases cover refusal boundaries, canonical runtime routing, -context before scope construction and restoration, intentional absence and queued -cancellation. Actual handler construction, invocation, internal handler dispatch, -per-subscription scopes, causal actor/trace, foreign cancellation, async faults and -cleanup are explicit Step 3/4 obligations; this step claims none of those execution -proofs. Existing producer worker timing/cleanup proofs use a disclosed scoped -publication wrapper around the real acceptance adapter. It deliberately models -cancellation-ignoring publication and real DI cleanup ownership. A separate -unwrapped-worker case proves durable acceptance without business construction. - -#### Step 2 validation before review - -The final `CI=true` Release solution build reports zero warnings/errors. The unit -suite passes 1,823 cases and architecture passes 287, with no failures/skips. -The 36 acceptance/inbox cases plus all 18 producer-worker cases pass together -(54 Docker cases). Foundation's canonical manifest registration replaces two -old Persistence-only composition fixture assumptions; the fixtures now exercise -the actual registration without opening a database or adding a second manifest. -The focused composition/corpus run also passes seven cases. Seven ADR-status -controls, format verification and whitespace checks pass. These are local receipts; -no PR-head CI or subscriber-owner delivery is claimed. Both fresh review receipts -follow below before Step 3 begins. - -#### Step 2 review round 1 - -A fresh GPT-6-astra/high reviewer examined every file in `80a3261..78992fc` and -approves with zero Blocker/Major findings. It independently passes all 36 new -acceptance/inbox Docker cases; the other local receipts above were inspected, -not rerun. One Minor catalogue link still named the renamed immediate-handler -worker proof. Root verifies the method rename and updates the label to the actual -acceptance proof. No runtime change is needed. Documentation links/fragments, -historical-record preservation and whitespace checks pass after the correction. -The second fresh review follows the correction commit. - -#### Step 2 review round 2 and closeout - -A fresh GPT-6.1-sol/high reviewer independently examines all changed files in -`80a3261..bce0bc7` and approves with zero Blocker/Major findings. It independently -passes 36 acceptance/inbox, 18 producer-worker, ten focused publication/composition -unit and all 287 architecture cases, with zero failures/skips. It reports one -Minor XML-comment grammar error; root verifies and removes the extra word. -Documentation/fragment, historical-preservation and whitespace checks pass. -Implementation is `78992fc`; `bce0bc7` corrects the verified round-one reference. -No runtime fixes were required. Step 3 follows automatically under the accepted -package; production subscriptions remain Pending. - -### P02b-3 Step 3 — business owner and completion gate (2026-10-13) - -**Complete; both independent review rounds complete.** -The closed prepared-owner entry announces the routing tenant/org and binds the -actual frame, unit, transaction and generation before retained-envelope loading. -Full validated event context replaces any inherited caller context before module -resolution. Inbox claim precedes classification/handler construction. A duplicate -skips business classification/construction and completes under the same final fence. - -Requests and deliveries share the common owner body: successful-save domain drain, -producer invariants, MUST audit, exact-row lock and fresh expiry check, sticky gate -admission, then physical COMMIT. No delivery opens a raw frame and calls the old -entry as a joiner. Incoming-event causation reaches nested production; immediate -domain-event identity takes precedence. SystemActor remains effective while closed -audit metadata preserves original causal actor and incoming event identity in both -writing paths. Shared audit fallback/reconciliation diagnostics suppress raw -exceptions only in event context; ordinary HTTP diagnostics remain unchanged. - -The one-use completion gate distinguishes cancellation before admission, unknown -COMMIT after admission and acknowledged durability. Npgsql retains successful -transaction disposal for owned cleanup, so an acknowledged commit reaches its -receipt before disposal faults or hangs. Cleanup before reuse and stale-frame -protection remain enforced. The executor retains its callback, frame and scope -through actual cleanup; scheduling deadlines/capacity/shutdown remain Step 4. -Ordinary versus privileged execution is explicit manifest metadata; P3 supplies -no privileged executor. Retained Active work may execute despite a Pending sibling, -while the producer's whole-event Pending hold remains unchanged. - -Production defaults remain Pending. Two fresh sequential review receipts follow -before Step 4 begins. - -#### Step 3 validation before review - -The `CI=true` Release solution build has zero warnings/errors. All 1,847 unit and -289 architecture cases pass, zero failures/skips. The 33 new delivery execution -and four physical Npgsql cleanup cases pass together as 37 Docker cases. They -exercise constructor/invocation/null-task failures, caller versus foreign -cancellation, SystemActor and original causal metadata before construction and -through cleanup, direct/nested/domain-event production, atomic five-leg rollback, -duplicate short-circuiting, ownership loss after saved work, expiry behind an -unchanged row lock, lost COMMIT acknowledgement at attempts one/six, and cleanup -faults/hangs after acknowledged durability. Unit proofs separately exercise the -closed capability/gate, fallback Activity, causal audit composition, capture -exclusions and actual nonempty bounded audit-failure diagnostics. - -An isolated source copy passes all six gate/token/expiry controls before mutation. -Removing gate refusal admits a late callback when its token is deliberately not -canceled; the corresponding test fails. Removing only the final expiry check -fails both expired-work and blocked-lock-expiry cases while the token/gate controls -remain green. Removing token equality fails its ownership-loss case while the -other two controls remain green. These are compiled behavioral mutations, not -source-string assertions; production source is never mutated for this experiment. -The restored isolated baseline passes all six controls after the mutations. -Required format verification, whitespace, seven ADR-status controls and the -1,623-link/372-fragment corpus sweep pass. The broader integration regression, -excluding the long frontend rendering proof, is still running at this commit; -its outcome must be recorded before this step closes. Neither this local -receipt nor the held production manifests claims an active production consumer -or PR-head CI. Step 4 retains independent scheduling, timeout and replay proofs; -Steps 5/6 retain actual defaults, Seeder convergence and full packet closeout. - -#### Step 3 review round 1 - -Two fresh complementary reviewers inspect `81ab105..77890ea` against the accepted -package and current code. GPT-6-astra/high approves the runtime/security path with -zero Blocker/Major/Minor findings. It independently passes 22 gate/audit-metadata/ -diagnostic unit and two owner-census cases; integration/mutation evidence is -inspected, not rerun. GPT-6.1-sol/high independently passes those 22 unit, all 37 -new PostgreSQL integration and two owner-census cases, zero failures/skips. It -approves with one Minor: the catalogue's updated 196-method total omits P02b-3 -Step 3 from its delivery attribution. Root verifies the two new methods and adds -that provenance; no runtime correction is needed. - -The broader integration run finishes after the implementation receipt: all 1,373 -additional cases pass, zero failures/skips. This excludes the 37 new cases already -run and `PublicServerRenderingTests`, whose long frontend proof remains in the -full Step 6 regression. Together these runs pass 1,410 integration cases. The -catalogue correction and review record pass link/fragment, historical-preservation -and whitespace checks. Fresh round 2 follows the correction commit. - -#### Step 3 review round 2 and closeout - -Two new reviewers independently inspect `81ab105..5a8b85d`, including the verified -round-one correction. GPT-6-sol/high approves the runtime/security/concurrency -path with zero actionable findings and independently passes 22 focused unit and -37 integration cases. A fresh GPT-6-astra/high evidence reviewer approves with -zero Blocker/Major/Minor findings and independently passes those 22 unit, 37 -integration and two owner-census cases. All reruns have zero failures/skips. -Full-suite and compiled-mutation receipts are inspected rather than rerun by -these reviewers. The initially selected evidence reviewer could not start because -its model was at capacity; it supplies no review evidence and was replaced by -the fresh reviewer named above. - -Implementation is `77890ea`; `5a8b85d` records the broader regression and fixes the -verified catalogue attribution. No runtime review fix is required. Earlier -Accepted ADR text and historical delivery records remain intact. Step 4 follows -automatically under the accepted package; no new decision or privilege expansion -is needed for its independent subscriber scheduler. - -### P02b-3 Step 4 — subscriber scheduling, terminalization and replay (2026-10-13) - -**Complete; both independent review rounds and the verified correction complete.** -The API-owned subscriber worker shares the existing confined keyed data source, -with no new role, migration or credential reader. Its store claims one exact -tenant/subscription/event tuple, selects routing/status columns only, and uses -the existing ordered indexes. Pending and privileged targets are held by exact -type/subscription pair; an accepted Active sibling remains runnable. Normal -claims spend independent attempts, expired claims recover without execution or -another attempt, and the sixth claim never authorizes a seventh invocation. - -The subscriber terminal writer extends the restricted actual-row witness and -fifth audit seam. Tenancy registers `platform.delivery.dead_letter` with that -writer; the terminal UPDATE and matching MUST/SecurityEvent audit share one -transaction. Targeted internal replay admits one completed terminal Active -ordinary tuple, invalidates its old ownership and never resets an inbox or -republishes a broadcast. Operator HTTP/permissions remain Phase 03. - -Task-owned controlled execution closes its sticky gate before asynchronous -cancellation callbacks, retains the actual application scope through those -callbacks and cleanup, and rejects control reuse before acquiring cleanup -ownership. Acknowledged durability survives faulted or overlong cleanup; retained -tasks continue to block their local partitions and consume the four-task capacity. -The shutdown wait uses one budget and the host token. Snapshot refresh follows -the configured cadence even after failure; gauges read immutable memory only. -Finite event/subscription labels and bounded diagnostics add no envelope read to -the scheduler. The private delivery health check leaves `/healthz` unchanged. - -Real-role store/worker tests and exact production-capability censuses with planted -controls pass local validation. Production defaults remain Pending until Step 5's -initializers and Seeder handoff are ready. Final test and two fresh sequential -review receipts follow before that step begins. - -#### Implementation validation - -The CI-equivalent Release build passes with zero warnings/errors. The final -candidate passes 1,855 unit, 298 architecture and 238 focused integration cases, -with zero failures/skips. The integration set includes 45 new store and 21 new -worker cases plus 172 producer/acceptance/inbox/owner/role regressions. TRX files -record each run; Docker-dependent tests use actual PostgreSQL and the guarded -application or confined scheduler role appropriate to the boundary. - -The final replay control first terminalizes four real rows, then resets one; -terminal neighbours differing in tenant, subscription or event remain byte-for-byte -unchanged. Business execution also carries a distinct human causal actor while -effective audit actor remains SystemActor. No-listener trace proof asserts the -actual source has no listeners before checking a fresh canonical attempt ID. - -Final format verification, all seven ADR-status controls, all five corpus guards -and whitespace checks pass. The changed-document sweep checks 1,818 relative -links and 398 fragments with zero missing targets/anchors; added prose passes -the 88-column check. Earlier Accepted ADR bodies and dated P02b receipts remain -byte-preserved. - -Three catalogue rules become Implemented with their behavioural/structural owners. -The catalogue now records 205 architecture methods and 196 Implemented rules, -120 in the architecture assembly and 76 elsewhere. Consumer-handler censuses, -production activation and defaults/Seeder proofs remain Steps 5–6. Earlier dated -receipts retain their original counts and pending status. - -#### Step 4 review round 1 - -Two fresh read-only reviewers inspected `3411424..262d4b2`: - -- **Runtime/security — GPT-6-astra, high:** one verified Major. Subscriber - execution and durable acceptance used the same singleton/raw partition lane; - a retained handler or postcommit cleanup could delay producer acceptance and - consume producer timeout/capacity. Its independent rerun passed 66 focused - PostgreSQL and eight focused unit cases, showing the missing combined scenario. -- **Proofs/docs — GPT-6-sol, high:** Approve, no Blocker/Major/Minor/Suggestion. - It inspected production capability censuses, actual-role/worker tests and - documentation/history without independently rerunning the suites. - -Root verified the shared lane and separates only the internal execution lane -with a fixed `delivery:` prefix. Validated event partitions remain canonical UUIDs; -consumer serialization and raw scheduler partition holds remain intact. A live -subscriber cannot delay a new same-partition publication's durable acceptance. -Two real-bus/PostgreSQL regressions hold the actual handler or acknowledged-COMMIT -cleanup and accept a second same-partition event before releasing the first. -In an isolated source copy, restoring the shared raw lane makes both cases fail; -no production source or branch is mutated for that control. This implements the -accepted independent failure domains and introduces no new policy or ADR. -Correction validation passes the Release build with zero warnings/errors, 1,855 -unit cases, 41 affected architecture cases and 101 store/worker/executor PostgreSQL -cases, with zero failures/skips. Both isolated restored-baseline cases pass again. -Format, whitespace and the 1,818-link/398-fragment document sweep pass; the next -fresh review round follows the correction commit. - -#### Step 4 review round 2 and closeout - -Two new read-only reviewers independently inspected `3411424..14d5f93`, including -the complete Step 4 implementation and round 1 correction: - -- **Runtime/security — GPT-6-astra, high:** Approve, zero - Blocker/Major/Minor/Suggestion. Independently passed 101 PostgreSQL cases, - 16 lifecycle/observation/commit-gate unit cases and 36 architecture cases, - with zero failures/skips. It verified lane separation, fresh-clock fences, - row-bound terminal audit, exact replay and actual resource ownership. -- **Proofs/docs — GPT-6.1-sol, high:** Approve, zero - Blocker/Major/Minor/Suggestion. Independently passed 101 PostgreSQL cases, - 41 architecture cases including all five corpus guards, and eight unit cases, - with zero failures/skips. It verified the corrected binary's new tests/lane, - planted census controls, catalogue counts and preserved historical records. - -Both reviews used existing Release artifacts without independently rebuilding or -rerunning the isolated mutant. Their receipts distinguish actual reruns from -inspection of root's earlier build/format/link/mutant evidence. Neither changed -files or GitHub. The correction is committed at `14d5f93`; root's restored mutant -baseline passes both cases after the old-lane mutant failed both. Step 4 is closed; -Step 5 follows automatically with useful consumers and semantic Seeder handoff. - -### P02b-3 Step 5 — useful defaults and semantic seed handoff (2026-10-13) - -**Complete; both independent review rounds complete.** -Step 4 is closed before these changes. This step implements the accepted pair of -one-root initializers and shared transaction-owned concept serialization, then -moves built-in seed verification to semantic identity. Authored identities and -exact pins retain their existing contract. Both production subscriptions activate -together only after the initializer and Seeder paths are ready. - -The initial implementation supplies two Off-classified subscriber coordinators -and two MUST-classified initializer commands. Both production manifests are Active -and bind the discovered handlers exactly. Each untouched concept is published -before its single save, with one generated UUIDv7 identity, generation bump and -resource audit. Every existing lifecycle/revision is preserved under the same -transaction-owned concept lock used by ordinary registration. - -Seeder discovers the exact Active built-in by key, verifies its full shape and -retains the discovered identity. Authored identities/pins remain strict. Fresh -seed inventory retains all definitions/content but uses six customization -generation bumps per tenant and 86 audit rows, replacing the earlier two-step -register/publish treatment of four built-ins. The P02d seed receipts remain -historical evidence of their original behavior. - -Initial validation: full CI-mode Release build has zero warnings/errors; all -1,862 unit and 298 architecture cases pass. Focused app-role integration passes -24 initialization cases, 83 Seeder/audit/projection/manifest cases and eight real -API delivery cases, all with zero failures/skips. The real flow covers stored -backlog, fresh provisioning, audit-failure rollback/recovery, duplicate acceptance -and Seeder/subscriber races for both concepts in both winning orders. Test-owned -database gates coordinate real writes without a production registration hook. -The race observer uses the app role so PostgreSQL exposes its own role's lock -waits; the earlier owner-role observer could not see app-role activity and failed -the fixture, rather than detecting a product defect. The corrected full flow -passes all eight cases. The existing publication concurrency suite also passes -all ten cases, and the guarded frontend run passes 1,616 cases with zero -skips/todos. Two fresh sequential review receipts follow before Step 6. - -#### Step 5 review round 1 - -Three fresh read-only reviewers examined `94d7d6b..d53ae27` before the second -round. GPT-6-astra xhigh reviewed production correctness, isolation and races; -GPT-6.1-sol xhigh reviewed proof quality and Seeder convergence; both approve with -no findings. They independently reran 92 integration cases and 100 focused -integration/unit cases respectively, all passing with zero skips. These overlap -root's receipts and are independent reruns, not additional distinct test cases. - -GPT-6-sol high identified four mutable Architecture 31 passages still describing -real defaults as Pending, and the standards-check skill still describing inbox -acquisition as pending. Root verified both against the Active bindings and owner -path, corrected those current-state carriers and extended the phasing table to -Step 5. The historical ADR and Step 1–4 receipts remain unchanged. Root's updated -document check passes 2,209 relative links and 480 fragments with no errors; -the reviewer independently passes all five corpus guards. No runtime correction -was needed. Missing full-packet ADR delivery notes are not a Step 5 finding: -Step 6 owns them after production-census enforcement and final regression. - -#### Step 5 review round 2 - -Fresh GPT-6-astra high and GPT-6.1-sol high reviewers independently reviewed -`94d7d6b..0302d8a`, including implementation and the R1 correction. Both approve; -no runtime finding remains. The runtime reviewer independently passes 92 focused -integration and 97 unit cases, with zero failures/skips. The proof/corpus reviewer -independently passes 92 integration cases and all five corpus guards, including -the final correction below. These are overlapping independent reruns. - -The second reviewer found the Pending-policy catalogue entry still naming the -renamed production-composition test and calling actual subscriptions Pending. -Root verified the surviving test and explicit Pending fixture registrations, -then corrected the reference and separated the policy proof from current Active -bindings. The reviewer rechecked that correction and the 198/120/78 catalogue -counts with no open finding. Release binaries are unchanged. Root's document -check has zero link/fragment/width errors and preserves earlier receipts and ADR -text. Step 5 is closed. Step 6 follows with production censuses, remaining current -carriers, full regression, demo/Lighthouse and PR-head CI verification. - -### P02b-3 Step 6 — production enforcement and PR closeout (2026-10-13) - -**Implementation and both independent review rounds complete.** -[PR #31](https://github.com/HodeTech/LearnStack/pull/31) is open for maintainer -review; merge remains pending. -Step 5 is closed at `ac7bbee` before these changes. This step completes nonempty -production handler/manifest and call-path controls, extends aggregate/audit -coverage to integration handlers, reconciles current carriers and performs full -Release regression plus the real shared demo/Lighthouse lifecycle. The earlier -five delivery/review receipts remain unchanged. - -The authorized Hub dependency pointer is reconciled in the existing sibling -`docs/hub-agent-handoff` branch at `dd243a0`: its P02c-3 dependency now links to -ADR-0046's shared transport-owned inbox. This is a local documentation-only commit; -no Hub runtime, HTTPS surface, branch change, push or PR is part of that update. -The Hub track remains frozen under its existing owner decision. - -#### Step 6 implementation and local proof scope - -The canonical inbox rule now discovers concrete integration handlers in every -production assembly/layer, compares inherited/explicit event contracts with the -actual API's two scoped Active bindings, and checks typed construction, -invocation, generic DI, helper, async and delegate capabilities. Missing assembly, -handler, registration and actual invocation subjects fail the same predicates. -The lifecycle companion pins exact typed unit/frame and raw transaction -completion owners, including site multiplicity and missing-owner controls. -These checks do not infer arbitrary reflection, raw SQL transaction control or -control-flow dominance; the app-role behavioural suites own execution order and -atomicity. They introduce no production runtime hook. - -Audit discovery now fails on assembly/type load errors and classifies each -concrete handler, rather than its shared event. Actual API/Seeder catalogues must -include both Off coordinators even when their operation entries are unchanged; -an omitted-handler control and integration-only module control can fail. -The aggregate constructor-port census includes inherited integration handlers, -fused ports and separate-root controls. It does not infer nested ISender -request dataflow; the real default effects supply the one-root runtime proof. - -The canonical restored-context test checks constructor/callback timing, inbox, -prior context cleanup, effective SystemActor and separate causal human identity. -It also reads the committed outgoing trace, tenant/org and exact nonempty -partition. A new test-only HTTP controller sends the existing provisioning -command through the real API pipeline and production outbox, then reads the -committed quartet from a separate app-role connection. This proves producer -tracing, not authorization or admission of a new production endpoint. - -Self-check corrected test-harness overload/fixture lifetime issues without -weakening assertions. The first full architecture run reported the new partial -HTTP test file missing a source-visible Docker trait; the runtime class already -inherited it from its other part. The method now declares the trait explicitly. -No failing or partial run is counted as passed evidence. - -Local Release proof receipts: - -- Build: zero warnings/errors; solution-wide format verification passed. -- Unit: 1,862; contract: 4; full integration: 1,550, all passed with zero skips. - The final integration receipt includes the new HTTP and strengthened delivery - quartet proofs; its subsequent source change adds only the explicit method - trait. The final full architecture rerun passes all 311 cases, zero skips; - the source convention requires the shared `RequiresDocker` constants. The - combined backend receipts total 3,727 passing cases. Catalogue self-checks - confirm 218 architecture methods and 200 Implemented rules: 121 in that - assembly and 79 elsewhere. Five focused HTTP/context/composition controls - also pass on the final candidate build. -- The unchanged frontend passed its guarded 1,616-case suite, lint and typecheck - in Step 5; those receipts remain applicable, without claiming a Step 6 rerun. -- A fresh isolated development clone at `ac7bbee` ran the full shared demo. Step 6 - changes only tests/docs, so its production runtime is identical. The proof - finished in 580,109 ms with 27 JSON/HTML report pairs, nine URLs and three runs - each: maximum normalized gzip JS 106,573 bytes, maximum CLS 0 and every - automated accessibility score 1. Nine timing advisories remain warnings, not - production p95 claims. Cleanup passed and every originally running external - container was restored. This local receipt is not an exact final-PR-head CI - claim; the required CI job reruns the actual head. -- Relative document links/fragments and 88-column prose checks pass. Earlier - P02b delivery/review receipts and Accepted ADR bodies are byte-preserved; - authorized dated delivery notes are additive. ADR parser/disclosure tests: 7. - -#### Step 6 review round 1 - -Three fresh independent agents reviewed `ac7bbee..82623d8`: GPT-6-astra/xhigh -covered typed invocation/lifecycle capabilities; GPT-6.1-sol/xhigh covered -aggregate/audit discovery, actual roots and HTTP/delivery proofs; GPT-6-sol/high -covered the corpus and governance. Independent runs passed eight capability -cases, twenty aggregate/audit cases and five actual root/HTTP/context cases. -The whole backend/demo receipts above were inspected, not independently rerun. - -They found four enforcement gaps: a same-simple-name integration handler could -hide inside the provisioning exception; a handler could inherit implementation -from a base without the interface; a closed generic helper could hide typed DI -resolution; and EF transaction completion APIs could bypass the typed lifecycle -census. Root read the actual predicates and independently reran both compiled -scratch reproductions, confirming dirty cases were missed and matched controls -were detected. No current production-runtime defect was demonstrated. - -The fix pins the exact provisioning Type and adds independently failing name -collision controls. The capability fixes map inherited implementations, follow -closed generic helper specialization to known DI capabilities and enumerate EF -transaction/facade completion APIs. Existing Facts gain compiled dirty/clean -controls without increasing counts. Root's corrected Release build has zero -warnings/errors and all nine focused guard cases pass, including independent -same-name and recursive/ordinary generic controls. Rerunning the original -compiled capability probe now detects both inherited/generic misses and every -EF completion case, while the actual production baseline remains clean. The -first fix build caught instance-only probe methods that used no instance state; -their instance task fields preserve the intended inherited call shape without -an analyzer waiver. Full architecture passes all 311 cases with zero skips; -solution-wide format verification and document checks pass. The fix changes -tests/docs only; prior full unit/contract/integration and demo receipts retain -their explicitly recorded scope. -Current README, processor and skill guidance also retained delivered-as-pending -claims; those verified carriers are corrected. The new ADR-0046 delivery note -stays only in its dated Amendment 3, with mutable-index navigation; no new top -navigation is inserted into the Accepted body. - -#### Step 6 review round 2 and local closeout - -Three new independent agents reviewed the full `ac7bbee..84995d3` Step 6 range: -GPT-6-astra/xhigh covered capability/lifecycle enforcement; GPT-6.1-sol/xhigh -covered audit/aggregate/root/tracing proofs; GPT-6-sol/high covered the corpus. -The technical slices approve without an actionable finding. Independent runs -pass eight capability cases, twenty aggregate/audit cases and five real root/ -HTTP/delivery cases, all with zero skips. A separate compiled probe detects -seven additional dirty generic/inherited/async/iterator/closure/local-function/ -permutation shapes and leaves two unused-handler-argument controls clean. - -The corpus reviewer approves with minor current-pointer corrections in -architecture 10/15, Standards 20 and the producer catalogue entry. Root verified -and fixed them, preserving Step 5 as dated evidence and linking current status -to this record; the reviewer rechecked the edits. A final glossary clarification -states context precedes business construction/DI resolution, while metadata -registry discovery happens earlier. Root verified the actual executor ordering. -Five corpus consistency cases and link/fragment checks pass; these final fixes -change documents only. No open verified finding remains from either round. - -All six P02b-3 steps completed their implementation commits and both independent -review rounds. The local full-suite, focused fix and demo receipts retain the -explicit scopes above; no final-head CI success is inferred from them. The PR -handoff below will own the live seven-check verification and maintainer review. -This completes P02b-3 implementation and local review, not a merge or the whole -Phase 02b. P02b-4–8 remain unimplemented; the next packet is P02b-4's background- -job decision pass, including the reserved ADR-0047 before runtime work. - -### P02b-3 PR handoff (2026-10-13) - -[PR #31](https://github.com/HodeTech/LearnStack/pull/31) compares `development` -with `main`. The six-step implementation and both independent review rounds -are complete; initial enforcement is `82623d8`, verified first-round fixes are -`84995d3`, and local review/document closeout is `a8e9c9d`. The -[Step 6 record](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) -owns scoped local validation, independent receipts and corrected findings. -This handoff changes documents only and introduces no new implementation scope. - -The [live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own -exact-head CI results. All seven required contexts remain active with strict -up-to-date protection: backend, frontend, secret scan, meta, backend integration, -OpenAPI diff and public demo/Lighthouse. The initial published head started CI; -this documentation receipt receives its own final-head run. No pending or -superseded run is counted as success. Maintainer review and merge remain pending. - -P02b-4's background-job decision pass is next after this packet's review. It -must draft and obtain approval for the reserved ADR-0047 before runtime work. -Authentication, realm reconciliation, BFF/session and phase exit remain -P02b-5–8; Phase 02b is not complete. - -### P02b-3 external review follow-up (2026-10-15) - -The external PR #31 review compares `6a277770..683ea537`. Findings are review -inputs, not authority; each was checked against current code, Accepted ADR-0046 -and the approved P02b-3 package. Earlier dated receipts and Accepted ADR bodies -remain unchanged. No new runtime decision, migration, role, endpoint or replay -permission is introduced by this follow-up. - -Verified corrections: - -- Live P02b-2 pointers now name its merge closeout; P02b-3 status points to Step 6 - and the PR handoff. Shared handler/audit remarks, canonical Inbox prose, - glossary, decision index and review guidance describe delivered behavior. -- Failed snapshot reads no longer advance the successful refresh timestamp. - Recovery is tested after restoring SELECT without advancing the fake clock. - A normal claim's uncertain completion records `execute:unknown:commit`; - expired-lease recovery retains `recovery:unknown:expired`. -- The existing lifecycle census now enumerates actual tenant-announcement calls - through both the interface and concrete adapter, including inherited, async - and delegate shapes. Missing real calls and planted extra callers fail it; - ADR-0040's eight logical setter paths remain unchanged. -- Catalogue discovery reads the declared Status block rather than any bold - Implemented mention elsewhere. A Registered entry with misleading Implemented - prose is a negative control. The scheduling-index proof reads actual production - eligibility/admission constants and includes time, lease, locking and LIMIT. -- Removed the duplicate executor registration. Added actual-store wrong-kind - controls and producer terminal audit cases for absent versus invalid causal IDs. - Composition/factory remarks and seed-audit count explanation are aligned. - -Verified dispositions for the remaining review items: - -| Review item | Disposition and current evidence | -|---|---| -| Health should tolerate one retained overrun | Rejected: the approved P3 runtime table and Standards 10 require unhealthy while any callback/cleanup overrun remains. Capacity four separately stops acquisition; ordinary running work is not this count | -| SQL NULL causal IDs should invalidate a valid original trace | Rejected: optional absence is valid; only empty IDs are invalid. Real terminal regressions now pin both outcomes; audit prose explicitly distinguishes absence | -| Unclassified delivery log should include raw handler type | Kept minimized: existing delivery proofs prohibit handler type text. The scheduler's correlated attempt already names finite subscription/event labels and outcome; no raw stored type or exception detail is added | -| Queue snapshot lacks a dedicated aggregate index | No schema change: the exact count/minimum covers all unfinished ledger states at the approved cadence, under the SQL deadline. Claim-index applicability is now tested against actual selection. This is not a claim of constant-time counting; Phase 11's existing retention/scale work owns aggregate cost tuning | -| Initializers need ordinary AggregateConflictException handling | No defect: initialization and registration share the concept lock, with both winning orders tested. Unexpected ID/constraint faults abort and follow subscriber retry | -| Initializer exception should include Result.Error detail | Kept bounded: actual consumers throw fixed effect-specific failures, tested on refusal. Raw details do not belong in delivery diagnostics | -| No-change initializer audit lacks a business snapshot | Accepted behavior: preservation attempts remain classified MUST successes without mutation or entity snapshots; creation separately requires captured Active state | -| Preserved non-Active built-in causes untested Seeder divergence | Rejected: Draft/Deprecated/deleted and successor/history tests preserve every business field, then refuse the exact Active demo postcondition; the seed skill already documents it | -| Seed skill implies old built-in registration | Rejected: its write-order step explicitly uses separate shared initialization commands and distinguishes authored registration/publication | -| Concept-history SQL duplicates mapping names | No refactor: owner-local constant SQL intentionally reads tombstones through explicit tenant predicates and RLS; actual schema/history/isolation/race tests cover it | -| Five-second acceptance/inbox command timeouts | Match the approved fixed SQL bound. No shared mutable configuration contract is promised | -| Per-subscription acceptance statements | Two declared subscriptions; separate equality reads deliberately obtain a fresh READ COMMITTED snapshot after a concurrent conflicting insert | -| Repeated writable-announcement checks | Deliberate boundary validation: detect changed transaction, context generation and tenant/org before SQL and commit | -| Retained envelope needs an owner trigger | Existing exact column grants implement the approved immutability boundary and have real-role forbidden-write controls. Inbox's owner trigger is a separate marker contract; no new owner-level policy is inferred | -| Capture exclusions name currently unmapped SQL machinery | Intentional ADR-0044 Amendment 11 policy; mapped probe types exercise actual interceptor exclusions even though production storage uses SQL | -| Integration friend assembly exposes all internals | C# friendship is assembly-wide; it enables actual internal execution/lifecycle proofs without exposing production APIs | -| DeliveryAttemptTests name, worker-test title and options binding | Naming/configuration suggestions only: the tests deliberately cover attempt cancellation control and exactly one OutboxProcessor; dispatcher options use approved fixed bounds, not a promised configuration section | -| Lifecycle/owner Facts need separate canonical rows | Existing Integration_Event_Handlers_Use_InboxGuard entry already names both companions. The expanded announcement proof is recorded there; no duplicate rule is added | -| Producer/subscriber rules share TerminalOffenders | Intentional common witness authority, with distinct producer and subscriber dirty controls; not a missing independent failure path | -| Bare First/Single in planted controls | Missing fixtures fail loudly rather than pass. No absent-subject success was reproduced; production subject and signature checks remain explicit | -| Nonempty/derived-capability assertions | Existing required-type, method, signature and exact-owner checks fail before mutation loops when a production subject disappears | -| Ignored consumer ActivityContext.TryParse result | Immutable envelope construction and the retained-envelope reader validate the trace before this call | -| Internal delivery partition lane needs explanation | Existing comment explains acceptance/execution separation and canonical UUID collision avoidance; the approved local-ordering bound remains | -| Subscription grammar copies need consolidation | Equivalent current contract, already tested through registry, storage and witness admission; optional refactor, no divergent behavior demonstrated | -| CancellationToken.None after commit admission | Accepted cancellation/unknown-outcome tradeoff; do not replace the approved sticky gate and reconciliation contract | -| Decision-index amendment numbering gaps | Selected navigation links do not enumerate all historical amendments; complete dated sections remain in each ADR | -| Built-in enumeration, meter factory and health Degraded suggestions | Optional abstractions/observability policy changes; no demonstrated current defect in the approved two-default, binary-health contract | -| Earlier P02d seed receipts and ADR-0046 top navigation | Historical evidence stays intact. P02b-3 Step 5 owns current generated built-in identities and semantic verification; current index links the preserved ADR-0046 Amendment 3 | -| Replay/privileged execution and future strict ordering | Existing Phase 03/new-decision triggers remain explicit; no operator entry point or privileged subscription is activated | -| Retention, inbox-trigger purge exception and erasure inventory | Existing Phase 11 retention/grant decision and P02b-8 inventory obligations remain; this follow-up does not grant purge or bypass access | - -The original source head `683ea537` passed all seven required CI contexts in -[run 38424753309](https://github.com/HodeTech/LearnStack/actions/runs/38424753309). -Downloaded exact-head artifacts corroborate 1,862 unit, 311 architecture, -4 contract and 1,550 integration tests (3,727 backend; zero failed/skipped), -1,556 web plus 60 SDK tests, and 27 admitted browser/Lighthouse report pairs. -Maximum normalized gzip JS was 106,551 bytes, maximum CLS 0, all automated -accessibility scores 1; the proof finished in 621,330 ms with successful cleanup. -These are evidence for the reviewed head, not this correction's final-head CI. -Correction validation: Release solution build has zero warnings/errors; -solution-wide format and diff checks pass. All 1,862 unit, 311 architecture, -4 contract and 176 Docker-free integration tests pass, with zero skips. Focused -real PostgreSQL validation passes 73 worker/store/terminal cases plus the actual -candidate-index case. Seven ADR parser cases and the document link/fragment, -prose-width and historical-record checks pass. At this initial receipt the -catalogue counted 218 methods and 200 Implemented rules (121 architecture, -79 elsewhere); the round-2 correction below records the accurate current count. - -The first full unit run exposed a cross-test metric listener race (one observed -failure counted another test's same-name meter). The corrected test filters its -owned Meter by reference, disposes its provider and verifies an unrelated meter -really emits while contributing zero to its count; the actual store must still -count exactly one. The focused case and corrected full unit suite pass. -Fresh review rounds and correction-head CI remain pending at this initial receipt. - -#### External follow-up review round 1 - -Two fresh independent agents reviewed `683ea537..586ed75`. GPT-6-astra/xhigh -reviewed runtime, security, isolation, lifecycle and performance, independently -passing 72 focused PostgreSQL integration cases and three architecture cases. -GPT-6.1-sol/xhigh reviewed guards, tests, governance and all changed documents, -independently passing eight architecture cases, 18 recorder unit cases and the -real PostgreSQL candidate-index case. All runs have zero failures/skips. - -The runtime review found no actionable issue. The proof/corpus review found two -Minor wording errors: the new machinery-write prohibition inadvertently required -all business handlers to send commands, although the Accepted classified direct -one-root path remains valid; and Security retained an obsolete one-setter count. -Root verified both against ADR-0044 Amendment 8/ADR-0057 and current transport -calls. The fixes remove the command-only restriction and describe the actual -announcement seam without a misleading count. The reviewer rechecked both and -approved with no remaining finding. Document checks pass; this fix changes no -runtime or test source. Round 2 and correction-head CI remain pending here. - -#### External follow-up review round 2 and closeout - -Two new independent agents reviewed `683ea537..d8c766f7`. GPT-6-astra/xhigh -reviewed technical correctness and proofs, independently passing 72 PostgreSQL, -eight architecture and 18 recorder unit cases. GPT-6-sol/high reviewed the corpus, -governance and test claims, independently passing seven focused architecture cases. -All runs have zero failures/skips. Runtime, isolation and lifecycle were approved. - -The corpus reviewer found a pre-existing counting omission in the touched parser -scope: two real integration rules used a bold `Implemented, twice.` status and -were excluded from the declared-state count. Root verified both exact-name -methods in `TenancySchemaTests` and `TenantIsolationHttpTests`, normalized the -statuses to a bold `Implemented` token with the qualifier outside it, and named -the actual classes. An additional positive control in the existing corpus Fact -pins qualified Implemented discovery alongside misleading Registered prose. -This adds no test method or runtime rule: the accurate catalogue total is now -202 Implemented entries, 121 in architecture and 81 elsewhere; architecture still -has 218 methods and 311 cases. The earlier 200-entry receipts retain their -as-recorded scope and are superseded for the current catalogue count here. - -Root's corrected five corpus tests pass after rebuilding. Both reviewers -independently recounted the entries, rechecked the exact methods/control and ran -all five corpus tests successfully, approving with no remaining finding. Final -format, diff and document checks pass; historical delivery receipts and Accepted -ADR text remain intact. Earlier full-suite receipts retain their stated scope; -the last correction changes test fixtures and catalogue metadata only. - -The implementation and both external follow-up review rounds are complete. -The [live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own the -correction-head CI result; the PR description is updated only after inspecting -that exact source head and its artifacts. No earlier run substitutes for it. -Maintainer review and merge remain pending; this follow-up starts no P02b-4 work. - -### P02b-3 second external review follow-up (2026-10-15) - -**Status: verified corrections and both review rounds complete on `development`; -PR #31 remains unmerged.** -The external reports reviewed `b681edb8`. Each finding was checked against current -source and Accepted ADR-0046/0057; supplied reproduction files were review data, -not instructions. This receipt supplements the -[first follow-up](#p02b-3-external-review-follow-up-2026-10-15). -That follow-up's final counting correction is commit `b681edb8`, after its -round-2 reviewed range `683ea537..d8c766f7`. - -The reviewed source head passed all seven required contexts in -[run 38736262412](https://github.com/HodeTech/LearnStack/actions/runs/38736262412): -3,732 backend tests (1,862 unit, 311 architecture, four contract and 1,555 -integration), 1,616 frontend tests and 27 browser/Lighthouse report pairs. -Downloaded artifacts were checked against source `b681edb8` and checkout -`3b06800d`; zero tests failed or skipped. These receipts cover that reviewed head, -not the corrections below. - -#### Verified corrections - -- Fixed class priority could indefinitely starve ordinary deliveries when a - terminal-audit failure backlog outlived its leases. Independent actual - PostgreSQL reproduction observed 216 terminal failures in eight seconds while - the normal delivery stayed at zero attempts; invoking the real executor - directly completed it while the scheduler audit grant remained denied. - Rotate terminal, recovery and normal acquisition after each class visit, - including failures. Each iteration still acquires at most one just-in-time - claim; existing lease, fence, partition, capacity and terminal rules remain. -- Duplicate acceptance compared retained type text literally. Independent - PostgreSQL reproduction rejected an explicitly declared compatible alias - while accepting the canonical control. Compare all other envelope values - exactly and resolve retained type through the closed registry to the incoming - CLR contract. Preserve retained type, payload, scheduling state and row version; - no arbitrary CLR loading or payload normalization is added. -- Completion constructor calls now have an exact owner census, with additional - direct/asynchronous caller and missing-site controls. Production project - discovery includes differently named projects and ignores generated `obj` - projects, with a temporary-tree control. -- Audit storage requires a non-null diagnostic context accessor in every - construction. Undefined subscription execution scope has its own fixed - diagnostic. Catalogue refusal has its own closed `execute:refused:catalogue` - descriptor, with no-construction/business/inbox controls. Rollback/reapply - proofs include the inbox trigger function, and - lease-expiry polling has a deadline propagated through its database reads. -- Live state pointers, migration-chain naming, the naming table, scheduler index - rationale, catalogue detector sharing and delivered subscriber wording are - aligned. Earlier delivery/review receipts retain their stated scope. - -#### Other findings and scope - -| Review item | Disposition and current evidence | -|---|---| -| Unknown-COMMIT failure counter | Accepted process observation, not durable business accounting; Standards 10 explicitly documents that an unknown COMMIT may have succeeded | -| Startup should log exception types/details | Existing minimized dispatcher diagnostics deliberately omit provider/exception type text; current fixed failures and health remain bounded | -| Additional completion owner assertion | Already enforced by prepared-owner creation and `RequireLive`, including before fencing; no reachable missing check | -| Suppress post-acknowledgement disposal errors | Deliberately pinned by `UnitOfWorkCommitCleanupTests` and `DeliveryCommitGateTests`; delivery interprets definitive commit evidence. Changing ordinary request response policy needs a separate design | -| Acceptance round trips | Two current subscriptions; the separate equality statement intentionally gets a fresh READ COMMITTED snapshot after a conflicting INSERT | -| Duplicated SystemActor derivation | Not present: the coordinator derives it; producer envelope creation consumes captured causal context | -| Add a 200-character subscription ID limit | No such bound exists in the Accepted grammar/package; the cited 150-character cap is specific to killswitch keys. Finite registered IDs remain trusted configuration; no new numeric contract or migration is inferred | -| Initializer conflict catch | Shared concept lock plus any-history refusal handles both registration orders; unexpected ID/constraint faults must roll back | -| Taxonomy verification needs set equality | Unique stored band keys plus equal count and complete membership already establish unordered equality; real shape/history mismatch controls remain | -| Two stores must use separate pools | Existing contention proof promises two stores and uses distinct live connections/transactions; separate pools/processes are not its claim | -| Raise shortened fixture deadlines | No reproduced deadline defect; keep the intentionally shortened valid test bounds and controlled shutdown clock | -| Health should count ordinary awaited callbacks | The published count tracks retained overruns/cleanup; the ordinary serial await does not publish it. Any retained task remains unhealthy, with acquisition stopping separately at capacity four | -| Additional commit-owner abstraction/refactors | Exact declared owners remain intentional; no new helper, outcome router or diagnostics abstraction is needed for these corrections | -| Internal replay needs a production audit writer | Still unwired; Phase 03 owns operator permission/HTTP and its classified audit path. No new replay entry point is activated | -| Friendship, cross-cutting composition and N envelope copies | Existing explicit internal proof access and composition are unchanged; the accepted package already inventories per-subscription retained copies for P02b-8/Phase 11 | -| Further policy parity/concurrency/census optimization | Existing real-role policy, independent-connection contention and planted production controls remain; no missing behavior was demonstrated beyond the corrected discovery/constructor gaps | - -Correction validation: Release solution build has zero warnings/errors; full -format and diff checks pass. All 1,864 unit, 312 architecture, four contract and -176 Docker-free integration cases pass with zero skips. Focused integration -passes 31 acceptance, 23 actual-worker and 113 store/audit/migration/composition -cases. The latter includes three Docker-free composition cases already covered -by the full Docker-free receipt; these are not extra distinct tests. - -The fixed-priority and literal-type-equality mutants each fail their new -PostgreSQL regression. Original source was restored, the solution rebuilt and -both regressions rerun successfully. Seven ADR parser cases pass; document -checks validate 2,822 relative links and 631 fragments, prose width, historical -receipts and earlier Accepted ADR text. The catalogue counts 219 methods and -202 Implemented rules (121 architecture, 81 elsewhere). - -The first architecture run correctly rejected the moved claim calls because its -exact privileged-consumer list still named `ExecuteAsync`. The corrected census -requires the private `ClaimNextAsync(string[], CancellationToken)` signature -instead, with an extra-overload control. It grants no whole-type exemption; the -full corrected architecture suite passes. - -Two fresh independent review rounds and correction-head CI remain pending at -this initial receipt. Earlier CI evidence does not substitute for that head. - -#### Second follow-up review round 1 - -Three fresh agents reviewed `b681edb8..92e296ed`. GPT-6-astra/xhigh reviewed -runtime, transaction/cancellation ownership, fairness and diagnostics; it passed -23 worker, 25 diagnostic/registry unit and 40 dispatcher architecture cases. -GPT-6.1-sol/xhigh reviewed guards, proofs, governance and corpus consistency, -independently passing all 312 architecture cases. GPT-6-sol/high reviewed alias -acceptance, concurrency, RLS and audit composition; it passed 31 acceptance, -23 worker and 25 focused unit cases. All runs have zero failures/skips. - -All three approve with no verified actionable finding. The older prefix-scoped -request/handler discovery scans are separately documented scopes, not a claim -of this shared production census. No new rule or deferred decision is silently -introduced. Round 2 and correction-head CI remain pending here. - -#### Second follow-up review round 2 - -Two new agents reviewed `b681edb8..a95ae2ec`. GPT-6-astra/xhigh reviewed runtime, -acceptance, isolation and audit composition, independently passing 163 focused -integration, 43 unit and 41 architecture cases. GPT-6.1-sol/xhigh reviewed proofs, -corpus, ownership controls and governance, independently passing all 312 -architecture and 25 focused unit cases. All runs have zero failures/skips. -Both approve with no verified actionable finding against that correction scope. - -The runtime reviewer separately identified the unchanged producer worker's same -fixed class-priority pattern. This concern was not counted as a verified finding -against the reviewed diff. The adjacent correction below owns its PostgreSQL -verification and any resulting implementation/review evidence; the delivery and -alias approvals do not substitute for reviewing that change. - -#### Adjacent producer fairness correction - -**Status: correction, validation and both independent review rounds complete.** The -producer worker's strict terminal/recovery/normal priority reproduced the same -starvation in real PostgreSQL. With 100 terminal requests and only the scheduler -role's audit INSERT denied, the regression passed its lease-cycle failure check -then failed at the independent normal-publication/recovery deadline. The baseline -producer source was unchanged. The fixed worker uses the same bounded rotating -acquisition as the subscriber; its exact private credential-consumer signature -and extra-overload control replace the prior call-site requirement. - -Accepted ADR-0046 requires continued unrelated eligible work and does not require -strict claim-class priority. This is an implementation correction, with no new -ADR, grant, lease, attempt, terminal-audit or publication-ownership contract. -The regression requires actual unwrapped transport acceptance, no business -construction, unchanged recovery attempts and every failed terminal request -remaining intact without terminal audit while the grant stays denied. - -The unchanged baseline fails the new progress regression after its first -lease-cycle check. After correction the full actual producer suite passes -19 cases, zero failed/skipped; the new regression passes in 10.634 seconds. -Release solution build has zero warnings/errors. All 1,864 unit, 312 -architecture, four contract and 176 Docker-free integration cases pass again; -full format/diff and document checks pass. Two fresh independent reviews of -this additional producer correction remain pending at this initial receipt. - -Producer correction review round 1 used two fresh agents against -`a95ae2ec..bd51a974`. GPT-6-astra/xhigh passed 80 producer/store integration, -40 architecture and 20 ownership/bounds/observation unit cases. -GPT-6.1-sol/high passed all 19 producer and 40 architecture cases. Both approve -without a verified actionable finding; no fix was needed before round 2. - -Two new agents independently reviewed the same frozen correction in round 2. -GPT-6.1-sol/xhigh passed 80 producer/store integration, 40 architecture and -20 focused unit cases; GPT-6-astra/high passed all 19 producer and all 312 -architecture cases. Both approve with no verified actionable finding. All -independent runs have zero failures/skips; neither round relies on earlier -scope approvals to cover the producer change. - -The verified delivery/alias corrections and the adjacent producer correction are -complete, each with both fresh independent review rounds. Final document/diff -checks pass; the earlier receipts retain their exact as-of scope. The -[live PR checks](https://github.com/HodeTech/LearnStack/pull/31/checks) own -correction-head CI; its exact source and artifacts must be inspected before the -PR description records success. Maintainer review and merge remain pending; -this correction starts no P02b-4 work. - -### P02b-3 merge and closeout (2026-10-15) - -The maintainer merged [PR #31](https://github.com/HodeTech/LearnStack/pull/31) at -2026-10-15 16:45:06 UTC. GitHub records final PR source -`0fa7dc869d5b0f704a2d05313226d3d1b0f98510` and squash merge -`ed60157c14d33fad926fd201b49c08e2d24eed1f`, whose parent is previous main -`6a277770e46a7f4ea3574d9d6891d1802cb8fa90`. Source and squash merge have the -identical tree `57cab77ffb486689de18abbf741b6186dcf7de6f`. Development incorporates -the main merge without switching branches or rewriting published history. - -All seven required checks pass in the -[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38755136480) -for that source; CodeRabbit also reports success. The tested synthetic merge is -`a131ca6b59f750c69d4465b46a0bd1a5717dcd0a`. The seven required contexts and strict -up-to-date protection were re-read from GitHub after merge and remain enabled. -Verified artifacts record: - -- **3,745 backend passes**, zero failures/skips: 1,864 unit, 312 architecture, - four contract, 176 Docker-free integration and 1,389 Docker integration cases. - All ten alias/progress PostgreSQL regressions pass on this exact source. -- **1,616 guarded frontend passes**: 1,556 web and 60 SDK, zero - failures/skips/todos; lint, typecheck, builds and native-ingress proofs pass. -- Exactly 27 matching Lighthouse JSON/HTML report pairs across nine URLs, with - matching source/checkout identities and report digests. Automated accessibility - is 1 throughout, CLS is 0 and normalized initial JS gzip is at most 106,554 - bytes. Proof finishes in 649.646 seconds within the 12-minute bound; owned - cleanup passes. Nine timing advisories remain warnings, not production p95. - -These are final PR-head results, not a new post-merge or local full-stack run. -**P02b-3 is closed.** All six steps and verified review corrections are delivered: -durable acceptance, shared inbox/ledger, independent retries and terminal MUST -audit, fenced business completion, both Active defaults and semantic Seeder -handoff, plus production-census enforcement. Compatible-alias retries preserve -retained envelopes; rotating acquisition keeps unrelated eligible producer and -subscriber work progressing during terminal-audit failures. Each step and -correction bundle retains its two independent review rounds above. Earlier dated -receipts keep their pre-merge wording; this closeout changes no Accepted ADR. -Publication remains at least once. Phase 02b remains in progress. - -**Next: P02b-4 decision pass.** G9 and reserved, undrafted ADR-0047 must settle -job storage under the four-role model, tenant-context and transaction ownership, -safe enqueue, retries/terminal audit, queue/job identity, the adapter's demand -gate, and package/licence choices before runtime implementation. The -[background-job scope](#background-jobs) owns these questions; no job definition -or dashboard route belongs to that packet. - -API authentication, realm reconciliation, BFF sessions and phase-exit enforcement -remain P02b-5–8 in the [packet table](#packets-and-decision-gates). P02b-8 owns -retained-envelope erasure inventory. Operator replay permissions/routes, audited -recovery and privileged erasure execution remain Phase 03; broker adapters, -mapped readiness, retention/purge grants and production measurements remain -Phase 11. This documentation closeout starts no later packet or new decision. - -**Documentation-only closeout validation.** Five local Release corpus controls -and seven ADR lifecycle/workflow controls pass, zero failures/skips. Relative -links/fragments, added prose wrapping and whitespace checks pass. Every earlier -P02b delivery/review receipt and every ADR file is byte-preserved against the -accepted PR source. Only 11 Markdown files change; runtime suites are not rerun -locally for this closeout. The final PR artifacts above supply their evidence. - -### P02b-4 decision package (2026-10-15) - -**Accepted — 2026-10-15, @cemil.** The maintainer approves **H1: stock Hangfire -plus an authoritative LearnStack job record**, expanded P4 infrastructure, -[ADR-0047](../decisions/0047-transactional-background-job-runtime.md), its bounded -supersessions/additive seams and all nine implementation steps below. -Acceptance and dated prior-ADR disclosures commit before runtime, package, -migration or grant changes. Development stays on `development`; prior Accepted -ADR bodies/metadata and P02b-0–3 receipts remain unchanged. Runtime, dependencies, -storage/grants, enforcement and production job proofs remain unimplemented. - -#### Problem and scope - -Ship reusable durable tenant job infrastructure covering short transactional work, -long external prepare/execute/finalize, isolated dispatch slots, cross-instance -per-tenant admission, and recurrence/tenantless fan-out. Hangfire carries opaque -wakeup/tick references; LearnStack is the only business job authority. No dashboard, -production job/recurrence, ffmpeg implementation, Hub endpoint or privileged -maintenance executor is added. P02b-5–8 authentication/session work is separate. - -The [ADR workload envelope](../decisions/0047-transactional-background-job-runtime.md#workload-envelope-and-first-consumer-obligations) -owns mechanism/feature boundaries. Phase 04 keeps real media providers, process/ -resource limits, artifacts and coordinated concurrency keys; triggered 02c keeps -phone-home definitions; 08a/08b keep notification/reminder domain semantics; 11 -keeps licence operational surround and privileged audit DDL/purge. These feature -owners no longer need to invent the selected P4 long-operation/fan-out foundation. - -#### Verified premises and document review actions - -Current transaction/producer/context/audit/entitlement seams and first consumers -were traced after the P02b-3 closeout. Three read-only design inspections cover H1 -handoff (GPT-6-astra xhigh), external/capacity (GPT-6.1-sol xhigh) and recurrence/ -privilege/schema (GPT-6.1-sol xhigh). They supplement, not replace, the earlier -comparison experiments and correction reviews recorded below. No runtime proof -is claimed by these source/design inspections. - -| Verified gap | H1 contract/action | -|---|---| -| Vendor enqueue/state commits separately | Immediate authoritative INSERT + durable generation-fenced handoff/repair; callback never depends on ACK having arrived | -| Wakeup duplication can become later retry | JobId plus wake generation; only business transition advances generation; resend retains it | -| Stock retry count differs from six committed starts | Separate app-role admission/start receipt; capacity/duplicate/deferred work spends no attempt | -| Current request owner has no job participant | Closed root/stage/recipient participants, exact mode mapping and existing eight setters | -| Ambient/SystemActor is not a privilege boundary | Sticky positive request admission, root/nested/direct Platform/provisioning denial and separate bypass/admin-entry guards | -| Long ffmpeg does not fit a DB transaction | Durable plan/execute-intent/outcome checkpoints; external execution/reconciliation with no business UoW | -| Lease expiry does not stop provider work | Positive quiescence or quarantine; unresolved reservations never expire into free capacity | -| Organization-scoped capacity misses other orgs | Tenant-wide control mutex/reservations; plan/operational ceiling applies across orgs/instances | -| Framework can enumerate no tenant today | Named minimal lifecycle projection grant, bounded durable recipients and actual-row witness admission; no caller tenant selector | -| Recurrence revision can duplicate a logical slot | Unique recurrence-key/UTC-slot independent of revision, monotonic activation, stable jitter and checkpoint/recipient atomicity | -| Filters can be bypassed on vendor fallback | Migration-owned below-filter state/metadata guards and bounded log provider, pinned real-worker dirty controls | -| Whole-schema tests assume every table is app-readable/RLS tenant data | Exact table classes, expected vendor/control 42501 denial, no unclassified-table exclusions | -| No general runtime was Accepted | H1 retains audit-maintenance Hangfire choice; exact bounded identity/context/storage changes get dated Amendment navigation | - -#### Accepted decisions - -| Gate/contract | Accepted H1 contract | Vehicle | -|---|---|---| -| G9 runtime/storage | Pinned stock Hangfire wakeups, authoritative tenant/org job row, exact public vendor-control class and four roles | ADR-0047; ADR-0003 Amendment for grant/confinement extension; canonical Standards 05/20 on implementation | -| G9 ownership/submit | Typed own-module definitions, exact writable announcement, identifier-only frozen payload, immediate INSERT/ancestral receipt | ADR-0047; ADR-0057 extension and source guards | -| G9 context/owner | JobExecutor alone; sticky ordinary ceiling; exact ISender roots/framework requests; staged owner participants | ADR-0036/0032 replacements; additive ADR-0040 and closed ADR-0052 mode extension | -| G7 job part | Sixth WriteJobTerminalAsync, actual job-row witness, terminal state/MUST audit atomic | ADR-0044/0033/0046 navigation; Tenancy platform.job.dead_letter catalogue/matrix | -| G8 job/recurrence part | Conditional routing/status exemption with exact grants/censuses, bounded diagnostics, metrics/health and terminal MUST | ADR-0046 / Standards 18 Required Behaviours extension; no general background/privileged exemption | -| G9 profiles/capacity | Short transactional or staged external execution; renewable authority, positive quiescence, tenant reservations and disjoint pools | ADR-0047; real role/capacity/stale-effect proofs | -| G9 recurrence/fan-out | UTC interval/daily, CoalesceLatest, durable slot/jitter, minimal lifecycle reader and restricted recipient producer | ADR-0047; exact Standards 05 enumeration exception and ADR-0057 producer origin | -| G9 retry/readiness | Six normal starts; separate six finalize starts/recovery probe bounds; unknown/Pending defer, explicit retired tombstone | Standards 09/20, ADR-0047 mixed-version/capability queues | -| G17 labels/observation | Finite definition/profile/recurrence/group categories, no tenant/org/job/trace labels; memory snapshots | Standards 10 with first emitters | -| G18 job payload/diagnostics | Identifier-only 262,144-byte parameters, 65,536-byte plan/outcome checkpoints and 256-byte failure descriptors; durable-store erasure inventory remains P02b-8 | ADR-0047; bounds/guards with implementation, retention/purge authority remains Phase 11 | -| Dependency/licence | Core/NetCore 1.8.25, PostgreSql 1.21.1, Newtonsoft 13.0.4; stock shared assemblies, concrete graph/notices/source/relinking qualification | ADR-0047 and implementation packaging evidence; outside ADR-0035 gated set | - -G9 and the new job parts of G7/G8/G17/G18 are Accepted — 2026-10-15. -Existing G7/G8/event accepted dates and receipts are preserved. At implementation, -production business and recurrence registries independently assert zero definitions; -nonempty real runtime subjects and fixture-only definitions carry enforcement and -behavior proofs. Acceptance claims no passing runtime census or production proof. - -#### Runtime bounds and observation - -Bounds below are accepted inputs for this expanded H1 contract. Invalid values or -relationships refuse startup before workers; SQL/database time and actual task -ownership remain authoritative. - -| Bound | Accepted value | -|---|---| -| Independent stock server pools | Transactional 1, external 2, control 1 workers by default; finite dedicated feature pools, at most 8 pools/64 queues, 1–16 workers per pool, sum at most 32 per API instance | -| Operational tenant/group ceiling | Positive 1–1,024, default 1; optional Hard LimitKey intersects it; no tenant-supplied pool/group | -| Retained actual overruns/cleanup | Stop-new-start threshold 4 per pool; atomic accounting, retain every admitted task; hard bound configured workers + 4, at most 20 per pool; other pools progress | -| Outstanding synchronous bridge calls | At most 4; wait at most 10 s, retain actual operation; do not block other control lanes | -| SQL and external reconciliation probe | SQL positive, at most 5 s/default 5 s; provider probe positive, at most 30 s/default 10 s | -| Short root/prepare/finalize | Positive, at most 5 min/default 30 s; no long external operation inside | -| External run wait | Positive, at most 24 h/default 1 h; immutable per-attempt deadline | -| Lease / renewal | Lease 15 s–10 min/default 60 s; renewal 1–60 s/default 15 s; lease > twice renewal + twice SQL timeout + 5 s | -| Quiescence cancellation grace | Positive, at most 30 s/default 30 s; expiry never releases an unproved reservation | -| Control poll / snapshot | Poll 50 ms–1 s/default 200 ms; snapshot 1–60 s/default 5 s; successful work does not force scans | -| Handoff repair grace / batch | 15–300 s/default 60 s; at most 100 rows per quantum; same-generation resend | -| Recovery probe cadence / unsuccessful budget | 5–300 s/default 30 s; 6 unsuccessful probes then quarantine; Running probes bounded by attempt deadline/grace | -| Shared shutdown joins | Positive, at most 30 s/default 30 s across pools and bridge; no per-task reset | -| Progress heartbeat deadline | At least lease + 15 s, at most 15 min/default 75 s; renewal/control progress counts, not long work completion | -| Parameter / plan / outcome / failure descriptor | 262,144 / 65,536 / 65,536 / 256 UTF-8 bytes | -| Recurrence interval / fan-out page | 1 min–366 days, UTC anchor; jitter 0–min(period, 2 h); at most 100 routes/page | - -A plan cap is resolved through IFeatureFlags, capped by a positive operational -ceiling. -1 means operational ceiling, 0 means no new admission, invalid/Soft/ -undeclared keys fail safely. No Media LimitKey is invented by this packet. - -Standards 10 owns final names/label inventory. Job observation includes pending, -oldest eligible, deferred, retained/quarantined/reserved capacity, bridge repair, -finalize/failure/lease loss, fan-out progress and heartbeat signals. Confirmed -failure differs from unknown outcome. Register jobs health, unmapped; preserve -healthz liveness and Phase 11 readyz/production-alert ownership. Normal valid -long-running work is healthy; stale/faulted/retained/quarantined work is not. - -#### Approved implementation steps - -Every step commits its implementation/validation, runs two fresh independent -review-agent rounds, verifies/fixes findings and commits corrections, then advances -automatically. Critical authority/state-machine reviews use GPT-6-astra xhigh; -independent proof/composition/corpus lenses use GPT-6.1-sol high/xhigh. Each round -uses new reviewers. A new decision outside this accepted package returns to the -maintainer before dependent work. Development stays on `development` throughout. - -1. **Acceptance and typed contracts.** Commit final acceptance/dated Amendment - disclosures first, then add scheduling/profile/recurrence/identity contracts, - closed registries, request-scope admission and Jobs project boundaries. Register - canonical catalogue obligations without claiming enforcement before it ships. -2. **Storage, dependencies and guarded bootstrap.** Add exact pins/graph/notices; - Platform migrations for authoritative/control/capacity/recipient and stock - vendor schema, immutable/transition/metadata guards, RLS/grants/indexes and - canonical Standards 05. Prove fresh/Down, every-table classes, expected 42501, - exact role/source guard, schema 23, below-filter containment, bounded vendor SQL - and real index plans; keep the unguarded notification reconnect path disabled. -3. **Submission and app-role admission.** Implement trusted producer stamping, - immediate INSERT/receipts, routing leases, scoped read-only envelope validation - and separate committed start receipts. Prove rollback/absorbed refusal, - getter/stale/read-only attacks, exact org/module scope, unknown/deferred readiness - and no handler construction before admission. Capacity integration follows step 6. -4. **H1 wakeups and independent pools.** Implement bridge/reconciler, exact two - wrapper targets, generation fencing, guarded native connection factory and - disjoint server queues/pools. Prove real pinned worker create/init/ACK crashes, - duplicates/early/stale callbacks, vendor loss/fallback, malformed invocation, - bootstrap refusal, retained synchronous calls and construction-only fixture wiring. -5. **Transactional owner and terminal audit.** Add root participant/gate, scoped - ordinary ceiling, async attribution and fair retry/recovery/terminal control. - Prove business/outbox/jobs/audit/completion atomically, lock-wait expiry, - Result/exception parity, uncertain COMMIT, no seventh start, actual-row sixth - audit seam substitutions, and terminal-audit backlog progress beyond a lease. -6. **Tenant capacity reservations.** Implement group mutex/reservations and optional - Hard LimitKey resolution. Prove two instances/orgs share a tenant cap, capacity - refusal spends no attempt, unlimited/zero/downgrade/fault cases, exact app grants - and no TTL release of unresolved external occupancy; keep independent pools live. -7. **External prepare/execute/finalize.** Implement immutable stage/attempt receipts, - confirmed ExecuteIntent, no-UoW external adapter, renewal, typed reconciliation, - quiescence proof/quarantine and bounded finalization. Prove each crash/unknown - COMMIT boundary, provider accepted-before-ACK, paused-old-start/NotFound traps, - stale outcomes/revisions, simultaneous overruns/cleanup saturation, no seventh - effect and domain known-failure/terminal behavior without rerunning external work. -8. **Durable recurrence and restricted fan-out.** Implement frozen monotonic manifests, - UTC slots/CoalesceLatest/jitter, minimal lifecycle projection, atomic pages/ - recipients and witness-bound app submission. Prove mixed revisions/ticks, - suspended licence targets, cohort bounds, NULL-org dedup, forged/cross-tenant - witnesses, child acknowledgement loss, target scope/parameter binding, bounded - fairness and no general selector. -9. **Enforcement and packet closeout.** Finish full observation, exact production - censuses/planted violations, all carrier/feature/skill handoffs and the new job - skill. Run complete backend/frontend/demo regression and packaging/boot proof; - open the development → main PR with exact evidence. Real CI and maintainer merge - remain separate from local completion; zero production business definitions. - -#### Expanded H1 proposal review - -The final contract is drafted against the selected H1/expanded direction. The -historical receipts below approve only their earlier document revisions; they do -not substitute for two fresh reviews of this route-specific proposal. Current -review/validation evidence is appended here after it actually runs. - -Round 1 reviewed proposal commit `fa539176` with three fresh independent reviewers: -GPT-6-astra xhigh (state/authority), GPT-6.1-sol xhigh (external/capacity) and -GPT-6.1-sol xhigh (recurrence/corpus). All approve the Proposed documentation; -none accepts the ADR or authorizes runtime. The state reviewer found one minor -carrier omission: Standards 01/17 now explicitly distinguish the authoritative -tenant envelope from opaque vendor wakeups/ticks. No confirmed lifecycle, -unknown-COMMIT, generation, terminal-audit or ordinary-authority defect was found. - -Self-review additionally pins the disabled stock notification reconnect path and -server-side SQL deadlines, including the counter aggregator's unlimited driver -timeout. It makes future-due handoff checks and recurrence target parameter/scope -binding explicit. These are proposal clarifications, not runtime changes or proof. -Local validation passes five Release corpus tests, seven ADR workflow controls, -1,059 local links and 321 fragments, added prose wrapping and whitespace checks. -Prior ADR files and P02b-0–3 receipts remain byte-preserved against `71568e78`. -Fresh Round 2 reviewed the corrected complete proposal before final approval. - -Round 2 paired new GPT-6-astra xhigh (architecture/security/state) and GPT-6.1-sol -xhigh (corpus/recurrence/proof) reviewers on `29cc4c15` and the correction captured -by `40c9f9b8`. The latter fixes the retained-overrun bound: four is the atomic -stop-new-start threshold; already admitted workers may overrun together and must -remain owned, with a conservative workers-plus-four bound. Both reviewers verified -that correction and approve the Proposed documentation with no remaining required -findings. Simultaneous-overrun behavior is an explicit implementation proof duty. - -Final local checks again pass five Release corpus tests, seven ADR workflow tests, -1,059 links and 321 fragments with zero errors, prose/whitespace and preserved -historical records. All eleven changed files are Markdown; no runtime/dependency/ -migration/grant change or job production proof is claimed. Final maintainer -acceptance of ADR-0047 and this nine-step package remains required before runtime. - -#### Maintainer acceptance (2026-10-15) - -The maintainer explicitly approves the final ADR-0047 and this nine-step package. -G9 and the new job parts above are Accepted. Dated numbered Amendments in the -fifteen named prior ADRs disclose only the bounded replacements/additions; every -original byte, acceptance metadata and earlier amendment remains preserved. -The decisions index, glossary, current status carriers and first-consumer handoffs -now distinguish this accepted contract from pending implementation. - -The review/validation receipts above remain evidence of their Proposed revisions; -their pending-approval statements are historical. This acceptance creates no -runtime, dependency, migration, grant or enforcement evidence. The acceptance -commit precedes every implementation change; each later step owes its own -validation and two fresh independent review rounds. - -#### Earlier proposal and correction receipts (historical) - -These dated receipts precede the H1/expanded selection above. Their then-current -open-choice/scope statements describe those revisions, not this final proposal. - -#### Decision review and approval readiness - -The following receipts describe the earlier proposal reviews, not final current -readiness. The subsequent workload/corpus review reopens the gaps named above; -earlier review agreement does not select a runtime or override maintainer findings. - -Two fresh independent review rounds inspected the Proposed ADR/package against -current source and Accepted records. Each round paired GPT-6-astra xhigh for -transaction/security architecture with GPT-6.1-sol xhigh for corpus/proof coverage. -The original three scoping inspections are separate from those four reviews. - -- Round 1 corrections: explicit TenantWide/Organization declarations and exact - announcement matching; closed transient/permanent outcomes; finite option - maxima; trusted direct-consumer operation identity; named ADR-0040/0052 - framework read-only extension. Both reviewers rechecked the revised clauses - and found no remaining approval-blocking issue. -- Round 2 corrections: explicit conditional G8 job-scheduler bypass exemption, - ADR-0020's licence-job vendor/identity handoff and first-triggered 02c/08a - recurrence ownership, with architecture 24/26 included. Follow-up inspection - confirmed the blocking issues were closed. Related source checks also name - ADR-0015's exact dashboard bullet, app-side UUIDv7 identity and the unaffected - Hub/superseded-record boundaries. The package's earlier queue summary was - aligned with the same recurrence answer. - -Local validation passes: five Release corpus controls, seven ADR status/workflow -controls, relative links/fragments, added prose wrapping and whitespace checks. -All earlier P02b delivery/review receipts and every prior ADR file are byte-preserved -against `71568e78`. These are document/source checks; no job runtime exists and -no runtime acceptance proof is claimed. Maintainer approval remains pending. - -#### Hangfire comparison follow-up (2026-10-15) - -The maintainer requested this assessment rather than accepting the initial -PostgreSQL proposal. The [expanded ADR comparison](../decisions/0047-transactional-background-job-runtime.md#hangfire-alternative-assessment-2026-10-15) -owns alternatives, trade-offs, package/source pins and evidence limits. Stock -Hangfire plus an authoritative job record is viable; public transaction-aware -storage customization is also physically feasible. Neither is accepted here. - -Three research agents inspected exact upstream/package sources, current owner -contracts, dependencies, storage privileges and lifecycle boundaries. Isolated -database experiments passed eighteen focused cases on fresh PostgreSQL 18.4; -the owned container was removed and no existing service/database was touched. -The native transaction spike used SDK 10.0.302 outside the repository, not pinned -10.0.112. Separate exact-version invocation probes and .NET 10 dependency/basic -load checks are recorded in the ADR. These do not prove production audit, RLS, -worker/retry/cancellation or complete provider support. - -Two fresh reviewers, GPT-6-astra xhigh and GPT-6.1-sol high, checked the revised -comparison against sources and experiments. Both approved the evidence/framing -without required corrections; neither approved runtime implementation. Local -document/corpus/ADR controls pass. Runtime choice and final acceptance still -belong to the maintainer; a Hangfire choice revises the detailed design and steps -before any implementation. - -#### Workload and corpus correction pass (2026-10-15) - -Verified the maintainer's findings against current code and the original -authorities. Three read-only inspections covered early-consumer workloads -(GPT-6-astra xhigh), runtime correctness (GPT-6.1-sol xhigh) and corpus/governance -(GPT-6.1-sol high). These are source/document inspections, not new runtime tests. - -- Phase 04 already requires long ffmpeg work, its own capacity and a tenant limit. - The single transactional lane does not deliver that. The ADR now names the - separate external prepare/execute/finalize contract and an explicit first-use - gate, with a maintainer scope choice before route-specific acceptance. -- Phase 04's nightly media lifecycle can precede 02c/08a recurrence. Its trigger, - restricted tenant enumeration and isolated tenant submissions are distinct from - Phase 11's privileged audit DDL/purge. Phone-home's 02c ownership exists in - ADR-0020 Implementation notes; its missing phase-plan entry is restored. -- The candidate now uses unlocked preflight and a final lock/time recheck, an - ordered Result/exception retry table, deferred unknown/Pending definitions and - explicit retirement, plus a SystemActor Platform ceiling for root/nested/direct - execution. Strict org admission and role/column/index proof duties are explicit. -- Corrected exact authority locators, dated Amendment terminology, the implemented - credential-rule widening obligation, conditional consequences and the decisions - index. Proposed glossary terms precede implementation. Quartz.NET is a documented - candidate requiring its own qualification; no unsupported rejection is made. -- Skipped the alleged missing Date/Deciders violation: neither canonical template - requires those fields. The existing Draft date is honest Proposed metadata. - Kept PreparedDeliveryOwner delivery-specific; participant and commit gate are - separately named. Long URLs/tables remain exempt from prose-width limits. - -No Accepted decision, runtime, migration, grant or previously completed delivery -receipt is changed. This pass prepares the choice; it does not accept or implement -one. - -Correction review round 1 paired fresh GPT-6-astra xhigh (architecture/security) -and GPT-6.1-sol high (corpus/proof) reviewers over the corrections after `46ca923c`. -Both approved the Proposed documentation correction with no required findings; -neither approved a runtime or workload-scope selection. Local validation passes: -five Release corpus tests, seven ADR status/workflow controls, 1,035 local links -and 323 fragments, prose wrapping and `git diff --check`. All prior ADR files and -P02b-0–3 receipts remain byte-preserved against `71568e78`. These checks run on -documentation; no new runtime proof is claimed. - -Correction commit `ec1a5520` was reviewed in a fresh second round by GPT-6.1-sol -xhigh (architecture/security) and GPT-6-astra high (corpus/evidence). The corpus -review found one wrong section locator for ADR-0017's Jobs row; the linked -Defense-in-depth heading replaces it, and focused reinspection verified the fix. -Both reviewers approve the documentation correction with no remaining required -findings. Final local link/fragment checks count 1,036 / 324 with zero errors; -earlier ADRs/receipts and the docs-only scope remain verified. Runtime selection, -workload scope and final route-specific ADR approval remain pending. - -#### Validation and carrier ownership - -Use the existing provider/migration/MediatR/audit/architecture/integration workflows -and run-tests-locally. Test real PostgreSQL, guarded roles and the actual pinned -Hangfire workers; no EF in-memory substitute establishes isolation/atomicity. -Stage dependencies/feature definitions stay explicit; no mock production job. - -Acceptance/implementation reconciles ADR-0003/0010/0015/0017/0020/0023/0028/0032/ -0033/0036/0040/0044/0046/0052/0057 through dated Amendment navigation/additions, -plus ADR-0047 and the index. Standards 01/02/05/06/09/10/11/15/17/18/20/21/index receive -only implemented current rules; canonical DDL stays 05, metrics 10, proof names 21. -Standards 01/17 distinguish the tenant-bearing authoritative job envelope from -opaque vendor wakeups and tenantless ticks without weakening business isolation. -Architecture 04/09/16/24/25/26/29/30/31/33, Tenancy audit/permission specs, glossary, -root guidance/readmes, compose/launcher fixture wiring and applicable/new skills -must follow the same delivered boundary. Phase 02c/04/08a/08b/11 handoffs keep -business definitions/provider/privilege owners explicit. Hub endpoints are unchanged. - -P02b-8 inventories job/attempt/plan/outcome/reservation/recipient copies and vendor -control metadata for erasure. Phase 11 owns actual retention/purge authority and -intervals; stock vendor expiry deletes control metadata only, never authoritative -business intent. Phase 03 owns operator replay/reconciliation/permission/runbook; -no recovery route or unsafe reservation-release switch is exposed by P4. - -### P02b-4 Step 1 — contracts and authority (2026-10-16) - -**Complete — both fresh independent review rounds pass.** -The acceptance commit is `affa0aca`; this step follows it on `development`. - -SharedKernel supplies typed job/attempt/occurrence/recipient identities, the typed -scheduler port, immutable definition/profile/request/capacity/recurrence metadata -and external Execute/Reconcile/finalization contracts. Frozen registries validate -module ownership, exact roots/nested requests, profile/queue/pool bindings, finite -readiness and recurrence scope. Identifier-only parameter/plan/outcome serialization -uses closed DTO shapes, canonical round-trips and frozen options/resolver state. -No production business or recurrence definition is added. - -Application admission holds an immutable positive request ceiling independently of -later accessor changes. Exact framework pre-reads select physical ReadOnly through -the existing pipeline. Direct privileged/delivery/admin entry refuses even through -a fresh service scope or permissive platform gate. A guarded lazy bypass-source -facade checks every synchronous/asynchronous connection acquisition, including warm -pools, and owns cleanup. API/Seeder register the same empty job catalogues; neither -registration activates a scheduler, vendor, migration or worker. - -Two architecture methods pin the current admission/credential callsites with -planted violations. The nineteen complete ADR-0047 obligations remain Registered; -these slice proofs do not claim the later runtime is implemented. Existing exact -credential/context/owner censuses stay enforced. The catalogue counts 221 methods. - -Initial Release validation passes the solution build with CI warnings-as-errors, -1,979 unit, four contract, 176 Docker-free and 1,389 Docker integration tests, with -zero skips. The first full architecture run reports 312 passed and two stale -expectations: the published method count and TransactionBehavior constructor pin. -Both are corrected without widening module/DbContext permissions; an architecture -rebuild and six focused corpus/constructor reruns pass. This gives 314 unique -passing architecture cases and 3,862 unique passing backend cases across the -full runs and focused corrections; it is not a second full architecture run. -Formatting passes for all 67 changed C# files. The documentation check resolves -2,506 local links and 590 fragments, with no wrapping/whitespace errors. Every -ADR/index remains byte-identical to acceptance commit `affa0aca`; earlier delivery -and proposal-review receipts stay preserved. Both fresh independent review rounds -remain pending; later receipts record their actual results. - -#### Step 1 review round 1 - -Two fresh independent reviewers inspect `affa0aca..94b126b4`: GPT-6-astra xhigh -for authority/lifecycle/credential confinement and GPT-6.1-sol xhigh for contracts, -registries/serialization/recurrence and corpus evidence. Both request changes for -one independently reproduced Major each; neither finds a Platform escape or a -current production job caller. - -- A retained already-entered nested request can have an open top frame after its - root closes. The common request/owner admission now checks every ancestor, while - preserving awaited nesting and framework owner entry with no current request. - Real ISender regression proves refusal before handler construction; its dirty - case fails before the correction and its awaited positive control passes. -- A handwritten getter/init accessor can change the returned identifier after the - canonical reads. Closed identifier DTOs now require compiler-generated automatic - getters and init setters, preserving positional/nonpositional auto-properties - and constructor round-trip checks. Three dirty registration/read cases fail - before the correction and pass afterward. This is an immutable DTO convention, - not an arbitrary CLR-code sandbox. - -Root verifies both findings, adds six regression cases and applies the minimal -corrections. The corrected solution builds Release with CI warnings-as-errors; -1,985 unit, all 314 architecture, four contract and 176 Docker-free integration -cases pass with zero failures/skips. The 1,389-case Docker run above covers the -initial implementation; it is not rerun for these nonactivated job guards. No -vendor/schema/production definition is introduced. A fresh second review round -follows the correction commit before Step 2 starts. - -#### Step 1 review round 2 and closeout - -Fresh GPT-6-astra xhigh (authority/lifecycle/security) and GPT-6.1-sol xhigh -(contracts/registries/tests/corpus) reviewers inspect the complete corrected range -`affa0aca..bf433085`. Both approve Step 1 with no remaining required findings. -The authority reviewer independently passes 168 focused unit and 78 architecture -cases; the contracts reviewer passes 168 focused unit and 14 architecture cases. -All use existing Release binaries with zero failures/skips. These overlapping -checks are not added to the complete-suite counts above. - -Both verify the ancestry/accessor corrections, unchanged Accepted ADRs, exact -credential/owner boundaries and the honest zero-runtime-subject scope. Recurrence -precision is a named next-step constraint: before Step 2 fixes PostgreSQL storage -representation, reject sub-microsecond manifest facts before fingerprinting. -No production job or recurrence is activated to satisfy a census. - -The implementation commit is `94b126b4`; verified Round 1 corrections are -`bf433085`. Both fresh rounds and the validation recorded above are complete. -Step 2 now proceeds under the already accepted nine-step package. Remaining -runtime/dependency/storage/worker guarantees are not delivered by this closeout. - -### P02b-4 Step 2 — storage and guarded vendor bootstrap (2026-10-16) - -**Complete — both fresh review rounds and critical-fix verification passed.** -This step follows the completed Step 1 on `development` under Accepted ADR-0047. - -Two Platform migrations introduce seven authoritative job/control tables and the -pinned stock Hangfire version-23 inventory. Standards 05 owns their canonical -DDL/grants and the explicit vendor-control table class. Existing schema sweeps -enumerate all public tables, classify expected application SELECT denial, and -continue actual tenant/organization isolation checks as `learnstack_app`. - -The vendor connection factory crosses the existing guarded lazy source on every -acquisition. Reset-safe server statement/lock deadlines bound SQL execution; -Accepted ADR-0058 requires finite enabled driver I/O and adds five-second -idle-session cleanup. The post-acceptance implementation and real source/reset -proofs are recorded below. Bootstrap verifies version, guard bodies/triggers, -exact grants and -metadata before constructing the provider. No production wrapper, scheduler -or worker is activated by this step. Runtime admission, business completion, -external execution and recurrence remain Steps 3–9. - -Recurrence facts now reject sub-microsecond precision before fingerprinting so -durable PostgreSQL reconstruction cannot silently change a declared manifest. -The dependency graph, corresponding-source/notice kit and copied publish output -are part of this step's validation. Passing evidence and review dispositions are -recorded after the actual checks; source-only inspection is not a runtime proof. - -**New qualification boundary.** The exact stock counter component overrides the -driver timeout with zero. PostgreSQL statement/lock deadlines pass blocked-SQL -checks, but a response-withholding proxy leaves the actual component pending. -[ADR-0058](../decisions/0058-bounded-stock-hangfire-maintenance.md) is Accepted — -2026-10-16 for the selective maintenance configuration and ownership controls -reviewed in the [reassessment](#step-2-maintenance-reassessment). The earlier -socket-exception proposal is withdrawn. The -[acceptance receipt](#step-2-maintenance-acceptance-2026-10-16) records the approved -boundary; Step 4 runtime qualification remains pending. This step -claims no Step 4 runtime qualification. Source/reset and schema validation pass -after acceptance as recorded below; formal Step 2 review closeout remains pending. - -#### Step 2 counter-maintenance decision review - -The isolated exact-pin response-loss experiment is independently repeated by the -root agent on PostgreSQL 18.4: the actual stock counter task is still pending at -eight seconds; closing the owned proxy sockets settles it with NpgsqlException. -Both disposable containers/proxies are cleaned up. This proves the missing -driver bound, not the proposed replacement ownership behavior. - -A fresh GPT-6-astra xhigh reviewer requests two corrections to Proposed ADR-0058: -name both read/write I/O, and pace held/not-due returns because stock Core -immediately reinvokes successful components. Root verifies and incorporates both. -The shared pool minimum and real disposal/late-cleanup proofs address the same -review's availability caveat. A new GPT-6.1-sol xhigh reviewer independently -approves the corrected whole proposal with no required findings after checking -the exact Core/provider/Npgsql source and governance. Neither review claims -passing runtime tests for the unimplemented maintenance owner. - -#### Step 2 maintenance reassessment - -The maintainer returns Request changes, not acceptance, on 2026-10-16. The -initial proposal/reviews above are historical receipts; they do not close the new -findings. Two independent source/research agents, GPT-6.1-sol xhigh and -GPT-6-astra xhigh, verify the exact pinned Core/provider/Npgsql sources. Root -independently reproduces PostgreSQL 18.4 timeout behavior. - -| Review issue | Verified disposition | -|---|---| -| Supersession/additive scope conflated | Valid. Revised Proposed ADR-0058 distinguishes selective configuration replacement from additive ownership/health/test seams; its former socket exception is withdrawn. Acceptance will name both in ADR-0047's dated amendment. | -| Suppression loses all counter maintenance | False rejection premise in the earlier draft. Stock expiration deletes expired counters and compacts the two nonexpiring state totals; removal is now the proposed alternative. | -| Expiration's five-minute wait and minimum-two sizing | Valid distinction. Retry-loop/whole-pass occupancy differs from per-command I/O. Two was never a topology capacity proof; that proposed rule is withdrawn. Step 4 must enumerate and qualify the actual supported acquisition floor. | -| Aborted transaction retains former row locks | Not reproduced. A positive active lock is released on abort; a concurrent update succeeds before the timeout response is read. Idle-aborted session occupancy remains real and is tested separately. | -| Missing interval/inventory/proof specificity | Valid. Revised proposal pins exact component/filter inventories and the expiration interval, assigns enforcement to Step 4, and maps proofs to the two existing canonical rules. | -| Incorrect timeout anchor/ambiguous defaults | Corrected. The source link names Npgsql's actual timeout selection; driver defaults, statements and invocation waits are distinguished. | - -The proposed direction suppresses only stock `CountersAggregator` and optional -`StatisticsHistoryAttribute`, preserving stock expiration/heartbeat and every -finite command/socket requirement. Expiration still needs single-flight retained -ownership: cancellation does not enter its synchronous SQL or lock-acquisition -loops. Healthy pass pacing, shared shutdown and independent progress remain -pending actual-runtime obligations, not consequences assumed from suppression. -No production owner, filter removal or new source deadline is activated here. - -**Reproducible qualification commands** (Python 3, Docker and .NET 10): - -```bash -python3 third-party/hangfire/qualification/probe-maintenance.py -python3 third-party/hangfire/qualification/probe-pg-timeouts.py -``` - -The first command builds only a disposable exact-package project and starts an -owned random-loopback PostgreSQL 18.4 container. It invokes actual stock -`ExpirationManager.Execute`, the public filter-removal hook and actual stock -aggregation through an ACKing response-withholding proxy. The second uses the -PostgreSQL simple-query protocol to withhold client reads while an independent -observer inspects backend/lock state. Both use synthetic data, finite waits and -owned cleanup. They touch no development database or shared repository binaries. -Neither substitutes for `learnstack_outbox_admin`/real worker/owner proofs. - -**Measured counter footprint.** Exact stock version-23 schema, default indexes, -fresh/truncated table per case and autovacuum disabled for repeatable sizing. -The denominator is vendor transitions between cleanup passes, not business jobs. -Bytes are `pg_total_relation_size(counter)` including relation/index overhead; -they exclude WAL, replication, other vendor tables and production bloat. - -| Transitions | One-row ordinary success | Two-row transition envelope | -|---:|---:|---:| -| 1,000 | 1,000 rows / 172,032 B | 2,000 rows / 286,720 B | -| 10,000 | 10,000 rows / 1,048,576 B | 20,000 rows / 2,007,040 B | -| 100,000 | 100,000 rows / 9,650,176 B | 200,000 rows / 19,210,240 B | - -The actual stock expiration pass reduces those six cases to one/two live rows -and preserves the tested positive totals. Ordinary VACUUM does not shrink the -previously allocated footprint in these cases. Stock delete-then-insert compaction -is not atomic, can lose a subtotal and drops nonpositive raw sums; this experiment -does not prove exact statistics accounting. Removal loses new vendor timelines. -Cleanup outages and retained snapshots can grow backlog/disk, and failed vendor -wakeups have their own nonexpiring retention. No bounded-disk or recovery-rate -claim is made. - -The actual aggregator remains pending at eight seconds despite requested -cancellation and five-second server/driver defaults. Releasing its proxy sockets -settles the owned task with a driver failure; this proves the removed path's -qualification gap, not a passing replacement owner. PostgreSQL's active lock -control holds one relation lock; the aborted state holds zero and an independent -update succeeds. Two 350 ms statements pass a 500 ms per-statement limit; a -500 ms idle-in-transaction limit terminates the remaining aborted backend. -Idle cleanup is session hygiene, not a guarantee that an ACKing proxy releases -its client socket. - -Standards 20's existing `hangfire`-schema drift is independently corrected against -Accepted ADR-0047 (`public`). Proposed ADR-0058 changes remain approval-gated; -the two fresh proposal review rounds and their dispositions are recorded after -they actually run. - -**Revised proposal Round 1.** A fresh GPT-6-astra xhigh reviewer approves the -whole revised proposal, carrier edits and qualification artifacts with no -remaining findings. The initial component-name mismatch is corrected to the -actual `PostgreSqlHeartbeatProcess` type. Root reruns both committed-source -experiments successfully: all six footprint cases, expired/future controls, -public selective component/filter removal, eight-second blackhole retention and -late cleanup, and all PostgreSQL timeout/lock controls pass. Both owned containers -and temporary projects are removed. The reviewer independently checks 450 local -links/fragments, Python syntax and scoped whitespace. This is proposal review, -not either formal Step 2 runtime/schema review or maintainer acceptance. - -**Revised proposal Round 2.** A new GPT-6.1-sol xhigh reviewer independently -approves `f5dd3a44..446d0a5f` plus the qualification-source formatting and protected -timeout-probe cleanup edits, with zero required findings/nits. Both isolated -commands pass again in that review, including all six footprint measurements, -selective component/filter controls, actual expiration and the PostgreSQL -abort/session controls. Owned teardown completes. The probe's non-whitespace C# -characters are unchanged by formatting; folder-based format verification passes. -Neither reviewer modifies files or uses proposal approval as runtime acceptance. - -Seven ADR-parser controls pass and ADR-0058 parses as Proposed. The changed-doc -audit checks 37 Markdown files, 2,673 local links and 621 fragments with zero -errors; whitespace is clean. Accepted ADR bodies remain byte-identical to the -P02b-4 acceptance commit `affa0aca`. These decision experiments are not added to -backend regression counts. Both fresh proposal rounds are complete; maintainer -acceptance and Step 2/4 runtime qualification remain pending. - -#### Step 2 maintenance acceptance (2026-10-16) - -The maintainer explicitly approves the revised ADR-0058. Its status is Accepted — -2026-10-16. ADR-0047 Amendment 1 records the maintenance configuration replacement -and additive ownership seams without rewriting its body or acceptance metadata. -The dated proposal/reassessment/review receipts above retain their original -as-of state; this receipt closes only their maintainer-acceptance gate. - -The approved configuration suppresses only exact stock `CountersAggregator` and -`StatisticsHistoryAttribute`, preserving stock expiration/heartbeat, state counters -and required admission/retry filters. Finite enabled command/socket bounds remain; -there is no unlimited-command exception. The shared source gains reset-safe -`idle_in_transaction_session_timeout=5000`, with no shared `transaction_timeout`. -At this acceptance receipt the new setting is authorized, not implemented; -source/reset, successful outbox/delivery and real aborted-idle proofs remain Step 2 -work. Full Step 2 validation and both fresh runtime/schema review rounds remain -pending. - -Step 4 owns exact component/filter selection, one shared expiration owner, -one-millisecond internal interval, completion-based one-hour cadence, bounded -wait/cleanup, shared shutdown and truthful retained-maintenance health. It also -owns the final simultaneous physical-acquisition census, enforced supported -configuration/floor and independent progress under contention. No minimum-two or -nonpooled prohibition is accepted. Step 9 owns full observation/enforcement and -regression. Standards 05/20/21 and the Events and Outbox architecture carry the -accepted policy; the existing bootstrap and independent-capacity obligations -remain Registered. Acceptance claims no implemented maintenance owner, runtime -proof, packet closeout or production-capacity/disk guarantee. - -#### Step 2 implementation and validation after acceptance - -ADR-0058 is accepted in `14bf9c42` before its dependent runtime edits. The shared -guarded source now sends reset-safe five-second statement, lock and idle-session -deadlines. Explicit bootstrap refuses disabled/excessive idle deadlines. Real -`learnstack_outbox_admin` sessions prove cold settings, the same physical backend -after pool reset, idle and aborted-idle termination while the transaction remains -checked out, and healthy reacquisition. Dirty zero/5,001 ms startup controls fail -bootstrap beside a healthy production-source control. Existing outbox/delivery -store and execution proofs pass with the new shared-source setting. - -The two Platform migrations and canonical Standards 05 deliver seven raw -authoritative/control tables and stock vendor schema 23 with exact four-role -grants. Tenant/org scope, immutable envelopes/checkpoints, reservation evidence, -recurrence slots/recipients, six-stage ceilings, schema rollback/reapply and actual -ordered locking index plans have real PostgreSQL controls. Whole-schema discovery -classifies all 47 public tables, including five migration histories, rather than -omitting denied control/vendor tables. App SELECT denial requires actual `42501`. -The genericity source census now classifies embedded production SQL and decodes -its literals; Docker-trait discovery resolves partial declarations structurally. -The existing Education parent-constraint sweep includes the seven new raw job -relations with explicit guard/FK dirty controls instead of excluding them. - -**Validation before the final column-grant correction:** Release CI-style build passes -with zero warnings/errors; formatting and whitespace pass. Unit 1,995, -architecture 315, contract 4, Docker-free integration 176 and complete Docker -integration 1,552 pass: **4,042 backend cases, zero failures/skips**. The focused -197-case source/outbox/delivery run also passes and overlaps the complete run; -it is not added to that total. TRX runner checks confirm each assembly ran and -none skipped. Earlier failed intermediate runs and their corrected focused -receipts are superseded by this fresh full run. The final self-review correction -also refuses column-level `GRANT OPTION` during bootstrap. Its subsequent Release -build passes with zero warnings/errors and all 34 Hangfire storage cases pass, -including the new dirty grant and restored-role control. A fresh full run of the -correction commit is recorded with the independent reviews after it completes. - -Framework-dependent API publish passes the actual graph/source/notice verifier: -four vendor assemblies match original NuGet bytes, both exact corresponding-source -archives and eleven licence/notice files verify. Ten planted distribution defects -refuse and explicit recipient-replacement inspection succeeds. Hosting 10.0.12 -is verified in the referenced Infrastructure graph; API/publish use the shared -framework. The actual local host is .NET/ASP.NET Core 10.0.10, not an inferred -NuGet patch. The pinned provider SQL resources remain byte-identical upstream. -The complete Apache 2.0 text accompanies its original Dapper/Core notices. -Narrow stock-byte Git attributes preserve upstream line endings/notice whitespace; -forced `autocrlf=true` checkout verifies all 32 SQL/licence/notice input hashes. -First-party whitespace checks remain enabled. - -No worker, wrapper, production definition or recurrence is activated here. -Step 4 still owns selective component/filter suppression, the retained expiration -owner, enabled-path response-loss and supported-pool-boundary progress controls; -Step 9 owns complete enforcement. Those obligations remain Registered. The -full Step 2 implementation is now committed for its first fresh review round; -both round dispositions and verified fixes are recorded after they run. - -#### Step 2 review round 1 and verified corrections - -Three fresh reviewers examine `1b4ec7f4..583374f5`: GPT-6-astra/xhigh owns -schema/isolation/state/indexes; GPT-6.1-sol/xhigh separately owns the vendor/source -boundary and the proof/corpus lens. Their formal reports precede their authorized -fix work. Root verifies four required findings against the implementation: - -- **Eligibility proof:** volatile candidate clocks scan 6,000 future rows when - fewer than ten rows are due. Stable statement-time cutoffs now supply actual - index bounds. Four migrated-schema controls cover zero/five due rows and detect - the old volatile scan; live post-lock lease checks remain separately required. -- **Stored metadata:** a guard re-enabled after an invalid durable write did not - make the old partial startup scan reject every closed field. Shared read-only - predicates now serve post-redaction writes and startup, covering every vendor - metadata store. Twenty-six committed-drift/restored controls exercise them. -- **Stock shape:** names/version alone accepted a missing unique key required by - stock `ON CONFLICT`. Startup now checks 58 column facts, 17 keys/constraints, - 29 index definitions and nine sequence configurations/associations. Eleven - dirty/restored controls cover types/defaults/nullability/keys/indexes/sequences. -- **Embedded material:** stock Core merges Cronos 0.11.1. Its exact MIT notice and - corresponding source are now in the kit, independently pinned to source commit - `b2050abdf910bf5c3b7262d1a09d2c04c0f56f58`, with five new failure controls. - -The live decisions index also distinguishes delivered source/reset proofs from -pending Step 4 ownership and Step 9 enforcement. Accepted ADR bodies and earlier -proposal/delivery receipts remain unchanged. - -Correction validation passes: Release build with zero warnings/errors; **193 -focused PostgreSQL cases**, zero failures/skips, in the final focused TRX. The -actual fresh API publish verifies three source archives, twelve licence/notice -files and original stock assemblies; fifteen planted defects refuse and recipient -replacement inspection passes. Canonical guard SQL matches its embedded resource; -first-party links/fragments, history preservation and whitespace pass. - -The first full correction-head Docker rerun was interrupted when its existing -container stopped along with unrelated running containers. It is not passing -regression evidence. Full regression is rerun after this correction commit and -recorded with fresh Round 2. No worker/business activation is claimed here. - -#### Step 2 review round 2 and external-outcome corrections - -Three new reviewers independently examine `1b4ec7f4..a593cd22`: GPT-6-astra/xhigh -owns storage/state/isolation; two GPT-6.1-sol/xhigh reviewers separately own the -vendor/source and proof/corpus lenses. The latter two approve their code/proof -scope. Root verifies the corpus review's stale live CLAUDE entry and reconciles it -with the other status carriers, preserving dated historical receipts. - -The storage reviewer reproduces a prohibited second ExecuteIntent after a durable -successful external outcome using real app/dispatcher roles with guards enabled. -Root also verifies that quiescence without a known outcome was incorrectly enough -for retry/release/terminalization. The correction now: - -- refuses a new normal cycle after success or selected finalization; -- requires known outcome plus quiescence, or positive no-start, for a prior normal - attempt, excluding only the newly inserted receipt during its own admission; -- keeps unknown effects from pending/finalize/terminal transitions and reservation - release, retaining occupancy; -- preserves failed/cancelled retry and separately counted finalize stages. - -Five real-role regression cases distinguish success, failed, cancelled, selected -failure finalization and unknown effect. The original twelve-receipt positive -fixture now records retryable known failures before its last successful normal -attempt. An independent scratch PostgreSQL control observes the old Unknown path -commit a second ExecuteIntent, then verifies the corrected refusals and both -known-failure positive controls. Its owned containers are removed. - -**Validation boundary:** the preceding Release binaries pass Unit 1,995, -architecture 315, contract 4, Docker-free integration 176 and Docker integration -1,594: **4,084 cases**, zero failures/skips. The final outcome correction then -passes a fresh Release build with zero warnings/errors and **198 focused -PostgreSQL cases**, zero failures/skips. Full canonical DDL equality and first-party -link/fragment/history/whitespace checks pass. Fresh final-binary regression and an -additional independent critical-fix review follow the correction commit; neither -is claimed complete in this receipt. - -#### Step 2 final proof and closeout - -Initial implementation is `583374f5`; Round 1 verified corrections are -`a593cd22`; Round 2 outcome corrections are `5d55ee78`. A new GPT-6-astra/xhigh -reviewer independently approves `a593cd22..5d55ee78` with no confirmed findings. -It traces first/next admission, known/unknown effects, finalize, terminal and -reservation paths, SQL-null behavior and exact refusal-message controls; canonical -SQL parity and whitespace pass. This is source review, not a claimed test rerun. - -Fresh final binaries from `5d55ee78` pass **4,089 backend cases**: Unit 1,995, -architecture 315, contract 4, Docker-free integration 176 and complete Docker -integration 1,599, zero failures/skips. The final focused 198-case run overlaps -that total. TRX runner checks require all four assemblies and zero unexecuted cases. -Release CI-style build has zero warnings/errors; formatting passes. These fresh -receipts supersede the interrupted Docker rerun and earlier regression heads. - -The final API publish independently verifies three complete source archives, -twelve licence/notice files, the actual package/framework graphs and original -stock assemblies. Fifteen planted defects refuse; recipient replacement inspection -passes. A forced `autocrlf=true` checkout preserves all 36 upstream SQL/material/ -archive hashes. Canonical SQL/resource equality, first-party links/fragments, -Accepted ADR/history preservation and whitespace pass. Owned test/probe containers -and proxies are cleaned up; the two previously running Saydin services are running. - -Both required fresh Step 2 review rounds, all verified corrections and the extra -critical-fix review are complete. No unresolved finding remains in this step. -Step 3 now owns submission and app-role admission. Step 4 still owns actual worker/ -component/filter/maintenance/pool qualification; Step 9 owns full observation and -enforcement. Both extended ADR-0058 catalogue obligations remain Registered. -No production job definition, recurrence or worker is activated by Step 2. - -### P02b-4 Step 3 — submission and app-role admission (2026-10-16) - -**Step 3 complete; both fresh independent review rounds passed.** -Accepted ADR-0047 and the approved Step 3 plan govern this work; no new decision -or worker activation is implied by this record. - -Submission stamps the actual typed producer operation, live announcement and -physical transaction. The ordinary scheduling port accepts only its declared -parameter type and owning module, requires exact tenant/organization scope, -and inserts intent on that same transaction. Serialization and injected clock/ID -operations cannot borrow stale enrollment. Successful INSERT adds a sticky -produced-work receipt; the existing owner remains responsible for commit. - -Routing claims are separate from business attempts. An opaque returned-row claim -authorizes only the exact framework read/start requests. App-role envelope -validation uses a physically read-only frame before installing the verified -Ambient/SystemActor context. A separate writable start frame locks/rechecks the -row and can authorize later execution only through an acknowledged-commit -receipt. Unknown COMMIT is not activation authority; acknowledged commit remains -distinguishable from subsequent cleanup failure. - -The committed proof set covers real app-role isolation, immutable routing facts, -read-only validation, unknown/Pending/early/stale callbacks, concurrent starts, -lock-wait expiry, absorbed producer refusal and uncertain commit. No business -request/handler may be constructed by admission. Capacity-bound/external starts -remain deferred until their approved implementation steps. - -The first full run exposes three obsolete proof expectations: synthetic request -metadata is no longer allowed to select physical read-only mode; failed audit -rows remain durable after rollback; organization-scoped audit reads need the -same organization announcement. The corrected expectations retain all business/ -job rollback assertions. A planted overload also exposes a detector exception; -explicit declaration-count diagnostics now distinguish the violation from a -clean production baseline. - -Root independently reproduces DI stopping disposal after the first throwing -async disposable. The executor retains each actual unit before handler resolution -and awaits its cleanup if scope disposal faults, while keeping context/authority -installed. Physical connection-close controls pass for failed pre-read cleanup -and post-acknowledgement start cleanup. Activity observer faults also preserve -acknowledged receipts and restoration. - -Release CI-style build has zero warnings/errors. All **38 focused PostgreSQL -cases pass**, zero failures/skips, including real physical generation substitution -at constructor/clock/ID callbacks, read-only RLS and write-refusal controls, -forced concurrent starts, lock-wait expiry, dropped COMMIT acknowledgement and -cleanup faults. Typed Pending submission commits backlog but cannot route/start. -Unit 2,018, contract 4 and Docker-free integration 176 pass; the complete -architecture suite separately passes 315 cases, including dirty/clean capability -controls. Full solution formatting verifies 972 files without changes; seven ADR -parser controls and local link/fragment/history/whitespace checks pass. -The final combined Docker-free receipt and complete Docker regression remain -pending in this receipt. Neither formal review round is claimed by self-review. - -#### Step 3 review round 1 and verified corrections - -Initial implementation is `63a7f4ac`. Three fresh independent reviewers inspect -`483463fa..63a7f4ac`: GPT-6-astra/xhigh for authority/transaction boundaries, -GPT-6-astra/xhigh for PostgreSQL/admission/concurrency, and GPT-6.1-sol/xhigh -for proof/census/composition/corpus. Authority and proof reviews approve with -no findings. Storage requests one verified correction: submission inherits -the general app source's 30-second or unlimited command timeout, violating -the accepted positive SQL budget of at most five seconds. - -The storage reviewer independently reproduces the pinned-driver defaults and -real PostgreSQL blocked-INSERT behavior in a private disposable database. Root -confirms the actual production command and accepted bound. Submission now validates -the existing runtime options, applies an explicit command timeout and links its -SQL cancellation deadline. Successful INSERT alone records produced work; -statement failure still poisons the same owner. The same source review also -identifies that announcement/COMMIT surrounding framework commands needs a bound; -the executor gives each exact read/start frame its own SQL deadline, retained -through actual cleanup. Unknown COMMIT still creates no activation receipt. - -The combined Docker-free run passes all four assemblies: Unit 2,018, -architecture 315, contract 4 and integration 176 — **2,513 cases**, zero failures -or skips, with runner nonempty/zero-skip validation. The initial complete Docker -run executes 1,637 cases: 1,636 pass and one old domain-event cleanup test fails -because its reflection call still supplies three producer-enrollment arguments -after the signature gained two optional attribution arguments. Root checks every -reflection reference and adapts that test to five arguments without changing its -cleanup/rollback assertions. This failed run is not a passing regression receipt. - -The corrected Release build passes with zero warnings/errors. All 66 focused -PostgreSQL cases pass, zero failures/skips: the 40 Step 3 cases include a real -FK-lock-blocked INSERT and a live session withholding the actual start COMMIT -acknowledgement; the other 26 cover domain-event production and the adapted -reflection call. The timeout controls use an unlimited actual app command default, -prove the production deadline wins before their independent proof timeout, and -retain poisoning, no-false-receipt, physical cleanup and restoration assertions. -Unit 2,018 and contract 4 pass again. The combined full backend rerun remains -in progress; no empty-filter run is counted as evidence. Round 2 has not started. -No runtime outside the approved Step 3 boundary is added. - - -#### Step 3 review round 2 and final closeout - -Three new independent reviewers inspect the complete `483463fa..0ddcb3e7` -implementation and its `63a7f4ac..0ddcb3e7` correction: GPT-6-astra/xhigh for -application authority/owner boundaries, GPT-6-astra/xhigh for PostgreSQL/storage, -and GPT-6.1-sol/xhigh for proof/census/composition/corpus. All approve with zero -verified Blocker, Major or Minor findings. They inspect actual source and existing -receipts without shared builds or repository edits; their source reviews do not -claim independent test execution or a completed full regression. - -Root's final CI-split regression at runtime head `0ddcb3e7` passes Unit **2,018**, -architecture **315**, contract **4**, Docker-free integration **176** and Docker -integration **1,639** — **4,152 backend cases**, zero failures/skips. The correct -`Requires=Docker` run includes the forty Step 3 PostgreSQL cases; the focused -66-case receipt additionally repeats all 26 domain-event production controls. -Every counted assembly/slice passes the nonempty/zero-skip runner assertion. -Release build remains zero warnings/errors; formatting, seven ADR parser controls, -local links/fragments, prior-ADR/history preservation and whitespace pass. - -A mistaken `Category` filter mixed HTTP and Docker tests in one integration -process, exposing startup/Activity assertions; that run was canceled and is not -passing evidence. An empty filter was also rejected by the runner and is not -counted. The exact `Requires` slices above replace those commands without -weakening production code or test assertions. The earlier reflection-signature -failure remains recorded in round 1; its corrected domain-event test passes. - -Both required review rounds and every verified correction are complete. Step 4 -owns stock workers, bridge/repair, component/filter selection, expiration ownership -and supported-pool qualification. Step 5 owns business completion/retry/terminal -execution; capacity/external/recurrence and full enforcement retain their approved -Steps 6–9. No production business definition, recurrence, worker or dashboard is -activated by Step 3. Work remains on `development`; no push, PR or CI-head success -is implied by this local step closeout. - -### P02b-4 Step 4 — server-generation decision (2026-10-16) - -**Current authority:** [maintainer acceptance and the Step 4 adaptation](#maintainer-acceptance-and-step-4-adaptation-2026-10-16) -below accept ADR-0059 on 2026-10-16. The following preparation and review receipts -retain their original pre-acceptance state; implementation is in progress and full -production qualification remains pending. - -**Preparation only; ADR-0059 Proposed, approval pending.** Step 3 closes at -`def48a1a`, with runtime `0ddcb3e7` and both required fresh review rounds complete. -The complete H1/expanded implementation remains authorized, but the newly exposed -server-lifecycle choice needs explicit approval: ADR-0047/0058 select H1 and -retention, but do not select a constructor or automatic-restart policy. -No dependent worker, maintenance or restart runtime is activated here. - -Exact-pin source inspection exposes a lifecycle qualification gap: Core links -child shutdown to its restart token, catches canceled joins and disposes live -children before announcing a replacement. `ShutdownTimeout=Infinite` alone does -not fix automatic restart. A connection-floor calculation based only on one -configured generation is therefore conditional, not an accepted/proven number. -The stock missing-server and sustained-heartbeat-failure paths both matter. - -[ADR-0059](../decisions/0059-owned-hangfire-server-generations.md) proposes an -owner per pool, public stock process composition, synchronous context capture, -classified heartbeat retries and replacement only after actual stock/LearnStack -cleanup. An affected pool can remain unhealthy/stopped while its work is unresolved; -healthy pools remain independent. Host stop retains the existing one finite -external budget. Stock SQL/binaries, roles/grants, job attempts, reservations and -business authority are unchanged. A restart never supplies external quiescence. - -The decision-support probe uses actual pinned Core 1.8.25 dispatcher/server code, -provider 1.21.1 loaded identity and the repository's pinned Npgsql/Newtonsoft graph, -with fake storage to force lifecycle events. It uses no production credential, -existing service/database or shared repository build output. The launcher builds -in an owned temporary directory and takes versions from the central package file: - -```sh -python3 scripts/probe-hangfire-lifecycle.py -``` - -| Probe | Required distinction | -|---|---| -| Stock restart | Second generation while first actual work remains live; old context token handles are disposed despite infinite internal shutdown | -| Fault before synchronous capture | Actual required watchdog is held; stop occurs first; capture still executes, supplied workers stay closed, no early disposal/replacement | -| Fault after worker start | One actual generation remains owned through finite caller wait; release precedes shutdown witness and actual join | -| Managed supplied-builder fault | Guarded failure requests draining, retains earlier actual work and skips later builders | -| Raw supplied-builder fault | Dirty control reproduces early joined outer owner and disposed tokens while actual work remains live | -| Direct process-exit callback | Dirty child remains live inside Core cancellation after the finite host wait; parent terminates and joins it | -| Closed process-exit relay | Actual Core exit runs without joining the held private callback/stock process; child exits zero, without a cleanup/quiescence claim | - -These are assertion-bearing isolated feasibility controls, not LearnStack's -production worker/PostgreSQL regression or implemented catalogue enforcement. -Generic heartbeat retries, multiple pools, partial-resource construction, -source disposal, actual wrapper/business cleanup and restart-after-cleanup still -owe real production controls. Fatal memory/thread-start failures are not qualified -by the controlled managed-builder experiment. Missing context or elapsed waiting -cannot be interpreted as successful cleanup. - -#### Proposal review round 1 and verified corrections - -Two fresh independent reviewers inspect `def48a1a..f8ff691f`: GPT-6 Astra with -xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers -proofs/corpus/governance. The proof reviewer independently builds/runs all five -initial controls, checks links/history and interrupts the actual launcher to -verify owned-child cleanup. It approves without a finding. The lifecycle reviewer -confirms two Major decision gaps; root verifies both against pinned vendor source: - -- The cached provider fetched-job heartbeat cannot belong to the replaceable - control generation. The revision gives shared stock heartbeat/expiration an - API-instance owner independent of every pool; all Core servers exclude provider - component hosting. Control-pool-held-drain/healthy-pool renewal becomes an - explicit real-production proof obligation. -- Core's synchronous process-exit cancellation is a separate boundary from the - finite host wait. The revision selects zero last-chance wait and a closed, - asynchronous cancellation relay, requires child-process qualification and - forbids treating exit/forced token signals as cleanup or external quiescence. - -The lifecycle reviewer then provides isolated exit-control implementation help; -that support is not a fresh review of the revision. Root inspects/integrates it -and independently passes all seven committed controls with zero build warnings -or errors. The unsafe direct callback stays held until parent-owned termination; -the positive observer confirms actual Core exit while private work remains held. -Every child is joined before its temporary build tree is removed. These remain -narrow feasibility controls, not production qualification. ADR-0047/0058 are -byte-preserved; acceptance and all dependent Step 4 runtime remain pending. - -Root also interrupts the launcher while its unsafe exit callback is held: -launcher exit 143, the actual child is gone and the owned temporary tree is -removed. Five Release corpus controls and seven ADR parser controls pass; the -first-party sweep checks 37 Markdown files, 2,708 local links and 643 fragments -without errors and preserves all prior authorized history. These are focused -proposal checks; the full 4,152-case Step 3 result is not rerun or relabelled. - -#### Proposal review round 2 and approval-readiness closeout - -Two new independent reviewers inspect `def48a1a..878bcd49` after the verified -first-round corrections: GPT-6 Astra with xhigh effort covers lifecycle/authority; -GPT-6.1 Sol with xhigh effort covers proofs/governance. Both approve the Proposed -change with no Blocker, Major or Minor finding. Each independently builds/runs all -seven isolated controls with zero warnings/errors. The lifecycle reviewer verifies -committed source archive hashes and extracted bytes. The proof reviewer also -interrupts the actual unsafe-callback child and forces the external watchdog; -both paths join the real child and remove the owned temporary tree. A watchdog -failure is not reported as a successful experiment. - -The initial proposal/probes are `f8ff691f`; verified first-round corrections and -exit controls are `2103f059`; the primary status pointers are `878bcd49`. Root -reads both final reports and execution logs, verifies focused final results of -five Release corpus controls and seven ADR parser controls, and repeats the -37-file sweep: 2,711 local links, 646 fragments, zero errors. All 53 previously -Accepted ADRs are byte-identical across this proposal range. No full backend, -production PostgreSQL/worker or multi-pool result is inferred from these checks. - -Proposal review is complete; ADR-0059 remains Proposed pending maintainer -acceptance. This closeout changes only the review receipt, not the reviewed -policy/probes. The user's requirement to approve new ADRs before dependent -implementation remains the gate. Step 4's real qualification and Steps 5–9 are -pending; no worker, maintenance owner or replacement policy is activated here. - - -#### External proposal review and verified revision (2026-10-16) - -The maintainer's response to the approval request is a review, not acceptance. -Root verifies its findings against `b49998d9`, the Accepted records and pinned -Core/provider source, with separate lifecycle, storage-surface and options support -investigations. Those investigators are not the fresh review rounds below. -ADR-0059 remains Proposed and no dependent runtime is authorized by this revision. - -| Finding | Verified disposition | -|---|---| -| B1 outer retry/repeat owner | Valid. Core retries failed announcement before capture and repeats normal server return independently of heartbeat. Add a preallocated owner, lazy complete lifecycle boundary, one-shot announcement and terminal stop fence including removal/acquisition/disposal. | -| B2 concrete seam and surface | Valid. Name the per-pool `JobStorage` / `JobStorageConnection` decorators, lazy acquisition and in-boundary lifecycle disposal. Preserve extended capabilities, actual transactions/fetched jobs and shared inventory; pin the obsolete API/upgrade and real-provider parity gates. | -| B3 StopTimeout and running work | Valid. Fix both stop/shutdown timers to Infinite. Local drain closes fetch/admission without canceling admitted private work; host stop has a separate retained asynchronous cancellation signal. Pre-admission wakeups may requeue. | -| B4 availability and alternatives | Valid tradeoff. Document shared-outage/all-pool drain and whole-pool blocking despite a spare slot or storage recovery. Compare no replacement and bounded two-generation shared budgets honestly; current probes do not disprove qualified overlap. Retain the proposed one-generation choice for approval. | -| B5 delayed/recurring dependency | Valid. Control drain stops native timers. Require independent same-generation bridge repair in Step 4 and missing-tick durable occurrence recovery in Step 8, without inventing a universal latency SLA. | -| B6 fixed options/metadata/margin | Valid. Pin server intervals, four-minute heartbeat cutoff below five-minute expiry, one-second pacing/five-second owner backoff and exact Queues/WorkerCount dictionary values. Step 4 startup validates these constants; they are not silently new public options. | -| B7 replacement classification | Valid. Earlier ADRs selected stock pools/retention, not a convenience constructor or automatic-restart policy. Correct the Proposed ADR/live summary to an additive lifecycle decision; accepted history is untouched. | -| B8 census/catchability | Valid. Name forbidden facade/registration paths and exact production capability scans. Catchability matches the pinned Core exact-type OOM/StackOverflow exclusions; require actual managed fault premises and closed diagnostic callbacks, not arbitrary throwing/blocking observers. | -| B9 upstream issue | Suggestion, not an implementation requirement or authorization to publish. No public issue is filed; a concrete qualified upstream change remains an alternative, not assumed available evidence. | - -The second report's smaller terminology/reference notes are also verified: -distinguish per-server metadata from storage-wide fetched-job heartbeat, separate -component/filter suppression, label the finite pool observation dimension without -mapping readiness, correct cancellation-timer wording and explain the whole-pass -heartbeat wait. Add the Database/Observability/Events and Outbox references. - -Root integrates twelve additional isolated actual-Core controls into the same -owned launcher, alongside the original seven. The current builder/exit controls -use infinite stop timeout; exit cancellation now receives an explicit host signal, -not the pool-local stopping token. All nineteen pass with zero build warnings or -errors. The new controls distinguish: - -- Raw announcement failure and normal-return repetition from stop-fenced variants. -- Announcement acquisition/disposal and removal/acquisition/disposal failures, - including faults held before owner handle publication and without capture. -- An actual caught non-InvalidOperation managed builder fault, with no later start - and earlier actual work/tokens retained; the premise cannot be skipped by stop. -- Infinite versus finite StopTimeout while actual work stays live, followed by - an independent host signal with its real cancellation/relay tasks held and joined. - -The normal-return pair deliberately allows a stock heartbeat restart with no held -old work to isolate outer repetition/removal fencing. It does not qualify supported -heartbeat containment. Fake lifecycle resources and held `IBackgroundProcess` -work prove neither real PostgreSQL/Worker cancellation nor partial mandatory -thread construction, complete provider parity, common-outage/multiple-pool repair -or actual replacement. All remain named production activation gates. The earlier -seven-control review receipts retain their as-of scope; they are not retrospectively -expanded to cover this external revision. - -Root's isolated whitespace/Release verification passes after integration; -all nineteen distinct controls pass, along with five Release corpus cases and -seven ADR parser controls. The first-party history/link sweep is clean. These -checks do not rerun or relabel the earlier full 4,152-case Step 3 evidence. - -#### External revision review round 1 - -Two fresh independent reviewers inspect `b49998d9..1853b48f`: GPT-6 Astra with -xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers -proofs/governance. Both independently pass all nineteen controls with zero -warnings/errors. Lifecycle reports no finding; proofs reports no Blocker/Major -and one Minor historical evidence-count error, verified and corrected below. -The proof reviewer also removes the actual managed exception in an isolated -mutant: the builder control turns red. Missing receipts, startup failure and -silent watchdog expiry are rejected; the actual timed-out child is joined. -Root reads both final reports/logs. These reviews do not certify production gates. - -**Evidence-count correction — 2026-10-16.** The earlier proposal round-2 receipt's -“53 previously Accepted ADRs” is incorrect. Root and the new proof reviewer use -`scripts/adr-status.py`'s canonical `lifecycle()` parser, not a text occurrence -count: both `def48a1a` and `b49998d9` contain 51 currently Accepted canonical ADRs, -all byte-identical at `1853b48f`. The older receipt remains as-of text; this dated -correction replaces its denominator, not the byte-preservation result. It does -not claim the original reviewer ran this corrected count. ADR-0059 is Proposed. - -#### External revision review round 2 and availability correction - -Two new independent reviewers inspect `b49998d9..b4a6fec0`: GPT-6 Astra with -xhigh effort covers lifecycle/authority; GPT-6.1 Sol with xhigh effort covers -proofs/governance. Both independently pass all nineteen controls with zero -warnings/errors and reproduce the canonical 51-ADR count/byte preservation. -The proof reviewer independently rejects missing receipts, startup failure and -watchdog expiry, joins the real child and turns the managed-fault mutant red. - -Both initially report a clean proposal. Root's final cross-check then identifies -an additional governance conflict: ADR-0047's unrelated-tenant progress promises -are broader than ADR-0059's whole-pool drain below four retained overruns. The -lifecycle reviewer independently confirms it and appends one Major, explicitly -narrowing its earlier verdict before acceptance. Root verifies the actual clauses; -their exception cannot be assumed implicit merely because the older contract -already had a four-overrun threshold. - -The correction keeps constructor/restart composition additive, but names a -bounded availability supersession of ADR-0047's Tenant capacity and independent -pools / Lifecycle and observation progress clauses. Same-pool unrelated tenants -may wait during generation-control draining despite a spare slot after storage -recovery and below four overruns. Healthy other pools, hard bounds, reservations -and independent orchestration are preserved. Acceptance will disclose this precise -change in ADR-0047; ADR-0058's ownership note remains additive. Prior Accepted bytes -are untouched. This correction changes classification/explicit contractual scope, -not the already stated single-generation behavior or the nineteen probe sources. - -#### External revision focused verification and approval-readiness closeout - -Two new independent reviewers inspect `b4a6fec0..35b6985d`: GPT-6 Astra with -xhigh effort covers governance and normative scope; GPT-6.1 Sol with xhigh effort -covers corpus/history and evidence mechanics. Both confirm the earlier Major is -resolved without widening the affected-pool exception. The first reviewer flags -one Minor in `71221799`: the four-overrun threshold stops new starts, not actual -retention. Root verifies/fixes it in `35b6985d`; that reviewer preserves its first -report and appends exact-head verification. Both final focused verdicts approve -with no unresolved findings in their stated scope. - -Root reads both final reports and verifies five Release corpus controls, seven -ADR parser controls and the first-party history/link sweep: 37 Markdown files, -2,716 local links, 648 fragments, zero errors. The canonical lifecycle parser -reproduces 51 Accepted ADRs at `def48a1a`, `b49998d9`, `b4a6fec0` and `1853b48f`, -all byte-identical in the final tree. ADR-0059 remains Proposed. The final -classification/wording corrections change only Markdown; the nineteen-control -sources are unchanged since `1853b48f`, so their existing passing receipts are -preserved without claiming a new runtime run. Diff/prose-width checks pass. - -The external revision is `1853b48f`; first-round/count correction receipt is -`b4a6fec0`; bounded availability disclosure is `71221799`; retention precision -is `35b6985d`. The initial clean round-2 verdict and its later Major addendum -remain explicitly recorded above. This final receipt changes no reviewed policy -or probe. It is neither maintainer acceptance nor real production qualification. - -The revised ADR and Step 4 adaptation are ready for maintainer approval under -the user's new-ADR gate. Same-pool blocking during generation-control drain, -including below four overruns after storage recovery, is an explicit decision -for that approval. Step 4's real worker/PostgreSQL, startup/resource, wrapper -parity, multi-pool and exit controls remain mandatory before activation; Steps -5–9 remain pending. Work stays on `development`; no dependent runtime, push, -PR or current-head CI result is implied by this proposal closeout. - -#### Maintainer acceptance and Step 4 adaptation (2026-10-16) - -**Accepted — 2026-10-16, @cemil.** The maintainer explicitly approves revised -[ADR-0059](../decisions/0059-owned-hangfire-server-generations.md) and the Step 4 -adaptation reviewed at `0db27eb6` on `development`. This closes the new-ADR -approval gate and authorizes dependent implementation after the acceptance -commit. It completes no implementation step or production activation proof. -The nineteen-control experiment and earlier review/validation receipts retain -their recorded scope; acceptance neither reruns them nor expands their claims. - -The accepted change has two distinct parts: - -- **Additive lifecycle integration:** public stock process composition, one - actual generation per pool, synchronous context capture, closed storage and - lifecycle disposal fences, classified metadata-heartbeat retry, sole owner - replacement after actual stock/LearnStack cleanup, separate shared component - ownership and a qualified closed process-exit relay. -- **Bounded availability supersession:** only the two ADR-0047 progress clauses - quoted in ADR-0059 are qualified during generation-control drain. Unrelated - tenants in the same pool can remain blocked after storage recovery, with a - spare slot and below four retained overruns, until actual cleanup completes. - Healthy other pools remain independent subject to common dependencies. - Four overruns still stop new starts in an otherwise serviceable generation; - actual retention continues. Hard bounds, fair independent orchestration, - attempts, reservation ownership and positive quiescence remain unchanged. - -[ADR-0047 Amendment 2](../decisions/0047-transactional-background-job-runtime.md#amendment-2--owned-server-lifecycle-and-bounded-availability-supersession-2026-10-16) -discloses both parts. [ADR-0058 Amendment 2](../decisions/0058-bounded-stock-hangfire-maintenance.md#amendment-2--independent-shared-component-ownership-2026-10-16) -is additive component-ownership navigation only. Both preserve the prior -Accepted bodies, acceptance metadata and earlier amendments. No whole-record -supersession or ADR-0041 fact correction is selected. - -**Adapted Step 4:** the original H1 wakeup/bridge/wrapper/pool work remains in -scope, with ADR-0058's component/filter and maintenance obligations. ADR-0059 -adds the public compositor and complete concrete storage/connection surface, -one-shot announcement/removal stop fences, exact fixed options/queue metadata, -local drain without business cancellation, retained actual stock/LearnStack -joins and API-instance shared fetched-job heartbeat/expiration hosting. -The closed diagnostic observer, cancellation relay and process-exit boundary -must be qualified before worker activation; unresolved startup/resource cleanup -refuses activation and reopens the decision, rather than granting replacement. - -Real pinned worker/PostgreSQL controls remain mandatory for full provider-surface -parity and capability census; acquisition/disposal/startup and heartbeat faults; -nonoverlap and no early token/resource disposal; control-pool drain with healthy -pool renewal and due delayed-handoff repair; common outage/recovery with a held -operation and a spare slot still closed; host stop/backoff/late completion; and -direct-callback versus closed-relay process exit. The final simultaneous physical -acquisition census must enforce its qualified supported configuration/floor and -prove progress at that boundary; no guessed numeric floor is accepted. - -Step 8 retains missing-native-tick recurrence/CoalesceLatest qualification. -Steps 5–9 retain business completion/terminal audit, tenant capacity, external -effects, recurrence and final enforcement under their existing approved scope. -The nine-step sequence and two fresh independent review rounds per step remain -authorized. Phase 03 operator recovery and Phase 11 readiness/supervision remain -with those owners. - -**Carrier inventory at acceptance:** - -| Carrier | Acceptance effect / remaining implementation owner | -|---|---| -| [Standards 05](../standards/05-database.md#background-jobs) | Existing canonical schema/grants/source deadlines remain unchanged. Step 4 must qualify every concrete connection/compositor acquisition lane and the supported pool boundary; this acceptance adds no DDL or grant | -| [Standards 10](../standards/10-observability.md#health-checks) | Accepted lifecycle observation reference only. Step 4 supplies truthful drain/heartbeat/shared-component health; Step 9 owns final instruments/censuses. No new emitter or mapped readiness is claimed | -| [Standards 20](../standards/20-infrastructure-stack.md#background-jobs-and-hangfire) | Accepted lifecycle and bounded availability reference; implementation/activation remain pending | -| [Standards 21](../standards/21-architecture-tests-catalogue.md) | ADR-0059 extends the existing bootstrap, independent-capacity and credential-confinement obligations by reference; all three remain Registered. Step 4 supplies real subjects/controls; Step 9 closes enforcement. No rule, method or Implemented count changes | -| [Events and Outbox architecture](../architecture/15-event-and-outbox.md#background-job-transport-and-maintenance) | Accepted server/component ownership and availability reference; delivered Steps 1–3 and pending Steps 4–9 remain distinct | - -This documentation-only acceptance precedes dependent runtime changes. It -claims no new worker, maintenance owner, production qualification, full backend -rerun, CI result or packet closeout. Earlier pending-approval wording is dated -history; current implementation and activation remain pending. - -#### Step 4 required-startup qualification (2026-10-16) - -ADR-0059 acceptance commits at `6c52eaa1` before dependent work. Root verifies -two independent source/design inspections (GPT-6-astra xhigh and GPT-6.1-sol -xhigh) against pinned Core and official .NET 10.0.10 source. Normal lifecycle -containment is implementable, but the literal required-startup join-before-dispose -obligation remains unqualified through the current public seams. - -Core starts metadata heartbeat and prepends private watchdog/cancellation builders -before supplied capture. If required construction throws, it skips the child join -and disposes prior controls before removal reaches the storage fence. Keeping that -uncaptured generation retained prevents replacement, but cannot undo disposal. -.NET distinguishes exact native-create OOM from a later initialization wrapper; -Core's exact exception predicate does not itself exclude ThreadStartException. -The identified Unix path concerns stack/TLS/runtime resource initialization. -No genuine Linux resource-failure experiment, ordinary SQL/configuration -counterexample or frequency estimate is claimed. A hostile global logger or -invalid input is not a supported-production counterexample. - -[ADR-0060](../decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md) proposes the narrow -fatal-process alternative: after prevalidation, unowned constructor/required -startup failure closes starts/replacement and terminates the entire API without -a graceful-cleanup claim. This interrupts unrelated pools/HTTP traffic; durable -attempts, external uncertainty and reservations remain authoritative. Normal -announcement/database faults, captured builders, local drain and host stop retain -ADR-0059's policy. The proposal neither accepts itself nor authorizes termination -runtime. It applies ADR-0059's existing decision-reopening gate. - -Independent bridge, closed diagnostics, selective component/filter inventory and -storage/parity work continue under the Accepted contracts. They do not qualify -the complete server owner or activate workers. New proposal review receipts and -actual implementation/test results will be recorded after they occur; no new -passing production test, full Step 4 completion or current-head CI is implied. - -##### Required-startup proposal review round 1 - -Two fresh independent reviewers inspect `6c52eaa1..34be14e6`: GPT-6-astra xhigh -covers policy/lifecycle and GPT-6.1-sol xhigh covers proofs/governance. Both -approve the Proposed documentation for maintainer consideration with no -Blocker/Major, independently identifying one Minor: the consequence's “rare” -frequency qualifier is unsupported. Root verifies/removes it, preserving the -explicit absence of a genuine resource-failure experiment or likelihood estimate. -The source-based state trigger, entire-host consequence, bounded supersession -and pending implementation/proof gates remain unchanged. - -Root reads both final reports. Seven ADR parser controls, the six-file link/ -fragment sweep and diff/prose checks pass; all 52 baseline Accepted ADRs remain -byte-identical. These are proposal checks, excluding the uncommitted independent -bridge/wrapper/diagnostic slice. A new second review round follows this correction; -ADR-0060 remains Proposed and no fatal-process runtime is authorized. - -##### Required-startup proposal review round 2 - -Two new independent reviewers inspect `6c52eaa1..ac5a1cd3`: GPT-6-astra xhigh -covers policy/lifecycle and GPT-6.1-sol xhigh covers proofs/governance. Both -approve the Proposed documentation for maintainer consideration with zero -Blocker/Major/Minor/Suggestion findings. Root reads both complete final reports. -The proof review independently checks all 52 baseline Accepted ADRs byte-for-byte, -ADR-0059 Accepted/ADR-0060 Proposed, 706 local links and 295 fragments with no -missing targets, unchanged catalogue bytes/counts, added prose/private-reference -checks and clean diff whitespace. Neither review runs shared builds, database -experiments or production qualification; no genuine Linux resource-failure or -frequency claim is introduced. - -The proposal is ready for maintainer consideration. Its entire-API interruption, -operator restart and absence of graceful cleanup remain explicit costs; fatal -runtime and activation still require acceptance. Independent Step 4 foundation -validation proceeds under the existing Accepted decisions and is recorded -separately. Steps 4–9 remain incomplete; no push, PR or current-head CI is claimed. - -##### Independent Step 4 foundation slice (2026-10-16) - -This slice implements the already-authorized H1 transport and public storage -boundary while ADR-0060 remains Proposed. It does not implement fatal termination, -compose Core generations, host shared maintenance or activate API workers. -Full Step 4 and Steps 5–9 remain pending under their accepted ownership. - -- The bridge claims committed intent in a short privileged transaction, retains - at most four actual synchronous stock-client calls on background threads and - suppresses ambient execution context/culture. Vendor IDs remain hints; absent, - failed or succeeded vendor rows permit same-generation repair without spending - business attempts. ACK/deferral locks the actual row before rechecking current - database-time lease/token/generation fences; callback admission may precede ACK. - Host stop closes acquisition and retains actual calls through late completion. -- Exact opaque wrappers and a five-token resolver reject arbitrary CLR lookup. - The closed activator binds a registered pool, invocation and single-use scope; - it reaches Step 3's framework admission only. Business completion stays Step 5; - recurrence materialization stays Step 8 and cannot currently report success. -- Concrete pool storage/connection wrappers preserve the complete pinned public - surface, provider features, extended casts, transactions, fetched jobs and locks. - Only announcement, metadata heartbeat and removal enter the closed lifecycle - operation. Failed disposal remains retained; this is no proof of the pending - complete generation owner or every physical provider cleanup outcome. -- Fail-closed component/filter inventories retain exact stock instances and required - filters while suppressing the counter aggregator/history. Vendor diagnostics use - fixed memory-only counters without evaluating messages or invoking observers. - Existing capability, authority, transaction and parallelism censuses enumerate - the new exact callers and retain their planted extra/missing-site controls. - -Real delayed creation exposed a predicate mismatch: stock explicit-queue scheduling -stores `queue:id` in the `schedule` set, while the prior guard admitted only numeric -IDs. The fix preserves immutable queue binding, restricts the added form to that -key and bounded queue/ID grammar, and reconciles the canonical SQL. An additive -Platform migration supports already-installed stores; reverse/reapply, malformed -and wrong-key controls exercise the boundary. Fixture corrections preserve the -actual ACK-after-lock-expiry and below-filter redaction assertions, and replace the -old missing-wrapper assumption with a positive load of the now-present wrapper. -Earlier recorded Step 2/3 evidence is unchanged. - -**Initial slice validation:** Release warning-as-error build passes with zero -warnings/errors. Unit 2,056, Architecture 315, Contract 4, Docker-free HTTP -integration 176 and focused real-PostgreSQL bridge/parity/storage/rollback 94 -pass: 2,645 tests, zero failures/skips. TRX counters are checked directly and by -the guarded test receipt. Seven ADR parser controls and a three-file sweep of -533 local links / 193 fragments pass. C# formatting and diff whitespace pass. -This is a focused slice receipt, not a full backend/renderer/demo/CI rerun. - -The first runs found the queued-schedule guard mismatch, a completed-locker -rollback in the proof, an inadmissible RetryCount test value and the old absent -wrapper assumption. The corrected PostgreSQL set passes in full. Initial -architecture failures identify only newly sanctioned caller inventories; exact -entries and forwarding/removal mutants now pass the full architecture assembly. -No failing check is skipped or broadened to allow arbitrary callers. - -Two fresh independent slice-review rounds follow the initial implementation -commit. They do not close full Step 4's real generation, maintenance, -cancellation/exit, multi-pool progress or connection-floor gates. - -##### Independent foundation review corrections (2026-10-16) - -The initial foundation review was interrupted before final reports; it is not -counted as a completed round. A resumed independent GPT-6-astra xhigh R1 inspects -the complete committed slice and surrounding runtime/census paths. It verifies -one Major: raw filter concatenation bypasses stock precedence and lets the global -retry execute before the wrapper's zero-retry attribute. The separately identified -bridge-source forwarding gap also needs exact capability enforcement. - -Commit `9db4822d` uses the stock filter-provider collection, preserves the admitted -global instances and pins the bridge store's signatures, source captures, -acquisitions, consumers and holders. Actual StateMachine controls distinguish -failed-state retention from the raw-concatenation retry/schedule outcome. Two -fresh independent R2 reviewers (GPT-6-astra xhigh runtime and GPT-6.1-sol xhigh -proof/security) inspect the corrections. The proof reviewer finds one further -Major: a pre-creation global retry registered at order 100 wins stock precedence. -Root verifies it and refuses nonstock retry registration order before changing -history; both wrappers now have effective-filter and actual state-election controls. -Both reviewers independently verify the final fix with zero remaining findings. - -Before the last two-line registration guard, Release build, Unit 2,058, -Architecture 317 and focused real-PostgreSQL 93 pass, with zero failures/skips. -After that guard and its added controls, Release build remains warning/error-free, -all 2,061 unit cases and four targeted credential/catalogue architecture cases -pass. Direct TRX counters and the guarded runner confirm execution and zero skips. -Pre-commit formatting leaves all four reviewed C# hashes unchanged. This is not a -new full backend/renderer/demo/CI receipt; no fatal runtime or worker is activated. -Full Step 4's complete-runtime review and qualification gates remain open. - -##### ADR-0060 external-review revision (2026-10-16) - -The maintainer requests changes to the Proposed record. The earlier two clean -proposal-review receipts remain historical; they do not close these later verified -gaps or authorize fatal runtime. Root rechecks pinned Core and official .NET source, -reads two independent state/policy analyses and revises the proposal before seeking -new approval. No genuine Linux resource failure, new runtime experiment or incidence -estimate is claimed. - -The revised file is -[ADR-0060: Fatal Hangfire Startup and Unsafe Unwind](../decisions/0060-fatal-hangfire-startup-and-unsafe-unwind.md). -Renaming the Proposed file reflects its explicit before/after-capture scope; earlier -record links resolve forward to that current proposal. All Accepted ADR bodies, -metadata and prior amendments remain unchanged. - -| Verified review gap | Revision / deliberate boundary | -|---|---| -| M1: fatal rationale relied on the old cleanup promise | Quarantine remains a viable policy alternative. Fatal is a conservative integrity/visible-failure preference with the whole-API cost, not technical necessity or proof that private controls execute business work | -| M2: Phase 11 ownership was absent from its roadmap | Reliability scope, deliverables and completion now explicitly own supervision/restart/backoff/crash-loop, termination/dump policies and the triggered worker-process topology decision; no present supervisor is claimed | -| M3: constructor predicate exceeded proved live-thread cases | Entire prevalidated constructor failure is explicitly conservative, including pre-thread false positives; no private instruction boundary is inferred from exception type/text | -| M4: capture did not cover Core post-builder/notification unwind | Separate progress and conditional normal-join facts; owned disposal, removal, second-announcement and outer-completion observations cover skipped waiting/removal. Closed logger/timer/final-exit premises must be qualified before activation | - -The revision also names process-wide starts/ExecuteIntent gates and earlier-admission -uncertainty, host-stop versus final-teardown priority, retained unhealthy stalled -startup under the existing ProgressTimeout, finite pool/stage diagnostics, runtime/ -Linux resource/collector dump prerequisites and orphan process-tree consequences. -Exact ADR-0059 qualification/availability clauses and its Option 4 are disclosed; -three existing canonical test obligations receive explicit prospective assignments. -No new rule/count/status or caller enforcement is declared implemented. - -The suggested automatic exact-OOM crash outcome is not established and is not used -as a policy argument. Existing API blast-radius, manual-restart, dump-risk and durable -reservation disclosures were already present; their concrete controls/owners are -strengthened rather than presented as newly discovered guarantees. Synthetic fault -placement remains distinct from real stock and genuine resource evidence. Proposed -and Accepted policies are not silently conflated. - -The independent foundation corrections above own their source capability and -filter proof/review receipt. Neither workstream completes Step 4 or permits -fatal activation. The following records own the proposal's fresh reviews. - -**Revision review round 1:** two fresh independent reviewers (GPT-6-astra xhigh -lifecycle and GPT-6.1-sol xhigh governance/proofs) inspect the frozen eight-document -revision against `422519b0`. Both request changes for one Major and one Minor. -Root reads both full reports, verifies ADR-0047's preserved other-pool progress -clauses/Amendment 2 and adds its prospective dated bounded disclosure alongside -ADR-0059. The second-announcement fatal predicate now requires missing normal -child-join evidence, preserving nonfatal post-join cleanup. Known pre-child refusal -precedence and complete-boundary announcement confirmation are explicit. - -Both independently confirm the state-model, conservative/quarantine tradeoff, -Phase 11 owners, dump/collector prerequisites and pending proof limits. Static -checks preserve all 52 Accepted ADRs; the governance review independently checks -1,290 local targets / 394 applicable fragments with no errors. Root's parser and -whitespace checks pass. No reviewer runs shared tests or resource experiments. -The independent bridge fix adds two architecture methods (222 → 224), without any -rule/status/Implemented-count promotion; its execution receipt is separate. -A fresh second revision review follows these corrections; approval remains pending. - -**Revision review round 2:** fresh independent GPT-6-astra xhigh lifecycle and -GPT-6.1-sol xhigh governance/proof reviewers approve the corrected eight-document -proposal with zero findings. Both recheck the frozen hashes and all 52 unchanged -Accepted ADR files; the governance reviewer verifies the four exact authority -quotes, unique Registered proof names and unchanged Implemented-rule count. -Root reads both full reports and reruns seven ADR parser controls, the changed-doc -sweep (1,291 local links / 395 fragments, zero errors) and whitespace checks. -No reviewer executes a resource, fatal-child, worker or PostgreSQL experiment. -These are proposal-review receipts, not maintainer acceptance or runtime proof. -The revised ADR-0060 remains Proposed; dependent fatal implementation still waits -for approval, and real lifecycle qualification precedes activation. - - -##### ADR-0060 acceptance and Step 4 continuation (2026-10-16) - -The maintainer approves the revised ADR-0060 at `189f3bcf` and explicitly requests -implementation. Acceptance precedes dependent runtime commits on `development`. -It selects the conservative opaque-construction/unsafe-unwind fatal policy after -comparing viable quarantine, including before-thread false positives and the -whole-API/healthy-pool availability cost. Stalled startup remains retained unhealthy -ownership, not timeout-based fatal selection. No exit releases durable uncertainty -or reservations; earlier-admission effects remain authoritative. - -The acceptance carrier commit adds dated bounded supersession amendments to -ADR-0047 and ADR-0059, keeps their bodies/metadata intact, moves ADR-0060 into the -Active index and reconciles current front doors, Standards 20/21, architecture 15 -and Phase 11's explicit operations ownership. Three existing canonical proof -assertions are extended without changing Registered status or published counts. -ADR-0058's ordinary maintenance contract remains unchanged. - -Step 4 resumes the actual generation owner, shared components, host/exit gates, -closed fatal capability and real pinned worker/PostgreSQL qualification. It still -must complete its implementation commit, two fresh independent full-step review -rounds and verified fix commits before Step 5. Fatal child prerequisites must be -qualified before launch; unsupported dump/collector settings fail, never skip. -No acceptance receipt claims runtime delivery, production readiness or activation. - -Focused independent acceptance audit passes after fixing the Active-table row and -derivation-header navigation. All 52 prior Accepted ADRs preserve their bodies; -the two named amendments add only new lines. Seven ADR parser controls, five -corpus architecture cases and a 1,543-local-link / 468-fragment sweep pass, with -zero failures/skips or broken targets. Published catalogue counts/statuses remain -unchanged. The acceptance commit contains documentation only. - -##### Owned generation and maintenance foundation (2026-10-16) - -**Implementation slice; Step 4 remains in progress.** ADR-0060 acceptance at -`e0d39bf5` precedes this dependent runtime. `HangfireGeneration` retains actual -construction, stop, startup observation and uncanceled Core completion separately -from caller waiting. A synchronous context capture and Core-facing wait-entry -marker distinguish progress from the qualified normal child-join witness. -Successful removal/disposal is also required before cleanup is acknowledged; -joined but unresolved cleanup stays retained. A stop that wins before Start has -its own positive no-Core completion path. - -The shared component owner retains the two frozen stock components independently -of pool drain. Native startup, invocation, actual join and cancellation callbacks -have distinct owners. Each lane observes its five-minute wait plus one-second -cleanup bound without releasing resources or starting another pass early. -Expiration keeps its one-hour cadence; fetched-job heartbeat keeps stock pacing. - -One closed process gate arbitrates host stop, final teardown and the sole -preallocated pool/stage fatal sink. Its final-exit callback registers before Core. -The gated native connection factory permits normal stock cleanup during host drain -and refuses fatal/final-teardown issuance. Bound activators/wakeups recheck the -same generation at activation, routing and app admission. The framework scope -retains that closed memory predicate and rechecks it after actual row-lock waits, -before spending an attempt. No module-supplied context or transaction owner changes. - -Focused source feedback fixes pre-lifecycle expiration drift, stop-before-start, -missing removal/disposal evidence and owner clock/timer failures. Ordinary provider -failures remain contained through the real stop/child-join fence. Two new structural -facts pin the actual fatal capability/sink and public Core constructor, with -direct/delegate/async/overload/interface/forwarding dirty controls. The catalogue -method total becomes 226; all 19 P4 obligations remain Registered and the -Implemented-rule count remains 202. Per-detector body snapshots are rebuilt after -every mutation; no process-wide mutation cache hides added or removed subjects. - -Validation currently records a zero-warning/error solution build, 2,083 Unit cases -and 133 focused PostgreSQL/process cases, with zero failures/skips. The latter -include ten real generation controls, app-role admission closure during a real row -lock, real stock parity/bridge/admission regressions, six Linux scenarios and -one in-memory receipt-predicate control. -The full Architecture run and final per-detector optimization rerun each pass -319 cases, with zero failures/skips. - -The Linux sidecar runs the real production sink only in an isolated .NET 10.0.10 -Arm64 child. A benign twin proves cleanup sentinels; fatal exit 134 omits them. -The shell verifies soft/hard core limits zero and the nonpiped `core` collector -before managed entry. Child environment is cleared, modern/legacy dumps disabled, -root/input binaries read-only, scratch isolated and network disabled. The initial -archive-copy setup refuses the read-only root; a read-only mount of staged proof -binaries fixes setup without changing dump/collector policy. Actual native and -supervisor exits, fixed diagnostics and artifact allowlists pass. These are direct -gate/synthetic-stage controls, not genuine Core resource-failure reproduction or -generation phase-dominance proof. - -The production API does not construct or activate these owners yet. Full pool -replacement/retained LearnStack work, independent bridge/control composition, -supported physical-acquisition boundary and remaining lifecycle/fault/exit proofs -remain in Step 4. Its complete implementation commit and two fresh full-step -review rounds still precede Step 5. This slice claims no new business execution, -recurrence, readiness mapping, production recovery, CI success or packet closeout. - -##### Foundation review round 1 and verified corrections (2026-10-16) - -Two fresh independent reviewers inspect `e0d39bf5..e1e6db42`: GPT-6 Astra with -xhigh effort covers runtime authority/lifecycle; GPT-6.1 Sol with xhigh effort -covers proofs/corpus. Both use standards-check then code-review lenses. These -are focused foundation reviews, not the still-required full Step 4 rounds. - -Root verifies one Major finding against the pinned provider source: fetched-job -renewal catches acquisition/SQL failures internally and returns normally. The -shared owner could incorrectly report that returned pass healthy. The correction -binds the closed diagnostics instance, preserves swallowed faults/ownership loss -through empty passes, and requires a clean pass containing actual renewal SQL -before clearing known storage failure. Return/join and storage health are distinct. -No provider message factory is evaluated and stock code/SQL remain unchanged. - -The real disposable-PostgreSQL regression fetches a stock wakeup, revokes only its -renewal-column permission and proves unchanged fetched-at, recorded fault and an -unhealthy returned/joined pass. Restoring permission must produce actual fetched-at -progress and healthy recovery with historical faults preserved. Fixture-only -cadence acceleration is explicit; the stock one-second pass pacing is unchanged. -Ten shared-owner unit cases and eleven generation PostgreSQL cases pass with zero -failures/skips. The combined bridge/generation regression passes 33 cases. -The initial new fixture does not compile against the provider's internal Options -property; narrow test-only reflection corrects cadence access. A ten-case run of -the previous integration binary is excluded from the new regression evidence. - -The proof reviewer reports no Blocker/Major/Minor. Both verified suggestions are -applied: the constructor-shape assertion includes public and nonpublic members; -the foundation receipt distinguishes six Linux scenarios from its one in-memory -predicate control. Complete Step 4 qualification/activation remains pending. - -##### Foundation review round 2 (2026-10-16) - -Two new independent reviewers inspect `e0d39bf5..28433f29`: GPT-6 Astra with -xhigh effort covers runtime and GPT-6.1 Sol with xhigh effort covers evidence/corpus. -Both approve the scoped foundation with no Blocker/Major/Minor. They independently -verify the swallowed-renewal mechanism, sticky health, positive storage recovery, -constructor census and six-Linux/one-memory proof boundary. They do not rerun the -toolchain or substitute their source review for the recorded execution receipts. - -Root verifies/applies the one nonblocking suggestion: README now distinguishes -in-progress implementation from pending full qualification/activation and points -its current-phase link to Phase 02b. Both focused foundation review rounds are -complete; the remaining Step 4 integration and fresh full-step rounds stay open. - -##### Pool replacement and framework cleanup ownership (2026-10-16) - -**Further implementation slice; Step 4 remains in progress.** One closed -`HangfirePoolOwner` retains each actual generation and its supervision task. -Replacement requires positive generation cleanup, the fixed five-second backoff -and live owner/process gates. A startup-stalled generation stays closed even -after its late cleanup joins; stop-before-start has a positive no-issued-work path. - -Generation-local work owns private cancellation sources and the actual routing -and admission tasks. Local drain closes starts without canceling that work; -host stop requests asynchronous cancellation independently of Core tokens. -Cancellation callbacks and failed cleanup remain owned after wrapper return. -Four retained entries close further starts, with workers-plus-four as the hard -ownership bound. Real stock joins do not substitute for private-work completion. - -Routing publishes its opaque claim only after acknowledged COMMIT and actual -resource cleanup. Failed cleanup retains the concrete reader, command, -transaction and connection. Framework admission likewise carries concrete failed -scope/unit/activity/authority/source owners in its result: a completed async task -may clear its state-machine locals. This correction preserves the actual failed -DI scope and unit rather than relying on the completed task alone. - -Bridge operations bind ownership before scheduling native startup and recheck the -process/local gates at actual creation and SQL acquisition. Startup return, native -end, observer return and positive cleanup have separate witnesses. Unknown startup -or observer cleanup cannot be pruned as completed; ordinary host stop preserves -durable late-handoff repair without a new local ACK acquisition. - -Validation passes a zero-warning/error solution build, 2,109 Unit cases, 74 focused -PostgreSQL cases and the full 319-case Architecture suite, all with zero skips. -The PostgreSQL set includes six real pool-owner cases, seven routing-cleanup cases -and five added generation-work cases. Those cover actual routing/DI cleanup held -past stock joins, real native admission/cancellation, delayed callbacks and exact -failed-scope retention. Four retained entries in the threshold proof are explicitly -synthetic framework occupancy; native refusal/restored admission are real. The -throwing-disposable proof repairs only its synthetic fixture during teardown and -does not introduce a production recovery API. - -Initial architecture runs expose the moved routing transaction's stale exact -caller inventories and the wrapper's declared sequential-task ownership exception. -Updating those precise owners preserves the privileged-entry checks and planted -controls; the fresh full rerun passes. A filter selecting no tests is excluded -from evidence. Earlier failed runs are not added to passing counts. - -API facade/source-lifetime integration, supported physical capacity and full Core -phase qualification remain pending. The new Core-phase fixture's first actual run -fails during isolated PostgreSQL setup, before arming any fault; its receipt -predicate passes. This is setup feedback, not fatal-policy qualification. Neither -this slice nor its tests activate workers or close full Step 4's review gates. - -##### Pool-cleanup slice review round 1 (2026-10-16) - -Two fresh independent reviewers inspect `28433f29..d9fda174`: GPT-6 Astra with -xhigh effort covers runtime authority/lifecycle; GPT-6.1 Sol with xhigh effort -covers evidence/corpus. Both approve the exact slice with no confirmed -Blocker/Major/Minor. Their source reviews do not rerun the toolchain or close the -remaining full Step 4 gates. - -Both reviewers identify the pre-existing ACK/deferral cleanup-fault qualification -boundary as remaining full Step 4 work: a returned store exception alone does not -prove positive connection cleanup. The ongoing source-lifetime integration owns -that correction and its decisive controls. Their report artifact writes succeed; -final readback is initially blocked while an unrelated local process burst -prevents new shell processes. The subsequent continuation receives both complete -reports and verifies their artifacts. No unavailable check is counted as passing. - -The implementation commit's normal hook initially conflicts only on formatting -of two newly added tests while restoring its own WIP stash. Root compares both -versions, verifies equal nonwhitespace content, keeps the formatter output and -verifies all three tracked/five untracked pending proof files byte-for-byte. -The second normal hook succeeds; only the verified recovered hook backup is -removed, preserving the three pre-existing stashes. - -##### Pool-cleanup slice review round 2 (2026-10-16) - -Two new independent reviewers inspect the same exact committed -`28433f29..d9fda174` range: GPT-6 Astra/xhigh covers runtime and -GPT-6.1 Sol/xhigh covers tests, structural enforcement and corpus. Both approve -with no confirmed Blocker/Major/Minor or required correction. The evidence -reviewer independently reads the supplied build log and TRX records, confirming -the recorded 2,109 Unit, 74 focused PostgreSQL and 319 Architecture cases with -zero skips; this is receipt inspection, not another execution. - -Both review rounds are complete for this slice. They do not close full Step 4, -review the subsequent working tree or establish worker activation. The baseline -bridge ACK/deferral cleanup ambiguity remains assigned to source-lifetime -integration rather than relabeled as a new slice regression. - -##### Source-lifetime and facade continuation (2026-10-16) - -An unrelated local test experiment exhausts the workstation's process limit and -blocks shell/test startup. With explicit maintainer authorization, only that -experiment's matching process path is terminated. The next process inventory -contains 659 processes and no matching experiment process; commands resume. -This environment repair is not product or CI evidence. - -The working implementation adds concrete connection-cleanup seals to the three -privileged dispatch/bridge stores, a one-shot shared-source lifetime pin, -positive messaging startup/actual-loop witnesses and the API runtime facade. -The corrected source builds with zero warnings/errors; its then-current Unit -assembly passes 2,161 cases with zero skips. Synthetic driver-state and cleanup -controls prove retained ownership, not production failure incidence. - -The isolated Core-phase fixture progresses through PostgreSQL preparation and -container qualification but still refuses its sanitized-output prerequisite. -Those failed runs arm no accepted fatal-policy proof and are not counted as -passing qualification. Full Core phase/mutation/native-exit evidence, composed -source lifetime, supported capacity and full Step 4 reviews remain in progress. - -##### Core-phase and direct-facade qualification (2026-10-16) - -The corrected isolated fixture passes 23 cases: seventeen unchanged-vendor Core -phase/native-exit scenarios, five actual child-only IL mutations and one separately -labelled receipt-predicate control. The mutations remove the production sink or -one exact constructor/capture-disposal/second-announcement/outer-completion -observer. The same normal predicate rejects each modified child's actual result; -a later fallback fatal call cannot conceal an observer that already returned. -These are synthetic fault placements in real pinned Core, not genuine native -thread/resource-exhaustion reproductions. - -The fixture retains strict empty-stderr, native/supervisor exit, artifact, dump, -runtime and original-vendor-binary checks. Its earlier output refusal is optional -GSS library discovery in the minimal Linux image; the password-only fixture now -explicitly disables GSS encryption. Production connection settings are unchanged. -PostgreSQL preparation has one ephemeral loopback binding, preserved and checked -after bridge detachment; the fatal child has only the inspected internal network. -No claim that the PostgreSQL setup port is unpublished is made. - -Six real-PostgreSQL facade cases pass. Actual default and maximum manifests use -the same guarded pooled settings and live stock worker/queue metadata: 45 and -151 connections respectively. A native framework invocation's held DI cleanup -keeps source disposal pending beyond the caller's stop deadline; releasing actual -cleanup permits Core removal, positive runtime completion and source closure. -Another case holds stock expiration's actual checkout with a competing database -lock while independent transactional admission succeeds at the supported default -floor. These cases do not assert simultaneous saturation of all reserved lanes. -Their two completed messaging tasks are explicit no-issued-work facts; the real -three-owner API composition requires its separate qualification. - -The current Release solution build passes with zero warnings/errors and all -2,165 Unit cases pass, zero failures/skips. Full Architecture validation and the -composed messaging-source proof remain in progress. These receipts overlap earlier -focused runs and are not summed into a packet total. Full Step 4 implementation, -fresh full-step review rounds and later Steps 5–9 remain open. - -Two additional composed PostgreSQL cases now pass with the actual API-hosted -jobs, outbox and delivery singletons and their exact bound completion tasks. -Each real terminal transaction and one matching MUST SecurityEvent audit commit -before a test-owned async disposable holds that terminal audit scope's cleanup. -The actual connection remains checked out and actual worker completion remains -pending through finite stop waiting and container disposal. Guarded acquisition -still succeeds; releasing the synthetic cleanup hold lets all three actual owners -join and the same source observer close the pool. Independent app-role reads -confirm unchanged terminal/audit durability, then no vendor server or tagged -backend remains. The synthetic disposable is not a driver-cleanup-fault claim. - -The first composed fixture run fails genuine DI validation because its custom host -omits tenancy edge registration. The corrected fixture uses the real edge and -literal development configuration; validation stays enabled. A discarded network -hold design is replaced before acceptance because bounded driver cancellation -would make its pending checkpoints depend on a narrow scheduling window. - -The full Architecture run exposes a detached Cecil target in a planted -missing-subject control; local guards now record the missing declaration/scope -instead of throwing. The already-failed unoptimized rerun is canceled and excluded -from qualification. A per-detector scan reuses type/call-site indexes only within -one synchronous evaluation; mutation and undo occur between disposed scans. -The existing companion verifies fresh async-subject addition/removal and cache -release. Its performance and the corrected full suite still await execution. - -##### Complete Step 4 implementation validation (2026-10-16) - -The current implementation passes a fresh CI-mode Release solution build with -zero warnings/errors and all **4,403 backend cases**: 2,165 Unit, 321 Architecture, -4 Contract and 1,913 Integration (176 HTTP and 1,737 Docker/PostgreSQL cases). -The runner guard confirms every assembly executes and no case is skipped. The -Docker run takes 9 minutes 55 seconds; Architecture takes 13 minutes 23 seconds. -The latter confirms the corrected detectors and mutation-scope cache pass, not -a measured speedup against the canceled failed run. - -The complete Integration run includes the Core-phase/mutation, direct-facade and -three-owner lifetime cases described above. Their focused receipts overlap this -run and are not added to the total. Seven ADR parser controls, 1,603 local links, -466 fragments, added prose wrapping and whitespace checks pass. No frontend/demo -rerun or current-head CI is claimed; full packet regression remains Step 9. - -This implementation is ready for the two fresh full Step 4 review rounds over -the changes after Step 3 closeout `def48a1a`. The earlier slice reviews remain -scoped receipts. Step 4 is not closed until both full rounds and their verified -corrections complete; Steps 5–9 remain pending. - -##### Full Step 4 review round 1 (2026-10-16) - -Three fresh reviewers inspect `def48a1a..a1832c6e`: GPT-6 Astra/xhigh covers -runtime/lifecycle; GPT-6.1 Sol/xhigh covers evidence/censuses; a second -GPT-6.1 Sol/xhigh covers security/composition/corpus. They inspect the passing -receipts without rerunning the toolchain. Four unique Major findings are verified -against current source; the security review independently confirms the same -metadata-heartbeat finding rather than adding another issue. - -- A held routing/framework cleanup has no finite wrapper-wait transition to - retained/unhealthy ownership. The correction reuses the existing short-work - wait bound and preserves actual work/callback/source ownership after return. -- The facade drops the running generation's metadata-heartbeat fault during its - retry window. Aggregate health must preserve that fault before drain and reset - only after actual stored recovery. -- Shared expiration/fetched-job component state/outcome and ownership facts do - not reach the registered health result. Fixed memory-only dimensions restore - those distinct observations without mapping readiness. -- The production final-exit child holds actual Core control work but no actual - private cancellation callback. The isolated prototype remains decision support; - a combined shipped-relay positive and direct-Core-callback dirty control are - required in the qualified production child. - -Corrections and their regression qualification are in progress. The optional -scan-cost suggestion scopes repeated type/call/body inventories to one detector -evaluation, preserving fresh mutations/restoration and measuring the full suite -before any performance claim. No Accepted decision changes. Step 9 retains the -existing Standards 10/11 carrier sweep for legacy vendor-payload wording and the -retired `Hangfire_Job_Payloads_Include_TenantId` spelling. No later step or full -Step 4 review gate is closed by this record. - -The first correction run passes 33 of 35 focused PostgreSQL/Core-phase cases, -including both real native framework expiry cases and all 24 Core-phase controls. -Its two health failures are investigated rather than relabeled as qualification. -One fixture fetches through a second provider whose renewal inventory is separate; -the corrected control uses the facade's actual provider and a fixed fixture-only -orphan queue with no native consumer. The metadata control also exposes PostgreSQL -`query_canceled` (57014), which the pinned driver's generic transient list omits. -The exact code now follows the already accepted timeout-retry policy; no other -classification or retry bound changes. Both corrected health cases pass in a -fresh 14-second run. Complete correction-head regression remains pending. - -##### Full Step 4 round-1 correction validation (2026-10-16) - -Root verifies all four findings against the current implementation and completes -their corrections. The finite framework wait owns its actual operation before -scheduling; expiry closes later admission and records retained ownership before -returning the native slot. Real native controls cover held asynchronous cleanup -and held synchronous framework execution, independent healthy admission below the -retained threshold, and positive source/generation cleanup after release. - -Real PostgreSQL controls verify metadata-heartbeat timeout/recovery through the -registered health result, distinct failed fetched-job renewal/recovery, and held -expiration ownership. The production exit child now retains its actual private -callback through finite host waiting and native zero exit. Its separate unsafe -direct-Core-callback control requires supervised timeout, owned kill and actual -join; those facts are explicitly refused by the normal-exit predicate. These are -synthetic callback/fault controls over the shipped owners, not native resource -failure incidence or a claim of cleanup at process exit. - -The corrected Release solution build passes with CI warnings-as-errors and zero -warnings/errors. Fresh complete suites pass 2,166 unit, 321 architecture, four -contract, 176 Docker-free integration and 1,741 Docker/PostgreSQL integration -cases: 4,408 backend cases, zero failures/skips. The Docker suite takes 10m10s; -the architecture suite takes 12m26s. The latter is a measured run duration, not a -controlled speedup claim. Scoped inventory caching preserves mutation/undo and -exception freshness controls without adding a global cache or a new rule. - -All 22 changed C# files are formatted. Seven ADR parser controls, 1,917 local -links, 557 fragments, changed prose wrapping and whitespace checks pass. Earlier -failed focused runs are excluded from the passing complete-suite total; focused -controls overlap it and are not added again. No frontend/demo/current-head CI is -claimed here; Step 9 owns packet-wide reruns. Round 1's verified corrections are -qualified; a fresh full Step 4 round 2 follows their commit. Step 4 remains open -until that round and any verified corrections complete. Steps 5–9 remain pending. - -##### Full Step 4 review round 2 (2026-10-16) - -Round-1 corrections are committed as `53ec8a4a`; normal Leakwatch/format hooks pass -without changing the 22 validated C# source hashes. Three new independent -reviewers inspect the complete `def48a1a..53ec8a4a` range (123 files): GPT-6 -Astra/xhigh for runtime/lifecycle and two GPT-6.1 Sol/xhigh reviewers for -evidence/censuses and security/composition/corpus. They inspect the 4,408-case -passing receipts without rerunning them and affirm all four first-round fixes. - -One unique Major qualification gap remains: ADR-0059 explicitly requires sustained -metadata-heartbeat cutoff/reset and common database outage/recovery with an actual -held old operation, a spare slot and fewer than four retained entries. Current -controls prove real transient SQL recovery and separately requested drains, but -do not compose that mandatory matrix. The runtime reviewer independently confirms -the same gap; neither review alleges a demonstrated production-code failure. -Root verifies the accepted obligation and missing coverage. Isolated PostgreSQL -outage and owner-clock controls are being added before Step 4 closes; their native -Core/SQL observations and logical clock advances remain separately labeled. - -The security/corpus review also verifies one Minor status mismatch: Standards 05 -and Events/Outbox architecture still describe both full reviews as pending. Their -live summaries now delegate review dispositions to this owning record, preserving -earlier dated receipts. No new ADR, runtime policy, grant or business definition -is introduced by these corrections. New qualification and correction review remain -pending; Steps 5–9 do not start until Step 4's verified findings are closed. - -##### Full Step 4 round-2 correction validation and closeout (2026-10-16) - -The two added controls exercise the shipped lifecycle with actual PostgreSQL. -One holds the real server row, verifies transient failure without stored progress, -then observes a stored success resetting the owner cutoff. At the renewed exact -boundary, the owner refuses before provider acquisition or SQL. The other pauses -only a test-owned PostgreSQL container and lets all three actual native metadata -heartbeats fault. Owner-clock advances then drive past-cutoff drain. After real -storage recovery, the two clean pools replace their generations and serve work; -the affected pool retains its old actual scope cleanup despite a spare native -slot and one retained entry. Only positive cleanup permits its one replacement -and the pending admission. No shared fixture container is paused. - -These controls keep native Core heartbeat cadence and SQL/socket bounds real; -the four-minute policy interval uses the owner's logical clock. The held scope -is a synthetic barrier around actual native framework work. Neither test claims -four minutes of wall-clock outage, genuine resource-exhaustion incidence, -external-effect quiescence or production supervision. - -The final corrected-source focused run passes both controls. Three separately -compiled, temporary mutations of actual production source each fail at the -intended behavior: removed cutoff permits forbidden issuance; removed successful -reset refuses the next valid heartbeat; replacing actual cleanup with the stock -child join starts generation two while generation one still owns held cleanup. -Each mutant builds successfully and executes its one expected failing case with -zero skips. Original production bytes are restored and the CI-mode Release -solution rebuild passes with zero warnings/errors. These expected red controls -are not additional passing cases. - -A fresh independent runtime reviewer inspects the complete correction and all -final receipts, verifies source hashes and restored production bytes, and finds -no remaining issue. This supplements the full second round rather than replacing -it. The status corrections in Database Standards and Events/Outbox architecture -now link their current qualification to this owning record. No Accepted policy, -grant, dependency, migration or production business definition changes. - -The final complete Docker/PostgreSQL suite passes 1,743 cases, zero failures/skips, -in 12m33s. The unchanged non-Docker partitions retain the round-1 receipt: 2,166 -unit, 321 architecture, four contract and 176 HTTP integration cases. Together -these cover 4,410 distinct backend cases; this is a combined receipt, not a fresh -run of all five partitions at this correction. The two focused passes overlap -that complete Docker suite and are not added again. Six current corpus/trait -checks and seven ADR parser controls pass. The changed-document audit resolves -1,919 local links and 559 fragments with zero errors; added prose wrapping and -whitespace checks pass. None of these overlapping checks adds to the case total. - -Both full Step 4 reviews and all verified findings are closed. Step 4 is locally -complete; Step 5 proceeds automatically on development with the existing approved -transactional-owner, retry/recovery and terminal-audit scope. Steps 6–9 retain -capacity, external effects, recurrence and packet-wide enforcement/CI. No frontend, -demo, current-head CI or completed production business definition is claimed by -this closeout. - -### P02b-4 Step 5 — transactional owner and terminal audit (2026-10-16) - -**Locally complete after both fresh full review rounds, verified corrections -and independent focused fix verification.** -The existing approved package -owns this step; no new decision or approval is pending. Source implements the -closed ordinary root participant, acknowledged start publication, immutable job -attribution, final row/time fence and sticky cancellation-versus-COMMIT gate. -Business state, child jobs, outbox/domain completion and MUST audit share the -existing transaction owner. Positive COMMIT acknowledgement remains distinct -from subsequent scope/source cleanup; unknown COMMIT needs a real locked probe. - -Independent finite renewal, retry/recovery and terminal lanes retain actual SQL, -probe and cleanup owners. Six acknowledged starts preserve the five accepted -backoffs; unknown/Pending definitions defer, explicit retirement terminalizes. -The sixth audit seam binds only actual returned job-transition values and the -same live transaction. Terminal audit failure does not advance business work. -Source and application-pool ownership are qualified against the formulas in -[Database Standards](../standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity), -including timed-out auxiliary loaders and separately declared shared headroom. - -CI-mode Release builds pass with zero warnings/errors. The complete unit run -passes 2,212 cases with zero skips. Initial PostgreSQL qualification exposed -reserved SQL naming, transition cleanup and two real concurrency defects: - -- A joined admission probe could refresh the locked job header while retaining - an older attempt snapshot. It now reads the immutable attempt in a fresh - statement after locking the header, on the same connection/transaction. The - restored original JOIN fails the committed-admission regression while its - rollback control passes; restoring the correction makes both cases pass. -- Deferred count validation upgraded the parent lock to `FOR UPDATE`, blocking - renewal COMMIT behind an unrelated child's key-share lock. A forward migration - uses `FOR NO KEY UPDATE`, preserving count-writer serialization and applied - history. Real child-lock renewal and exact one-function Down/Up controls pass. - -Focused real PostgreSQL controls pass for business/outbox/child-job/MUST-audit -atomicity, stale authority, lock-wait expiry, uncertain COMMIT, terminal witness -substitution, and native terminal-audit backlog progress beyond two leases. -Actual application and privileged sources remain retained through ignored -cancellation, held callback and messaging cleanup controls. These overlapping -focused receipts are not a second complete backend run. - -The first full architecture run records 322 passing and six failing cases out -of 328, with zero skips. Failures identify the published method count, the same -JobExecutor's additional partial path, exact physical transaction-owner lists -and retained-factory scanning. Corrections preserve finite ownership and planted -controls; four focused count/writer/parallelism reruns pass. The new orchestration -detector indexes each evaluation's actual field instructions once, retaining every -mutation/restoration check. The corrected complete architecture run passes all -328 cases in 17 minutes 31 seconds. A fresh complete run also passes 2,212 unit, -four contract and 176 Docker-free HTTP cases, all with zero skips. - -The complete Docker run records 1,771 passing and 39 failing cases out of 1,810 -in 13 minutes 1 second, with zero skips. All failures belong to two old fixtures: -DeliveryExecution's observed-unit factory still resolved the removed raw source -alias, and EducationPersistence passed the driver's password-free connection -string view to its API composition. The former now passes the existing lazy -source explicitly; the latter supplies original fixture configuration while -preserving the Seeder's caller-owned source. No raw alias or second DI disposer -is restored. After a clean Release build, both complete classes pass all 43 cases -in 19 seconds, with zero skips. Their four overlapping earlier passes are not -added twice. Together these runs establish 1,810 unique passing Docker cases and -4,530 unique passing backend cases; this is not a second complete-suite rerun. - -Formatting, seven ADR parser controls, 1,755 local links and 500 fragments pass. -Both fresh full review rounds follow the validated implementation commit; no -completed review or Step 5 closeout is claimed. Steps 6–9 remain pending. - -#### Step 5 review round 1 - -Three fresh independent reviewers inspected `4826b7df..9b634405`: owner, -authority and lifetime (GPT-6-astra xhigh), control/SQL/terminal audit -(GPT-6.1-sol xhigh), and proof/composition/corpus (GPT-6.1-sol xhigh). The last -lens reviewed all 109 changed files and independently recalculated the composite -TRX totals and original-JOIN mutation/restoration evidence. Two confirmed groups -required correction; no additional Blocker or verified finding remained. - -- A cache caller could return while the original auxiliary task still cleaned - its connection. The executor froze this pending state as a permanent cleanup - failure, preventing eventual positive generation release. It now joins that - exact task without the expired caller token before deciding cleanup. Business - issuance closes first; framework's prior binding closes while its successful - admission keeps the same owner open. Genuine disposal failure stays retained. - Exact caller/signature controls reject extra, async, detached, missing and - token-taking joins. Four unit cases and native clean/dirty controls exercise - original loader cleanup, private callbacks, retained identity, healthy later - work and both requested source disposals. -- Business COMMIT-acknowledgement loss and final lock-wait expiry previously had - real PostgreSQL direct-executor controls only. New pinned native-worker cases - stage organization, child-job, outbox and MUST-audit effects. Lost ACK retains - the actual identity while a fresh database probe is causally locked, then - resolves without a duplicate effect or vendor retry. Expired/live final-lock - controls prove atomic rollback/commit and the actual retry disposition. - -CI-mode Release builds pass with zero warnings/errors. The complete unit run -passes 2,216 cases; the complete architecture run passes all 328 in 18 minutes -3 seconds; 36 focused PostgreSQL cases pass, including the five new native rows. -All report zero skips. The initial focused run passed 34 of 36; both failures -were the new auxiliary fixture attempting a second rollback after its lock had -already been released. Explicit lock ownership fixes teardown, and the same -36-case rerun passes without weakening a production assertion. - -The actual-source control restores the old pending-cleanup snapshot temporarily. -It builds, and both native auxiliary variants fail specifically because the -business task completed before its original cleanup. Restoring the exact source -bytes, rebuilding and rerunning makes both pass. Raw exception logging observed -in two existing helpers was not established as a new Step 5 disclosure or violated decision; it was not promoted to a finding -or bundled into this correction. - -The focused run overlaps 31 prior Docker cases and adds five. Combining current -complete unit/architecture, prior contract/HTTP, and the existing corrected Docker -receipts gives 1,815 distinct passing Docker and 4,539 distinct passing backend -cases, using `(testId, testName)` identity. This is explicitly composite evidence, -not another complete-suite rerun or current-head CI claim. Formatting, the -nonempty/zero-skip runner, seven ADR parser controls and local links/fragments pass. - -The second full fresh review round follows the correction commit. Step 5 and -Steps 6–9 are not declared complete by this first-round receipt. - -#### Step 5 review round 2 - -Three new independent reviewers inspected the complete `4826b7df..9dbea7bf` -range: owner/authority/lifetime (GPT-6-astra xhigh), control/SQL/terminal audit -(GPT-6.1-sol xhigh), and proof/composition/corpus (GPT-6.1-sol xhigh). Three -verified groups required correction; timer and control findings were independently -corroborated. No additional Blocker or verified finding remained. - -- Reconciliation silently stopped at a pending/faulted job auxiliary, then cleared - the rolled-back MUST intents. Removing that precheck lets the actual standalone - writer refuse another acquisition inside its existing reporting boundary. - Every intent now receives the required bounded Critical, operation-only failure - counter and unhealthy audit signal; the original business refusal stands. - Native clean/dirty controls assert the absent rolled-back audit row, actual DI - logger/meter/health signals and unchanged held resources. A two-intent unit - companion proves independent reporting without resolving another source. -- Timer disposal preceded renewal closure. A late acknowledged renewal could - rearm a disposed timer and cancel unrelated batch members through the shared - error path. Renewal now closes permanently under the publication lock before - disposal. A deterministic real-timer disposal-gap control keeps a second - execution live and forbids early identity release. -- A positively cleaned pre-COMMIT control fault discarded its original permanent - business decision. The request now retains that exact decision and retries on - the bounded existing cadence; uncertain COMMIT and failed cleanup keep their - separate paths. A native worker returns one permanent refusal, hits a real SQL - lock timeout, retains its exact identity/request, then terminalizes with one - MUST audit and no second business start, including after lease expiry and a - duplicate native wakeup. - -CI-mode Release builds pass with zero warnings/errors. The complete unit run -passes 2,218 cases; complete architecture passes 328 in 17 minutes 23 seconds; -37 focused PostgreSQL cases pass. The control-failure proof now captures progress -while its actual SQL is blocked, rechecks that wait, then observes a completed -failed iteration before separately asserting the retained request/identity. After -this test-only strengthening, a fresh clean build and the same 37-case run pass. -All passing runs report zero skips. - -Three actual-source mutations compile and fail their intended assertions: -silent audit refusal fails one unit and both native health controls; late renewal -closure fails at the disposed real timer; discarded control decisions fail the -retained-request assertion with zero pending outcomes. Each exact source is -restored in a finally, rebuilt and its same regression cases pass. No mutation -remains in the tree. Formatting, seven ADR parser controls, local links/fragments -and the nonempty/zero-skip runner pass. - - -The focused run adds one Docker case to prior corrected receipts. Current -complete unit/architecture, prior contract/HTTP and corrected Docker receipts -establish 1,816 distinct passing Docker and 4,542 distinct passing backend cases -using `(testId, testName)` identity. These are composite receipts, not another -complete-suite rerun or current-head CI. All nineteen job obligations remain -Registered; Step 9 owns final enforcement and packet regression. - -The corrections are committed at `6a2ded99`. Normal hooks pass eight-file -Leakwatch and seven-file C# formatting, with no C# byte changes after validation. -Two new independent reviewers verify that correction and its immediate -lifetime/authority and proof/corpus dependencies: GPT-6-astra xhigh and -GPT-6.1-sol xhigh. Both approve without verified findings. The proof reviewer -independently recalculates the composite counts, checks each intended mutant -failure, and compares exact restored source bytes. They inspect recorded local -receipts, without rerunning the toolchain or claiming current-head CI. This is -focused correction verification, not a third full review round. - -Step 5 is locally complete. Step 6 proceeds under the existing approved package; -Steps 7–9 and packet-wide regression/PR/CI remain pending. - -### P02b-4 Step 6 — tenant capacity reservations (2026-10-16) - -**Locally complete after both full review rounds and verified corrections.** -Step 5 closes at correction `6a2ded99` after both full rounds and independent fix -verification. Accepted ADR-0047 and the approved nine-step package own this step; -no new capacity-policy decision or approval is pending. - -- App-role admission locks the tenant/group mutex, resolves an optional registered - Hard LimitKey and counts every unreleased reservation across organizations and - instances. Deferral spends no normal attempt. Existing entitlement provider/key - contracts and empty production definitions remain unchanged. -- Successful business completion releases its exact reservation on the existing - business transaction. Failed or skipped work needs a distinct local actual - cleanup witness and acknowledged nonexecuting recovery authority before a - sequential app-role checkpoint can release occupancy. No executable receipt is - reconstructed after lost admission acknowledgement. -- A forward storage change records truthful transactional cleanup separately from - never-started or external-quiescence evidence. The original source owner stays - open across sequential phases while every old binding closes permanently. - Missing cross-instance cleanup evidence retains occupancy in recoverable parked - state, permitting a live origin's eventual positive cleanup; TTL never releases. -- Control handles each checkpoint as a bounded owned operation, preserving fair - service and actual stop/cleanup ownership. The existing transaction owner, - tenant-setter inventory and bypass reservation-write prohibition remain intact. - -Qualification covers two-instance/two-org caps, no-attempt refusal, unlimited/ -zero/downgrade/fault limits, atomic success/cleanup release, admission and checkpoint -COMMIT uncertainty, held callbacks/resources, missing-witness parking, exact grants -and source bounds. Each implementation/correction commit and both fresh review -rounds are recorded here after they occur. Live external execution remains Step 7; -final observation/enforcement and full packet regression remain Step 9. - -#### Step 6 implementation and qualification (2026-10-17) - -The app-role start owner locks the job, then the tenant/group mutex. A separate -post-wait statement counts every unreleased reservation across organizations and -instances. The registered Hard projection intersects the operational ceiling; -missing/unlimited, zero, positive, oversized and invalid/faulted answers retain -the accepted bounded semantics. Capacity refusal spends no attempt. No production -job definition, entitlement key or provider is introduced. - -Business success releases its exact reservation on the existing business/MUST/ -outbox/child-job completion transaction. Other grouped transactional outcomes -must join the actual admission/business, auxiliary resources, observers and -original private cancellation callbacks before minting a local cleanup witness. -Genuine no-start requires an atomic unused-entry seal, including receipt-less -admission uncertainty. This witness grants neither execution nor database truth. - -The confined recovery owner publishes a separate nonexecuting capability only -from acknowledged acquisition or an exact locked proof. The same original -application-source owner then enters one fresh sequential checkpoint. Its old -bindings remain permanently closed. Evidence and release commit together; -unknown checkpoint COMMIT probes read the descriptor's historical attempt after -the header lock, separately from current routing authority. Missing local cleanup -parks occupied work with a paced probe; neither TTL nor a replacement owner -manufactures cleanup. Stop retains and joins every issued checkpoint/callback. -Host stop admits no fresh cleanup checkpoint; a clean local stop cannot substitute -for cleanup evidence that never committed, so restart still retains that occupancy. - -Forward migration `20261016210528_add_transactional_job_capacity_cleanup` adds -write-once transactional cleanup evidence, its exact release reason and three -existing guard replacements. The predecessor's non-key count lock remains. -Only the app UPDATE and dispatcher status-SELECT column budgets expand; bypass -reservation writes remain refused. Down refuses recorded new history rather -than erasing or relabeling it. Canonical fresh DDL comparison remains exact; -Down/reapply accounts only for PostgreSQL's advanced physical position of that -single dropped/readded column, preserving every other inventory fact. - -Exact owner, framework-request, minting, command, task/callback, source and final -SQL-fence censuses gain closed enrolled paths and planted dirty/clean controls. -The existing transaction owner and ADR-0040's eight logical GUC setters remain; -the new executor partial belongs to the same ADR-0036 context writer. Its exact -accessor-writing file is enrolled explicitly; no new logical writer is added. -Sequential cleanup adds no simultaneous main/auxiliary checkout to the current -acquisition inventory. - -Initial qualification exposed two missing SQL separators in the new checkpoint -builder; actual native tests now fail directly through a sanitized observer fault -signal instead of hiding the handler failure behind a timeout. Both separators -are fixed and the same four real native cleanup/acknowledgement-loss cases pass. -It also corrected the no-plan fixture's empty-provider assertion and the precise -physical-column comparison above. Initial failing receipts are retained. - -#### Step 6 validation receipts (2026-10-17) - -Local CI Release build completes with zero warnings/errors. The full Unit suite -passes 2,229 cases, Contract passes four, and integration without Docker passes -176, with zero failures/skips. These are separate local suites, not current-head -PR CI or full packet closeout evidence. - -Focused PostgreSQL qualification passes all 192 cases after the SQL separator and -fixture corrections above. Eight additional native facade cases pass together, -including admission and capacity-checkpoint acknowledgement loss, private callback -retention and receipt-less genuine no-start. A first tight-budget no-start run -reached a disposal-barrier timeout once; that cause was not reproduced. The same -two cases and two repeated mixed eight-case runs then passed. The new no-start -fixture now uses the accepted five-second SQL budget and a ten-second transaction -budget, retaining every barrier and bounded failure diagnostic. This removes an -unnecessary cold-source/role-initializer/read constraint; it does not establish the -cause of that initial timeout. - -Three actual production-source mutations compile and fail their intended -behavioral controls: counting before the real tenant/group mutex wait (two cases), -leaving sealed unused execution permission open (one), and omitting the actual -private cancellation-callback join (three). The initial callback observation let -one mutant pass; the held-callback observation was strengthened, and all three now -fail against that mutant. Every source file is restored byte for byte, freshly -rebuilt, and the same respective controls pass. No mutation remains in production. - -The first full architecture run reports 330 cases, 327 passed and three failed. -Two failures identify stale exact admission/privileged-owner caller inventories; -the other exposes a detached-Cecil-method null dereference after the detector -already records the forbidden target. The corrected guard enumerates the actual -new owners and reuses the existing exact local-revalidation proof. The capacity -detector returns its known detached-target offenders before unsafe identity -inspection. No target filter, namespace exemption or weakened production boundary -is added. Both corrected clean guards and their complete planted-control tests -pass together: four cases, zero failures/skips. - -The corrected full architecture baseline passes all 330 cases in 1,695.7 seconds. -The first full Docker run reports 1,848 cases: 1,847 passed and one native framework -lifetime row timed out before reaching its real cleanup barrier. Both original -rows subsequently pass with bounded diagnostic observations; that does not -establish the cause of the earlier timeout. The corrected lifetime fixture keeps -actual pinned native workers, physical SQL deadlines, held cleanup and source/ -slot/stop assertions. It parks the three polling loops, issues exact native wakeups, -and advances only the owner observation clock after the actual barrier. This -intentionally removes incidental bridge ACK/cold-start timing from that lifetime -proof; separate real bridge/repair controls remain and pass with the common -PostgreSQL-outage proof: 21 cases. Both corrected lifetime rows also pass. - -Two invocation-local/name-first detector filters preserve complete subjects, -identity/signature/opcode checks, caller multiplicity and every clean/dirty/restored -mutation. The same four complete guards pass in 311.2 seconds versus 515.3 before -these filters. Capacity dirty control falls from 251.6 to 113.2 seconds; authority -from 261.9 to 196.3. A source/equivalence preflight finds no actionable issue; it -supplies no full Step 6 review credit. - -The final full architecture run passes **330/330** in 1331.9 seconds, and the -fresh full Docker integration run passes **1,848/1,848** in 889.3 seconds, -with zero failures/skips and identical case-name multisets to their baselines. -Together with Unit, Contract and Docker-free integration, these distinct local -suites pass **4,587** cases. Focused/negative/restoration receipts are overlapping -proof and are not added to that total. The local timing comparisons do not prove -the complete real CI backend job fits its 20-minute ceiling; Step 9 retains full -packet regression and real PR CI qualification. - -At this qualification head, both full fresh review rounds and their verified -corrections remained pending. All nineteen job obligations remain Registered; -Step 9 owns complete packet enforcement/regression. External execution and -recurrence remain Steps 7–8. -ADR-0061 is separately Accepted in `82956666`; its dependent Step 7 implementation -starts only after Step 6 closes its two full review rounds. - -#### Step 6 full review round 1 (2026-10-17) - -Implementation commit `caf51297` passed normal hooks with a clean tree. -Three fresh independent reviewers inspect its complete 64-file scope and connected -paths: two GPT-6-astra reviewers at xhigh for ownership/lifecycle and storage/ -isolation, and GPT-6-sol at xhigh for tests/corpus/performance. They inspect source -and actual receipts; they do not rerun the toolchain or claim CI qualification. - -Both runtime reviewers independently confirm one Major local lifetime race. After -an exact historical cleanup probe releases its row lock, another instance can route -the released job to a new generation before local recovery reacquisition. A clean -null acquisition then repeats the permanently obsolete generation, retaining the -original invocation despite settled history. The corrected null branch reinstalls -its exact historical cleanup descriptor when a checkpoint is already committed. -Settlement still needs the locked original evidence plus changed routing; a live -peer lease remains pending. The production correction is five lines and changes -neither schema nor grants. A separate permanent-decision durability concern is not -confirmed as a new regression against existing crash/recovery handling of decisions -not yet recorded. - -Three native takeover cases cover the probe-unlock interleaving, live-other-owner -retention and a lost recovery-acquisition COMMIT acknowledgement. The test proxy -holds the actual historical ROLLBACK response only after PostgreSQL unlocks; an -independent store performs real fenced routing. The live-lease control uses an -explicit privileged fixture lease and waits for another actual locked probe before -asserting retention. All preserve one original attempt/checkpoint and immutable -release history, then join the original source and native slot without host stop. -Before the final fixture strengthening, the first two cases failed the original -implementation's final-join assertion after their positive database premises. -Removing the re-probe correction from the final source compiles and fails all -three current takeover controls at their missing-probe or final-join assertion. -Exact source restoration and a fresh build pass the same three cases. This includes -the recovery-acquisition ACK-loss entrance and preserves live-peer retention. - -The proof review also identifies two missing native stop windows. New controls -stop after a real recovery ACK before checkpoint issuance, and after issuance -while its actual private cancellation callback is held. The first observes the -actual control loop past the issuance window while a separate stop callback keeps -final request release held. The second observes the real app task's known rollback -separately from the checkpoint's still-pending callback join. Neither source nor -invocation is falsely released. Removing both issuance guards or the checkpoint's -actual private callback join compiles and fails the respective intended assertion. -Both production files are restored byte for byte, rebuilt, and pass those controls. - -Initial takeover-harness runs do not supply runtime proof: a thirty-second proxy -lifetime obscured the primary failure, and a diagnostic run exposed a row-description -flag reset at each ReadyForQuery before the intended ROLLBACK hold. The corrected -proxy has a separate finite test lifetime, transaction-scoped observation and primary -failure preservation. A read-only fixture preflight strengthens the actual second -probe, exact peer lease fence and host-stop cancellation premises; it supplies no -full second-round credit. - -The new release reason joins the existing real app-role forged-release refusal / -removed-trigger dirty control. Standards 05's stale pending-qualification wording -is corrected. Two further invocation-local/name-first Cecil filters preserve every -production subject, exact signature/opcode, caller multiplicity and planted control; -no global cache or owner exemption is added. - -Fresh format and CI Release build pass with zero compiler warnings/errors. The -focused native/release set passes nine cases. Full Unit passes 2,229, Contract four, -Docker-free integration 176, Architecture **330/330**, and Docker integration -**1,854/1,854**, all with zero failures/skips: **4,593 distinct full-suite cases**. -The architecture case multiset is unchanged; all 1,848 previous Docker cases remain -and six new cases account for the difference. Focused and mutation receipts overlap -these suites and are not added to that total. Full architecture takes -1318.4 seconds versus 1331.9 at implementation qualification; -full Docker takes 933.2 seconds. These are local measurements, -not a real CI budget pass. Current-head CI remains unrun. - -The first-round corrections are locally qualified. The second full fresh review -starts only after their normal local commit. All nineteen job obligations remain -Registered; the published architecture-method count remains 237. Step 6's second -full review gate is pending. Steps 7–9 and full packet/PR/CI closeout remain pending. - -#### Step 6 full review round 2 and local closeout (2026-10-17) - -First-round correction `d387f71f` passed normal hooks with a clean development -branch. Three new independent reviewers inspect the complete **68-file** Step 6 -scope: GPT-6-astra at xhigh independently covers ownership/lifecycle and storage/ -isolation, and GPT-6-sol at xhigh covers proof/corpus/performance. They inspect -source and parse actual receipts, without claiming personally executed tests or CI. - -Both runtime reviewers independently identify one further Major admission-lifetime -race. A physical admission COMMIT can fail before reaching PostgreSQL, leaving no -original attempt or reservation while its local outcome correctly remains uncertain. -If a peer clears the expired routing token before original scope cleanup finishes, -the old probe sees changed authority. Discarding that admission descriptor then -retries recovery acquisition for history that cannot exist, retaining clean work. - -The correction makes a fresh exact admission-token history read after acquiring -the actual job-row lock. Locked absence proves rollback independently of current -routing. Existing original history remains distinct from a peer's later attempt; -positive original release requires its exact reservation and corresponding immutable -evidence. Changed authority alone never settles the request, and its unresolved -historical descriptor remains retained. The read probe changes no peer state and -constructs neither executable nor recovery authority. No schema, grant or source -capacity changes are needed. - -The new native control drops the actual second app COMMIT request before the server -receives it, holds real original scope disposal, and uses an independent real -recovery store to clear expired routing. It verifies absent original attempts/ -reservations, uncertain admission with no executable receipt, no business constructor, -and original control/source/native join without host stop. The unchanged production -source fails at that final-join assertion; the correction passes. Four guarded -app-role history cases distinguish absent original with/without peer admission, -committed occupied original, and positively released original before a real second -peer admission. The positive history setup is explicitly a storage fixture rather -than a minted runtime cleanup witness. Peer header and occupancy remain unchanged. - -Two additional fresh reviewers, GPT-6-astra and GPT-6-sol at xhigh, inspect the -complete correction and its connected owner/history/proxy controls without further -verified findings. The targeted set passes ten cases, including actual lock wait, -lock timeout and both existing native admission-ACK outcomes. Removing historical -probe dispatch compiles and fails the native join plus three history assertions; -the occupied-original control still passes. Making existing history falsely mean -rollback separately fails that occupied-original control. Both source mutants are -restored byte for byte with their modes, rebuilt, and the same five cases pass. -Focused receipts and negative mutations overlap the full suite; they are not extra -passing cases. Formatter normalization changes only test whitespace. - -The first full Docker receipt reports 1,858 passed and one failed among 1,859 -cases, with no skips. The common-outage fixture times out after the owned database -pause while waiting for all three original metadata-heartbeat fault observations. -It supplies no evidence of a failed pre-outage healthy job or a cause linked to the -admission-history correction. A separate read-only source diagnosis establishes no -deterministic production fault. Bounded elapsed-phase and failure-time memory-only -pool diagnostics are added before teardown; no wait, option or assertion changes. -The same focused scenario then passes in 38.2 seconds, with pause completed at -0.55 seconds and all native faults observed at 35.3 seconds. This later pass does -not establish the earlier failure's cause. Both independent correction reviewers -inspect the diagnostics and this evidence limit. The original failed receipt is -retained. The second complete Docker run passes that outage scenario, but the -new native rollback case fails before the intended COMMIT drop: zero drops, one -bridge ACK and no retained control execution. No history assertion is reached. -Source inspection confirms a permitted setup race: bridge ACK takes the job-row -lock, native routing can skip that lock, and the default 60-second repair grace -exceeds this fixture's 30-second wait. The receipt does not establish that race -as its cause. The fixture now mirrors the existing lifetime controls: park empty -owner polling, issue an explicit stock/native wakeup, then pulse only owner polling -for the actual original join. It asserts zero initial bridge ACKs and retains the -real second-COMMIT drop, peer takeover, zero attempts/reservations and source refusal. -The outage fixture similarly parks polling around its existing explicit wakeups; -its real heartbeat cadence, 90-second bound and all lifecycle assertions remain. -Both independent reviewers verify the actual eight-file candidate against its -manifest without a further confirmed finding. The repeated production removal -mutant reaches the real COMMIT drop and fails specifically at original final join; -exact restoration passes. Both complete failed receipts remain recorded; the -fresh complete Docker receipt below is a separate passing result. - -Final full format verification and CI Release build pass with zero compiler -warnings/errors. The critical native/history/stop/release and lifecycle set passes -**24/24**. -The last changes affect only the two integration fixtures; the exact production -bytes and earlier full Unit/Contract/Docker-free/architecture subjects are unchanged. -Full Unit passes **2,229**, Contract **4**, Docker-free integration **176**, -Architecture **330/330**, and Docker integration **1,859/1,859**, with zero failures -or skips: **4,598 distinct full-suite cases**. Architecture names are unchanged; -all 1,854 preceding Docker cases remain and exactly five new cases account for -the increase. Full architecture takes 1315.5 seconds; -full Docker takes 960.2 seconds. These local measurements -provide no real GitHub Actions budget pass; current-head CI remains unrun. - -Step 6 is locally complete after both full fresh reviews, verified corrections -and their independent verification. All nineteen background-job obligations stay -Registered and the published architecture-method count stays 237; Step 9 owns -complete packet enforcement/regression and real PR CI. Accepted ADR-0061 in -`82956666` authorizes the next external-stage implementation. Steps 7–9 and full -packet/PR/CI closeout remain pending; no production business definition is added. - -### P02b-4 external completed-failure proposal (2026-10-16) - -**Initial proposal status, before the 2026-10-17 acceptance: Proposed; the -maintainer's first review required changes and explicit reapproval.** Current -acceptance is recorded [below](#adr-0061-acceptance-and-step-7-contract-2026-10-17). -Step 7 preparation identified an unanswered report-policy input: direct completed -Failed/Cancelled reports carry outcome/quiescence, without classifying the failure -or granting retry of the same stable logical operation. Existing guards permit -both retry and finalization; they do not select between them. - -The initial [ADR-0061](../decisions/0061-known-external-job-failure-policy.md) draft -at `8e0f982b` proposed separate failure class and same-operation permission, -write-once status and a terminal code when transient work cannot be repeated. -Its initial source/contract audit was against `6a2ded99`. No dependent Step 7 runtime or migration is implemented or -authorized by this proposal. Step 6 capacity work continues under Accepted -ADR-0047; the existing nine-step review/commit loop remains unchanged. - -**Initial-draft reviews at `8e0f982b`:** two fresh independent proposal reviewers -(GPT-6-astra xhigh and GPT-6.1-sol xhigh) approve that initial draft for maintainer -consideration without verified findings. They -check the actual contract/guard/grant and reason carriers, the exact bounded -supersession, restart equivalence and discriminating pending proof obligations. -The corpus reviewer independently verifies the ADR's links/anchors, Proposed -status and prose width. No runtime test is claimed. Maintainer acceptance still -precedes dependent Step 7 implementation. - -#### ADR-0061 revision after maintainer review (2026-10-17) - -**Historical revision record, before acceptance below.** -The maintainer requested changes to the initial proposal; that review was not -approval. Source checks confirm the missing finalization/terminal policy guards, -the app/control ownership distinction and the absence of durable cancellation -origin. The [revised ADR](../decisions/0061-known-external-job-failure-policy.md) -remains Proposed and supplies the complete decision and proof inventory. - -The new choices for reapproval are one nonzero three-state policy and Permanent -only for Failed. Cancelled explicitly states repeatability of the same operation; -malformed Permanent cancellation is rejected without rewriting it. Adapter truth -must survive reconciliation, while the runtime claims no certification of external -causality. App-owned selection, deterministic storage and actual-row-bound audit -cover retry, finalization and terminal reasons. The ADR separately maps module -reasons, capacity release and all seven affected Registered rules. - -Two new independent reviewers, GPT-6-astra xhigh and GPT-6.1-sol xhigh, approve the -full revised proposal for maintainer consideration without Blocker/Major findings. -Their verified Minor corrections name stored outcome kind rather than an -identifier DTO, and publish a clearly Proposed glossary pointer now. Both reviewers -verify those corrections without further findings. These are source/design reviews; -no new runtime, migration or passing execution proof is claimed. - -Error Handling's inherited five-attempt/jitter summary is independently reconciled -with already Accepted ADR-0047. This does not accept ADR-0061 or change its budgets. -No Accepted ADR body is edited. Explicit maintainer acceptance and its own decision -commit still precede dependent Step 7 implementation; Step 6 continues independently. - -### ADR-0061 acceptance and Step 7 contract (2026-10-17) - -**ADR-0061 is Accepted — 2026-10-17.** The maintainer's latest review considers -the previous seven gaps closed and finds no acceptance blocker, conditional on -correcting the catalogue Status step lists before the acceptance commit. This -decision includes Storage Steps 1–2, 6–9 and Retries Steps 4–5, 7 and 9; all seven -affected rules remain Registered, with counts unchanged. Their extended Asserts -record pending Step 7 qualification and Step 9 enforcement, not completed proofs. - -[ADR-0061](../decisions/0061-known-external-job-failure-policy.md) selects the -three-state policy, Permanent only for Failed and deterministic database retry, -finalization and reason guards. The app owns the immutable attempt outcome/policy -and finalization selection; actual returned row facts bind terminal audit. -[ADR-0047 Amendment 4](../decisions/0047-transactional-background-job-runtime.md#amendment-4--known-completed-external-failure-policy-2026-10-17) -discloses the exact completed-report input replacement and additive seams without -rewriting the Accepted body. The decision index, glossary, Error Handling status -and all seven catalogue assertions are synchronized in this acceptance decision. - -Winning owned stop closes new outcome-checkpoint and COMMIT admission even with -a live database lease; an already admitted COMMIT retains its actual result. -Durable confirmed outcomes win over later reports. Honored cancellation remains -Cancelled across restart. A nonrepeatable cancellation may finally fail the same -job during deploy through the prepared domain finalizer and atomic MUST audit; -the Transient taxonomy supplies no promise of resumability. - -Step 7 now implements and qualifies this contract before external activation, -including the forward migration and normative implementation carriers. Step 9 -closes full enforcement/regression. The nine-step sequence and two fresh -independent implementation review rounds per step continue; the historical draft -reviews above do not satisfy them. Step 6 capacity work remains independently -authorized under ADR-0047. Acceptance supplies no new runtime or passing proof. - -### P02b-4 Step 7 — external stages and recovery (2026-10-17) - -**Implementation, both full review rounds and verified corrections complete.** -The round-2 closeout below owns the final local receipts. Step 6 -closes at `0ea50b15` after both full reviews, verified corrections and 4,598 passing -full-suite cases. Accepted ADR-0047 and ADR-0061 authorize this next step on -`development`; no further decision or permission is pending. - -**Remaining closure units — 2026-10-17.** The original Step 7 scope remains -unchanged. Its long-running implementation is now tracked by these explicit -closure units; focused receipts below do not close the step or its full reviews: - -- [x] Finish no-plan terminal cleanup, exact owner handoff and atomic terminal - audit, including persistent reason and complete positive history guards. -- [x] Finish finalizer rollback/retry/refusal/exhaustion and prepared uninvokable - terminal behavior, preserving the separate six-start finalization budget. -- [x] Close external/transactional contention, retained cleanup, exact owner/ - source/caller censuses and their planted violations; qualify the complete step. -- [x] Commit Step 7 and complete both fresh independent full review rounds, - verified corrections and correction commits before advancing to Step 8. - -The foundation separates sticky process/run stop from eight finite stage COMMIT -boundaries. Admission is prebound before SQL; physical acknowledgements survive -stop without reopening later stages. Transactional capacity cleanup retains its -own fresh boundary on the same process cell and original clean source. The actual -successful result reaches the existing sole completion participant. Closed report -factories require the explicit three-state policy; Completed is removed. - -An early targeted source review identifies one P1 with two stop-refusal paths that -faulted owned tasks before their finite cleanup/publication handling. Both paths -are corrected. Two actual source mutants independently fail the corresponding -admission or grouped-business regression while its sibling passes. Exact source -and modes are restored, the CI Release builds have zero compiler warnings/errors, -and that correction's focused foundation suite passes 61 cases with zero failures/skips. -The reviewer independently verifies the correction, actual receipts and restoration. -These checks and that early review supply no full Step 7 review-round credit. -Two earlier failing fixture receipts remain recorded; the diagnostic identifies -an incorrect NeverStarted expectation, corrected to the existing positive owned -transactional-rollback result while separately asserting unused root entry. - -The forward failure-policy migration and canonical guards now pass 189 actual -PostgreSQL storage cases. Two early source-review findings are reproduced and -corrected: terminal requests cannot set the incomplete-finalization flag before -the actual terminal transition, and incompatible retained predecessor selection -or outcome/release history refuses upgrade without inventing missing facts. -Independent correction inspection verifies those fixes. External denial also -covers pre-existing UoW frames before their state changes and the four concrete -owner-null auxiliary loaders; their original failing controls and corrected -receipts are retained. - -The original-execution checkpoint foundation adds exact app-role read, Arm and -Outcome requests on the existing transaction coordinator. Prepare captures its -actual successful typed result, writes the immutable canonical plan and stamps -the original normal attempt in the same transaction. Its clean source remains -available for the next sequential checkpoint. These paths do not activate the -external routing engine. - -An early checkpoint review identifies a canonical-byte defect: JSONB parameters -rewrote text-column payloads. Both plan and outcome now use text parameters. -Actual PostgreSQL execution separately exposes four missing SQL-concatenation -spaces; the initial six failures and diagnostic `42601` receipt remain recorded. -After correction, six state/policy cases and two typed byte-boundary cases pass. -The production Prepare and Outcome writers preserve 65,536-byte canonical JSON; -a 65,537-byte outcome refuses before mutation and leaves occupancy retained. -Reintroducing only the plan JSONB binding fails all eight cases, including the -actual plan byte CHECK. Reintroducing only the outcome binding fails seven while -the oversized-input refusal still passes. Exact source/mode restoration passes -all eight again. Independent correction review verifies source, receipts and -both restoration hashes; this supplies no full Step 7 review-round credit. - -At the earlier checkpoint snapshot, the full Unit assembly passes 2,305 cases and the -focused PostgreSQL selection passes 349, with zero failures or skips. The latter -includes all 189 storage cases, the eight checkpoint cases and existing physical -owner/business/audit/helper/source controls. Its receipt validator initially -expected 342: the expanded class filter also selects seven unchanged source-owner -siblings. A separate exact-subject and 95-file source/hash audit confirms all -original subjects plus those seven passing cases; no failed test is reclassified. -Fixture-supplied admission and Audit Off business roots isolate checkpoint SQL; -these are not provider execution or domain-MUST-audit proofs. - -The original Execute bridge now requires the exact command owner's physical Arm -acknowledgement, the current Arm boundary, the original clean source and a frozen -canonical plan. The external denial scope precedes adapter construction; the -actual task, immutable observation and failed cleanup owners remain retained. -An early review catches a command borrowing another command's gate acknowledgement; -the correction and its discriminating regression are verified independently. - -Fresh recovery has a distinct eighteen-column status projection and never mints -a counted start receipt. Its new lease can outlive the original attempt deadline. -Acquisition/probe publication follows actual COMMIT acknowledgement or explicit -probe rollback acknowledgement and successful resource cleanup. A specialized -owner retains the originating operation, exact descriptor and process stop cell; -all confirmations share one receipt and one source/run binding. Early review -identifies original-cleanup substitution, duplicate receipt publication and a -cross-process-cell edge; all three are corrected and independently verified. - -The corrected snapshot passes 2,331 full Unit cases and 75 focused PostgreSQL -cases with zero failures/skips. Four actual source mutants each fail exactly their -intended regression; baseline and every restored source pass all eight selected -cases. Exact source hashes/modes and the receipts are independently audited. -Two further PostgreSQL cases prove actual acquisition COMMIT-response loss with -repeat confirmation of the same receipt, and refusal after a real token takeover. -The complete seventeen-case external checkpoint selection passes after those -additions. These storage/ownership checks do not claim provider execution, -domain-MUST atomicity or full Step 7 review-round credit. - -The three closed app requests now distinguish original admission from fresh -recovery authority. Original ledger identity remains separate from the current -recovery token; an expired original deadline does not invalidate a live recovery -lease. The read represents an absent plan explicitly and obtains causal metadata -from the actual app-role envelope. Its provisional recovery context invents no -trace, parent, incoming event or actor. Stored-fact parsing requires the exact -reservation and complete canonical plan/outcome, policy, quiescence and release -facts. Existing completed outcomes take precedence over conflicting later reports. - -An early app-owner review identifies a reused-plan exhaustion defect: a sixth -normal admission stopping before Arm lacks the plan stamp required by failure -selection. Two actual PostgreSQL regressions reproduce the exact `23514`, both -for first no-start and for independently retained unstamped no-start history. -The correction copies the validated immutable plan identity in the same locked -no-start transaction, preserving any existing timestamp and release. Its first -rerun exposes a second guard ordering issue: validated recovery finalization is -checked before eligibility-cycle normalization clears its token. The forward -migration and canonical guard now admit that exact app transition; normalizing -the new cycle still clears all recovery ownership and advances generation. -The predecessor Down body remains unchanged. Both failures remain in the receipts. -Independent inspection approves both corrections without full-round credit. - -The corrected snapshot passes all 2,331 Unit cases and 275 PostgreSQL cases: -189 storage, 26 external checkpoint, 20 capacity-admission and 40 control cases, -with zero failures/skips and a CI Release build with zero warnings/errors. -The checkpoint selection includes sixth-admission first/retained no-start, -recovery success and final-failure selection, token revocation and generation -advancement, no-plan recovery, armed no-start refusal and durable-outcome -precedence. These remain app/storage proofs with explicit fixture admission and -Audit Off roots; provider/native execution and domain-MUST atomicity are pending. - -The subsequent short-checkpoint boundary captures a conservative monotonic -lease window from fresh SQL after the actual job lock and before writes. -Original work also observes its immutable deadline; recovery uses only its fresh -lease. After pending audit, the exact owner's COMMIT admission checks the elapsed -window inside the same run lock as the stage CAS. Expiry closes the run and rolls -back; it cannot borrow an earlier successful handler check. This adds no generic -participant, callback or transaction entry. - -That boundary snapshot passes 2,333 Unit and all 32 PostgreSQL checkpoint cases. -Six cases park the actual handler before COMMIT admission without token -cancellation: Arm, original Outcome and recovery Outcome each have live and -expired-lease controls. PostgreSQL time establishes expiry; assertions inspect -actual rollback or committed intent/outcome/selection and capacity release. -Removing only the elapsed predicate fails exactly the three expiry cases while -all three live controls pass. Restoring exact source bytes and modes passes all -six again; both CI Release builds have zero warnings/errors. This remains a -targeted ownership proof, not external engine activation or full review credit. - -Read completion now also binds the exact canonical candidate recorded by its -actual read-only owner. An unrelated successful result or an unchanged clone -cannot obtain that owner's acknowledgement. Three actual PostgreSQL controls -verify the physical read-only transaction and application role, reject missing -or substituted candidates and accept the real recorded object. This later -snapshot passes 2,333 Unit and all 35 checkpoint cases, with zero failures/skips -and a CI Release build with zero warnings/errors. Executor read-handle publication -and cleanup ownership are qualified in the subsequent snapshot below. - -The named executor read driver now publishes an immutable handle only from the -exact acknowledged app-read candidate and positively completed cleanup. Recovery -uses provisional null causal metadata during Read; its handle retains only the -actual app-read envelope for later checkpoints. Actual held and throwing DI scope -controls cover both original and recovery origins. A physical read acknowledgement -survives cleanup failure, while the failed scope/unit owner stays retained and no -handle is published. - -An early review reproduces a cancellation gap after registration disposal but -before Activity cleanup, together with the pre-cancelled-entry edge. Registration -now remains owned through all actual cleanup; a final token check closes the run -before publication. Both original red cases fail on the intended open-run state. -The corrected snapshot passes 2,333 Unit and all 44 PostgreSQL checkpoint cases, -with zero failures/skips and a CI Release build with zero warnings/errors. -Subsequent test-only Task.Run hardening first exposes a test-ordering race in -the pre-cancelled case. Awaiting that actual task before its assertion corrects -the test; the held-cleanup case still asserts closure before release. Both final -cases pass after recompilation. Independent review verifies the unchanged -production hashes, exact subjects and separate receipts, closing the focused -finding without full Step 7 review-round credit. - -The named Arm, original/recovery Outcome and recovery-only NoStart drivers now -consume that exact read handle, retain their actual sealed request and await -scope, Activity, binding and cancellation cleanup. Original admission identity -stays separate from fresh recovery ownership. Only the actual app-read envelope -supplies later causal attribution; no provider report or bypass projection does. - -An early writer review corrects lost Activity ownership when Start throws and -duplicate issuance borrowing an earlier gate's COMMIT history. Real observer and -repeated-Arm cases discriminate both fixes: each source mutation fails exactly -its intended controls, and exact source/mode restoration passes again. All four -CI Release builds have zero warnings/errors. The first causal fixture run retains -two pre-driver `23514` failures from a nonexistent parent; a real parent row fixes -that fixture. Independent review audits 119 restored source hashes/modes, 2,333 -passing Unit cases and all 54 passing checkpoint cases, including ten named-writer -cases. This is a bounded slice receipt, not external activation. - -Six additional cases pass in the complete sixty-case checkpoint rerun. Actual -TCP COMMIT-response loss leaves Arm/Outcome uncertain while an outside app read -observes the landed transaction. Stop after the real handler but before COMMIT -records actual rollback; pre-cancelled entry and cancellation during held Activity -cleanup close continuation without erasing historical ACK. One further passing -case distinguishes an unissued duplicate from an earlier command's known rollback -and then commits through a fresh gate without another counted attempt. Production -source is unchanged from the 2,333-case Unit snapshot; the sixty-plus-one receipts -cover 61 distinct checkpoint cases. Seven ADR-parser and five corpus checks pass. -Provider/native integration and full Step 7 reviews remain pending. - -The original Execute bridge now accepts only the trusted read handle and exact -local Arm result. Fresh Reconcile accepts only its once-bound recovery and read -handle. Both retain the actual provider/cleanup task and external denial; stored -outcomes or absent intent skip provider construction without fabricating a report. -The last typed method-entry CAS remains separate from any earlier validation. -These helpers remain unwired to native execution and current-lease control. - -The next snapshot passes 2,333 Unit and eleven actual PostgreSQL bridge cases. -An early test review corrects masked ACK-isolation coverage using a real read -and an explicitly synthetic negative result around a distinct unacknowledged -command. It also distinguishes the first scope-only receipt from constructor -proof: that host lacked the fixture's adapter registration. The revised test-only -binding invokes the exact frozen, unchanged throwing constructor and records its -actual fixed exception under external denial. All eleven revised cases pass. -Removing both command-derived ACK checks fails only the borrowed-ACK case while -six siblings pass; exact source/mode restoration passes all seven again. Both -CI Release builds have zero warnings/errors. A throwing constructor proves entry -or refusal, never successful Execute/Reconcile or native lifetime semantics. - -The same start-observer ownership defect is then reproduced in the admission and -Prepare entry paths: both actual cases fail because the started Activity was lost -before assignment. Assigning the actual object before Start corrects both paths. -The subsequent CI Release build has zero warnings/errors; 2,333 Unit and 137 -PostgreSQL cases pass with zero failures/skips. That selection comprises all 74 -external-checkpoint cases, 23 admission, 20 business and 20 capacity-admission -cases. It includes both original red observer cases, the revised bridge controls -and the existing stop/cleanup/commit regressions. Full Step 7 review and native -activation obligations remain open. - -The history foundation now retains an exact issued Prepare/Arm/Outcome/NoStart/ -Finalize operation, with immutable business-result receipt and gate identity. -A separate job lock precedes its fresh, status-only 48-column original-attempt -query. Confirmation publishes only after explicit probe ROLLBACK acknowledgement -and actual cleanup; it never sets physical COMMIT ACK or rollback. Real lost-ACK -controls cover Prepare, Arm, Outcome and NoStart with open and stopped runs, plus -a closed duplicate Prepare that cannot borrow its predecessor's history. - -Early review corrects two unqualified Finalize classifier branches and separates -historical Arm truth from current Execute permission. Both the outer bridge and -last run CAS now require the exact command, current original owner and a -conservative monotonic lease/deadline observation. Live, takeover with an open -old run, elapsed-lease and borrowed-command controls use actual app checkpoints; -their positive remains constructor-canary evidence, not a successful provider -method. This snapshot passes 2,333 Unit and 127 PostgreSQL cases: 87 checkpoint, -20 business and 20 capacity-admission, with zero failures/skips and a CI Release -build with zero warnings/errors. An earlier Unit run retained one obsolete -unissued-root rollback assertion; its correction preserves the independent -positive unused-entry and capacity-cleanup controls. No full review credit or -Finalize/native qualification follows from these bounded receipts. - -Additional history controls distinguish COMMIT-request loss from response loss: -all four original checkpoint families remain Absent when COMMIT never reaches -PostgreSQL, without inventing a physical rollback acknowledgement or reopening -the old root. Two probe cases hold or lose the actual ROLLBACK response; a peer -acquires the released job lock before client acknowledgement, and confirmation -publishes only after acknowledgement and cleanup. Two later-admission cases keep -history bound to the original stamped attempt after current identity changes. -Replacing that query join with the current attempt fails exactly those two -controls; all sixteen same-current controls pass. Exact source/mode restoration -passes all eighteen. Both CI Release builds have zero warnings/errors. - -The wider history snapshot passes 2,333 Unit and 179 PostgreSQL cases: 99 -checkpoint, 40 control, 20 business and 20 capacity-admission. An independent -receipt audit verifies all 130 recorded source hashes/modes, exact subjects and -artifact hashes. These app/storage proofs do not exercise successful provider -methods or Finalize; socket-loss cases do not independently inject every disposal -failure. - -The ordinary business completion owner now also carries one conservative -COMMIT budget from its fresh locked SQL observation. Prepare's final plan-stamp -cleanup and transactional reservation-release cleanup consume that interval. -The existing coordinator reaches a synchronous, exact-root wrapper; elapsed -time is checked inside the same run lock as COMMIT admission. One-way publication -states prevent concurrent or duplicate recording from replacing the first -timestamp or interval. No new participant, callback or transaction owner is added. - -Four actual PostgreSQL controls pause the final Npgsql command after successful -SQL/reader cleanup, with no cancellation token or runtime timer closing the run. -Both expired-lease cases fail against the earlier implementation because it -acknowledges COMMIT; both live controls pass. The correction passes all four. -The final publication-state snapshot passes 2,333 Unit and 183 PostgreSQL cases: -103 checkpoint, 40 control, 20 business and 20 capacity-admission, with zero -failures/skips and a CI Release build with zero warnings/errors. Transactional -admission is the production path; Prepare still uses the explicit fixture -admission. These focused checks supply no full Step 7 review-round credit. - -The existing owner-boundary detector now enumerates the exact budget methods, -callers, private publication fields, fresh SQL observations and protected COMMIT -ordering. Its actual-subject and planted-control cases both pass. Controls include -extra callers, deleted capabilities, changed projections, late capture, mutable -budget reset, missing live identity and a plain-CAS bypass. This finite structural -check supplements the actual PostgreSQL expiry controls; it does not prove every -possible value, branch or asynchronous control flow. Full census qualification -and both full Step 7 review rounds remain pending. - -The shared app reader also validates the selected normal attempt, finalization -status and module reason. Its eleven focused cases cover completed policy rows, -sixth-attempt repeatable failures, positive no-start history and all partial-null -selection shapes. Projection-only dirty inputs reject mismatched identity, stamp, -status or reason without altering guarded durable data. An earlier run retained -one fixture failure from waiting for the original deadline instead of the lease; -the corrected helper and expanded matrix pass. The current snapshot passes all -2,333 Unit and 192 PostgreSQL cases: 112 checkpoint, 40 control, 20 business and -20 capacity-admission, with zero failures/skips and a CI Release build with zero -warnings/errors. These are reader/storage proofs, not actual Finalize execution, -successful provider methods or the domain/terminal two-MUST atomicity proof. - -The actual app Finalize path now reads and cleans its selected-input owner before -ordinary root entry, admits a separate counted finalization attempt and constructs -the exact registered typed request. Finalize bypasses capacity admission and -creates no reservation. Its existing business owner rechecks the actual selected -normal facts after the job lock and retains the same monotonic COMMIT budget. -Successful domain failure writes terminal state and its MUST row on that pair; -the private app mint binds the actual returned row, old acquisition token, live -unit/source/announcement and selected policy. The existing bypass mint remains -separate. A duplicate consumed root has no new read or COMMIT history. - -Four actual PostgreSQL cases cover success and permanent/nonrepeatable completed -failure. The first run passes success but refuses the three failure cases with -`42501`: the authored UPDATE unnecessarily names a control-only incomplete flag. -Removing that assignment and requiring the existing false value preserves the -column grants; all four pass. Final assertions bind audit identity, generation, -timestamp, policy and counters to actual stored facts. The corrected snapshot -passes 2,333 Unit and 196 PostgreSQL cases: 116 checkpoint, 40 control, 20 business -and 20 capacity-admission, with zero failures/skips and a CI Release build with -zero warnings/errors. Normal admission, observations and the routing claim remain -explicit fixture setup; app Finalize admission, receipt, read, root, fence and -terminal MUST write are production paths. These cases use an Audit Off root and -do not claim a domain mutation with two MUST rows, native provider execution, -independent witness-substitution coverage or full Step 7 review-round credit. - -The physical-ACK Arm path also retains its original conservative SQL interval. -An actual PostgreSQL control demonstrates that ACK alone previously allowed -provider scope construction after that lease expired, without cancellation or -a native timer; the live control passes. The corrected gate publishes its one -immutable interval only for an issued open boundary. Both the pre-scope check and -the final Execute CAS check elapsed time; the latter runs inside the original run -lock. Premature or late rejected COMMIT calls cannot seed a window for a later -unbudgeted acknowledgement. Known entry expiry reports EntryRefused, preserving -the physical ACK and inventing no provider failure or outcome. - -The corrected snapshot passes 2,335 Unit and 198 PostgreSQL cases: 118 checkpoint, -40 control, 20 business and 20 capacity-admission, with zero failures/skips and -a CI Release build with zero warnings/errors. The unchanged throwing adapter -canary verifies pre-scope refusal; a real held-constructor/provider-method timing -proof remains part of the positive SDK work. Lease renewal does not extend this -retained interval, and repeated history probes do not replace the gate's first -confirmation. These conservative refusals are distinct from permission to execute. - -The separate positive SDK fixture now supplies genuine Contracts, Application and -Infrastructure assemblies, with actual nested Tenancy commands and their MUST -audits. Its adapter calls an independent provider database using a separate, -unprivileged credential. Normal External routing and app admission use the actual -opaque claim, tenant capacity mutex and counted ledger; Finalize uses its separate -real admission. The first routing run exposed an ungranted outcome-body read; -the corrected predicate uses the already granted outcome-kind status instead. -No dispatcher grant is widened. Production definitions remain empty and the -construction-only test host runs no native background worker. - -Eight focused PostgreSQL cases pass: four actual provider outcomes, two exact -audit-INSERT faults and live/expired adapter-constructor barriers. A test-owned -SQL observer records the actual top-level transaction ID, preserving savepoint -semantics; domain state, successful business MUST, terminal state and terminal -MUST share the Finalize transaction. Each injected MUST failure rolls that work -back while prior Prepare/provider facts remain. The existing audit coordinator -may separately record the failed business attempt; this is never a success row. -The initial tuple-`xmin` assertion was invalid across EF savepoints and was -replaced by this observer, without changing production transaction handling. - -The held constructor retains its actual task and scope through release and join. -With the final run-locked Arm-window check removed, the expired case fails and -the real provider journal records an unexpected Execute and effect; its live -control passes. Exact source bytes and mode are restored, then all eight cases -pass again. These cases establish actual provider-method timing and real-store -atomicity, not native handoff, duplicate-provider acceptance or recovery. The -2,335-case Unit run and expanded 247-case PostgreSQL regression pass on the -corrected snapshot, with zero failures/skips and a CI Release build with zero -warnings/errors. The old External-unavailable admission assertion is replaced by -an exact profile/definition mismatch refusal; the genuine SDK flow supplies the -positive External coverage. The broader run retains the existing checkpoint, -control, business, capacity, admission and submission cases. - -The next native-control foundation binds the real External receipt's profile, -normal/finalize stage, counters and selected outcome to its existing execution -owner. Prepare acknowledgement no longer ends lease renewal. Its status-only -renewal probe checks the exact locked job and fresh immutable ledger, before -generic completion shortcuts. Two actual publication/control cases and seven -passive metadata substitutions per case cover both preparing and finalizing. - -The Prepare case starts the real renewal lane and independently observes SQL -lease advancement and a successful rearm of the actual System timer. Restoring -the two old Prepare-ACK guards leaves SQL renewal working but fails that timer -assertion. Exact source/mode restoration passes all ten SDK cases. The frozen -150-source snapshot passes 2,335 Unit and fifty focused PostgreSQL cases (forty -control, ten SDK), with zero failures/skips. An independent receipt audit verifies -all source hashes/modes, artifact hashes and actual TRX subjects. A retained -zero-match run after an initial compile failure supplies no test credit. This -foundation does not yet prove complete native provider handoff or recovery. - -The existing native execution owner now retains the optional Prepare, app read, -Arm, provider and Outcome tasks, with separate exact-family historical probes. -It skips Prepare when admission supplies the existing-plan stage. A normal return -closes that original run; unresolved effects retain reservations for fresh recovery. -An acknowledged Outcome stops renewal even during held cleanup, while actual -cleanup still gates identity release. Finalize remains a separate admission/root. - -Four genuine SDK cases now pass through the real facade, stock bridge and native -worker pools, independent provider journal and fresh Finalize admission. Success, -permanent failure and both nonrepeatable failure/cancellation preserve one normal -and one finalize receipt, one provider Execute, and actual business/terminal MUST -atomicity. The earlier two-case red run reached Prepare but stayed `prepared`, -discriminating the missing native continuation from the explicit-driver proofs. - -A held real adapter constructor exposes the former global short-wrapper timeout. -The existing invocation now owns one monotonic stage timer, armed before each -possible synchronous prefix, and retains every task after wrapper return. Its -finite mapping uses short-root, SQL, external-run and history-probe bounds. Lease -loss, deadline and host stop close/retain before signalling wrapper return; normal -capacity-cleanup cancellation remains separate. Actual timer disposal and private -cancellation callbacks precede source release. Deterministic controls distinguish -an old queued callback from the current stage and forbid refreshing elapsed work. - -The qualified 158-source snapshot passes 2,339 Unit and one hundred PostgreSQL -cases: forty control, twenty-three admission, twenty business and seventeen SDK. -The SDK selection includes all four native results, the long-constructor wait and -host-stop/lease-loss cases that return the wrapper while actual cleanup stays held. -The initial Unit run retained one obsolete host-stop `Running` expectation; its -correction independently counts running plus retained ownership. Removing only -the actual cancellation join fails the held-callback test while its three siblings -pass. Exact source/mode restoration passes all 2,339 again. Builds have zero -warnings/errors; no full Step 7 review or fresh native recovery is claimed. - -The receipt addendum includes the changed host-stop Unit fixture omitted from the -initial 157-path inventory. It preserves the original manifest and distinguishes -the two subsequent Unit-only corrections from unchanged production/PostgreSQL -sources; an independent audit verifies the complete 158-path inventory. - -Four further genuine native cases hold actual COMMIT responses at Prepare, Arm, -Outcome and Finalize. Their clean, exact-family historical confirmation permits -continuation without inventing physical acknowledgement or duplicating provider -work. The Outcome case also handles a real early wakeup while the original -invocation remains retained: a pre-routing identity check avoids acquiring a -routing lease that the same owner must immediately refuse. The initial red run -fails only that Outcome control; the corrected four-case run passes. - -A separate actual Outcome-ACK control holds Activity cleanup after the database -scope has closed. Its gate is acknowledged while the concrete task and invocation -remain retained. The live control lane neither rearms the settled lease timer nor -reports a renewal refusal; actual cleanup still precedes identity release. An -already issued renewal batch may finish. This does not claim zero SQL after ACK -or immediate next-stage service: a consumed early vendor hint can wait for repair. - -The final 160-source snapshot passes all 2,339 Unit and 261 PostgreSQL cases: -118 checkpoint, forty control, twenty business, twenty capacity, twenty-three -admission, eighteen submission and twenty-two genuine SDK cases. There are no -failures/skips; CI Release builds have zero warnings/errors. The snapshot keeps -red/green epochs and the test-only repair-grace reduction separate. Fresh native -recovery, full architecture qualification and both full Step 7 reviews remain -pending. - -Fresh recovery now carries a source-local Stopwatch observation taken before its -actual locked SQL projection. Binding and the final typed Reconcile entry check -the same remaining lease under the Run lock; expiry closes that Run permanently. -Neither binding, cleanup, a held constructor nor a later probe rebases its window. -The original attempt deadline may already have expired; it is not the new lease. - -A genuine SDK live/expired pair first executes against the independent provider, -omits Outcome and then acquires fresh recovery for that exact old attempt. A held -real adapter constructor exposes the missing final check: the red expired case -incorrectly calls Reconcile; the correction prevents that actual method call, -while the live control reconciles the retained effect. No extra Execute, normal -attempt or effect is created. This is an explicitly arranged recovery route, -not native bridge/control recovery qualification. - -Three additional real-socket controls hold the exact recovery probe's completed -ROLLBACK response. A peer can acquire the released row lock before the client ACK, -but no receipt publishes yet. Live ACK/cleanup permits the first binding; a clean -response delayed past the observed lease publishes history but refuses binding. -A lost response publishes nothing; a later clean first probe cannot rewrite its -failure or physical acquisition ACK. Repeated probes retain the same receipt. - -All 2,342 Unit and 145 focused PostgreSQL cases pass with zero failures/skips and -zero-warning/error Release builds. The PostgreSQL selection contains 121 checkpoint -and twenty-four SDK cases. An Integration-only test cleanup correction then joins -the actual probe task using its existing deadline even on failed premises; its -three affected controls pass again. Earlier source epochs are retained separately. -The subsequent recovery-renewal foundation preserves the original ledger token -and expired deadline separately from the fresh recovery token. Its actual SQL -extends only a still-live exact recovery lease; ordinary execution remains capped -by its original deadline. Private passive evidence publishes only after physical -COMMIT acknowledgement and actual cleanup. The Run accepts it under its own lock -only while both windows remain live, without changing the acquisition receipt or -resetting provider entry. Observing expiry closes the Run and current checkpoint. - -The actual expired-original case first fails against the old execution-only SQL. -Four genuine SDK controls then pass: a two-tenant mixed renewal batch, lost renewal -ACK without evidence publication, and timely/late evidence application around a -held real Reconcile constructor. Timely application permits one Reconcile after -the old window expires; late application cannot reopen it. These are delayed -applications of already acknowledged evidence, not held successful network ACKs. -Fourteen memory identity substitutions and separate binding/process/stop/order -controls exercise the acceptance boundary without claiming SQL provenance. - -The frozen 164-source foundation passes 2,361 Unit and 189 focused PostgreSQL -cases with zero failures/skips and zero-warning/error Release builds. The latter -contains 121 checkpoint, forty control and twenty-eight SDK cases, including the -four renewal controls. A lost ACK's later status probe proves the recovery row's -renewal without publishing usable evidence; the ordinary mixed row is independently -checked in the direct-ACK case. Native renewal consumption, actual cleanup-fault -injection, native recovery handoff and retry/quarantine/finalizer failure routing -remain pending, as do both full Step 7 review rounds. - -The native recovery owner now roots acquisition, exact historical confirmation, -app read, Reconcile and checkpoint tasks before issuance, without fabricating an -ordinary admission. Its fresh lease survives the expired original deadline; -actual renewal evidence feeds the existing Run boundary. Two genuine SDK controls -exercise direct/lost acquisition ACK and renewal across the first recovery window. -They arrange parking explicitly and do not qualify automatic scheduling. - -NoStart's lost app COMMIT ACK now uses its exact history family. Real timer -construction/Change controls hold the actual call while host stop closes permission; -returned handles require actual disposal, while unreturned failed initialization -retains ownership. Renewal keeps its old expiry visible during Change, and Join -awaits the actual update before disposal. A clean late return can decline renewal -without inventing failed cleanup. Held-stop controls do not prove autonomous expiry -at a shorter deadline during an arbitrarily blocked supplied Change. - -The frozen 167-source correction passes 2,362 Unit and 280 PostgreSQL cases: -121 checkpoint, forty control, twenty business, twenty capacity, twenty-three -admission, eighteen submission and thirty-eight SDK cases. There are zero -failures/skips; Release builds have zero warnings/errors. The new Change controls -first fail at the actual blocked stop/late identity boundaries, then pass after -correction. Earlier constructor/history and known-fault native epochs remain -separate. Automatic park/bridge/disposition and both full Step 7 reviews remain -pending. - -The next automatic-recovery slice adds two bounded control selections for expired -external owners and retained unarmed recovery rows. A single eligibility cycle -arms a finite probe and advances the wake generation once; stock handoff/repair -retains that generation, the original normal attempt and its reservation. A -forward migration and canonical DDL guard live-owner clearing, unarmed/reset -transitions and unsafe downgrade. Five actual SDK controls plus canonical-schema -parity pass, including an automatic facade recovery and both pending routing -stages. This does not qualify every future-due, exhausted, contention or planner -case. - -Its broader frozen 172-source run passes 493 of 494 PostgreSQL cases and exposes -one native lost-Outcome-ACK history failure: a competing row lock legitimately -returns a clean unavailable result. The correction retries only that exact clean -unavailable history read, after actual cleanup, inside the already armed single -history budget. It never treats unavailability as confirmation or resets the -original origin. A separate real transaction holds the exact job lock; the socket -observer ties the actual binary UUID/query to PostgreSQL's zero-row response. -That causal control first fails at the missing history value and then passes. -Seven focused history controls and all 2,362 Unit cases pass with zero skips and -zero-warning/error Release builds. The broader failed run remains a failed -receipt; these narrower passing controls do not imply a fresh full regression. - -The application-source inventory now includes external invocation owners alongside -transactional owners. Its job-only floor is 22 by default and 118 at the maximum -business-pool topology; unrelated arrival headroom stays separate. The shared -privileged inventory remains 50/156 because each invocation's routing, recovery -acquisition, confirmation and history operations are sequential and cleanup-owned. -The maxima need separate calculations: the qualified eight-pool/four-worker -facade fixture has privileged 156 and application 32, without claiming that -every topology reaching privileged 156 has the same application floor. - -The new count/kind and immutable 21/22 startup controls first fail against the -transactional-only calculation. After correction, 15 actual PostgreSQL cases -and all 2,365 Unit cases pass with zero skips and zero-warning/error builds. -Actual main/auxiliary connections fill 22/118 pools, with explicit zero/two -unrelated headroom controls; four native normal SDK cases and automatic recovery -use pooled application 22/privileged 50. These controls do not claim held external -versus transactional native contention or maximum-topology native execution. - -Retained completed facts now have a recovery-only app selection mode. Its actual -trusted read supplies plan/operation identity; no caller supplies a replacement -report, payload, policy or quiescence fact. The handler re-reads canonical stored -facts under the job lock and applies their policy. Missing facts and early -repeatable outcomes are refused by both driver and actual handler; selection -never rewrites outcome, quiescence, NoStart or reservation-release stamps. - -An existing marker alone no longer confirms a selection-only transaction. -Outcome history requires the exact policy-derived selected normal attempt, -status, reason and plan stamp; prepared-plan NoStart at six likewise requires its -exhaustion selection. Actual request-loss controls first expose both false -confirmations, then pass after correction. Actual response loss confirms the -selection while keeping physical ACK false, including after a distinct counted -Finalize admission advances the current header. - -The native recovery owner consumes those retained facts through the same held -app checkpoint task and commit budget. A genuine SDK control first remains -Reconciling against the old early-return branch, then reaches completion after -the correction without another provider scope, Reconcile or Execute. Its peer -with absent Outcome still performs one Reconcile. Thirteen focused PostgreSQL -cases and all 2,365 Unit cases pass with zero skips; the broader checkpoint/SDK/ -control regression is still pending at this receipt. This delivers selection, -not early-repeatable retry disposition, probe/quarantine or finalizer-fault policy. - -That subsequent run executes 217 PostgreSQL cases: 216 pass and one native -nonrepeatable case remains FinalizePending at its fixed twenty-second assertion. -Its saved receipt contains no ownership/handoff snapshot, so its exact cause is -not retrospectively established. The source permits a successor hint to finish -while the old acknowledged Outcome still owns actual cleanup; the default -sixty-second repair grace exceeds that test's former wait. - -Two causal controls, for success and nonrepeatable failure, now hold the actual -Outcome Activity cleanup. They observe the exact new-generation persisted vendor -hint as Succeeded, cleared bridge/ownership fields and a future database-time -handoff check while the old task is incomplete and routing is refused. Releasing -the real cleanup permits same-generation repair and one Finalize, with unchanged -normal count and independent provider counts. The NativeFlow fixture uses the -accepted fifteen-second repair minimum and a wait derived from repair grace plus -Finalize transaction/SQL budgets. Both causal cases and all four native flow -cases pass together. The complete forty-six-case SDK regression then passes -with zero skips and zero-warning/error builds. Only the two SDK test files -changed; production and all other frozen sources remain byte-preserved. Earlier -132 checkpoint and forty control passes, plus 2,365 Unit passes, stay tied to -their unchanged-production epoch; this is not a fresh 218-case run. The failed -217-case receipt stays distinct, and both full Step 7 reviews remain pending. - -Known-fact retry now accepts only a closed original-completed or fresh-recovery -identity. Under the actual job lock, its status-only read validates every normal -ordinal and positive NoStart/release or repeatable completed-outcome/quiescence -history. The current original admission token, deadline, scope and generation -remain distinct from a fresh recovery token. Missing or unresolved facts cannot -return work to Pending. - -For a live original owner, lease shortening, private nonexecuting recovery handoff -and fixed-backoff Pending selection share one transaction. Only the final returned -row permits COMMIT; refusal rolls back the intermediate ownership too. A fresh -recovery owner uses its live lease independently of the expired original deadline. -Scheduling advances one generation without adding an attempt, rewriting evidence -or starting provider work. The uncertainty descriptor retains the actual returned -schedule. Its locked probe distinguishes the exact old rollback shape, committed -same-cycle routing and a distinct later admission; no generic rollback fallback -or executable receipt is used. - -The native owner retains the actual disposition and optional confirmation tasks -through cleanup. It issues them only after a clean acknowledged or exactly -confirmed app checkpoint; retained known recovery facts need no new provider report. -A focused source review removed an unnecessary recovery-side control call after -final-selecting outcomes. Twenty-eight real PostgreSQL cases pass after that -correction, with zero skips and zero-warning/error Release builds. The twenty-one -store cases cover all five backoffs, real COMMIT request/response loss, subsequent -routing/admission, unresolved/nonrepeatable refusals, final-UPDATE rollback and -positive no-plan NoStart after actual original-deadline expiry. - -Seven actual SDK/native cases cover Failed/Cancelled original retry with normal -or lost Outcome ACK, plus recovery from retained facts, Reconcile and absent -ExecuteIntent. Held actual writer cleanup forbids early disposition issuance; -lost ACK requires its exact clean history confirmation. The subsequent counted -attempt preserves the plan/operation, reacquires capacity and performs its own -Execute before one fresh Finalize. Independent provider counts and domain rows -distinguish that progress from another Prepare, duplicate effect or invented -quiescence. The broader current regression then passes all 246 cases: 153 -checkpoint, fifty-three SDK and forty control cases. All 2,365 Unit cases also -pass on the same frozen source with zero skips and zero-warning/error builds. -The twenty-eight focused cases are included in that broader result. This is a -fresh passing run, not a reinterpretation of the earlier failed 217-case receipt; -neither full Step 7 review round is closed by these tests. - -The next bounded status slice validates unresolved ExecuteIntent under the same -exact normal identity and complete positive prior history. Running preserves the -unsuccessful-probe count; explicit failed probes increment once. The sixth failure -or a still-unresolved deadline/grace boundary quarantines without inventing an -outcome, releasing occupancy or admitting another normal attempt. Private lease -shortening and paced parking remain atomic behind the existing expiry-only wake -guard. Actual returned generation, counter, schedule and quarantine reason bind -the separate lost-COMMIT history probe. - -Thirty-five focused PostgreSQL cases pass with zero skips: twenty-two new store -cases and thirteen existing filter matches. They cover the six-probe boundary, -Running between failures, retained occupancy, known-fact and stale-owner refusal, -actual deadline/grace, request/response COMMIT loss, changed ownership and an -injected final-park rollback. A fault followed by a repeatable outcome preserves -the count through Pending; only the next real counted admission resets it. -The initial fixture attempted to move an unowned probe schedule and was correctly -refused by the existing guard. Its failed receipt remains separate; the corrected -tests wait for the actual due time and leave that production guard intact. -Independent source/artifact inspection closes this store slice only. Native -timeout/report/callback qualification and durable quarantine-health observation -are still in progress; neither is claimed by these store cases. - -The subsequent native regression executes 275 PostgreSQL cases: 273 pass and -two fail, with zero skips. Both failures record the only Reconcile timer callback -arriving before its owned monotonic deadline, by 1.288 ms and 1.200 ms. Discarding -that callback loses the future wake. A preliminary 1 ms tolerance therefore -does not qualify this path; its failed receipt is preserved separately. All -2,377 Unit cases passed at that same source, demonstrating the missing combined -timing coverage rather than disproving the native failures. - -The correction restores actual elapsed-time checks and gives an early wake one -supplementary timer and one task under the existing invocation. That observer -alone rearms and asynchronously disposes its timer; stage changes and closure -signal it without calling timer operations under the state lock. Actual observer, -timer and cancellation cleanup precede private-source release. Twenty-three -focused Unit cases pass, including repeated early wakes, successor changes, -held timer construction/change/disposal and refused/faulted timer operations. -An additional nanosecond-clock control rejects premature expiry caused by -TimeSpan conversion. The current source then passes all 2,385 Unit cases and -all 275 PostgreSQL cases: 175 checkpoint, sixty SDK and forty control cases, -with zero skips and zero-warning/error builds. The actual late-report tests -assert preserved state and original job/attempt/operation identity. The earlier -failed receipt remains separate. This adds no database connection, executable -authority or full Step 7 review credit; it does not qualify the later durable -health slice or remaining terminal/finalization policies. - -Durable quarantine health now uses a forward partial index and one status-only -read on the existing serial control lane. Acknowledged read rollback and actual -cleanup precede cache publication. Failed refresh retains the last good value -with an independent fault; unknown or stale samples cannot report healthy. -Snapshot cadence remains valid even when it exceeds the separate progress bound. -Health getters issue no SQL and do not become admission gates. - -All 2,391 Unit cases pass, including six new memory/freshness controls. Eleven -focused PostgreSQL cases also pass with zero skips and zero-warning/error builds: -six control observations, three schema/canonical/reversal cases and two genuine -native quarantine flows. The latter waits until quarantine is the only health -fault; a fresh host, source, gate and runtime start with no cached sample and -independently observe the retained quarantine. They preserve occupancy and the -single normal admission without another Execute. The normal planner uses the -partial index against six thousand future rows; dropping it makes the same -detector expose the backlog scan. These focused results close no full review round. - -The subsequent control/SDK/facade/storage regression executes 332 cases: 328 -pass and four fail, with zero skips. Two historical recovery-migration tests -incorrectly include a later index migration in their refused-downgrade inventory; -EF commits each successful migration separately. They are corrected to qualify -the recovery migration at its own boundary without weakening the full inventory -comparison. One retained-outcome recovery case remains FinalizePending at a -thirty-second assertion despite its sixty-second repair setting; its original -cause is not established by that receipt. A separate facade case passes actual -cleanup and zero retained-owner assertions, then times out awaiting a follow-on -job. Controlled recovery-cleanup coverage and follow-on scheduling diagnostics -are in progress; the four failures are not credited as passing qualification. - -The test-only correction run then passes nine PostgreSQL cases with zero skips -and a zero-warning/error build. It covers both historical migration modes, both -native recovery modes, both original held-Outcome cases, a new genuine stored -recovery selection with held real cleanup and same-generation repair, and both -auxiliary-cleanup modes. Production is unchanged from the preceding 332-case -epoch. The diagnostic-only facade rerun does not establish the original -follow-on timeout's cause; a source-reachable test-fixture collision between -the old job's legitimate retry and the new job is being tested separately. - -The controlled old-retry-before-new-job experiment fails with the original -call-count mapping. Exact job-id mapping alone still fails: the two fixture -UUIDv7 ids also share the timestamp-only twelve-character slug prefix. Actual -handler diagnostics show the new job's `business_rule_violation`, independently -of clean source/owner release. The corrected fixture maps resources by actual -`JobTenantContext.JobId` and uses the full UUID in each slug. Two distinct ids -are deliberately generated at the same timestamp; the old retry commits first -without consuming the independent job's resource, and the new job completes -in one admission. Both clean and dirty auxiliary-cleanup cases pass with zero -skips and a zero-warning/error build. These constructed controls explain and -remove both fixture collision classes, without retrospectively assigning the -earlier receipt a cause its saved observations did not capture. - -The no-plan terminal foundation now persists an exact finite request before -app NoStart, reservation release or terminal audit. Its fresh locked read checks -every normal admission and positive prior plan-free NoStart/release; committed -plans, effects and finalization are excluded. Its dedicated lost-COMMIT probe -binds the requested reason and immutable admission identity, preserving physical -ACK separately from history confirmation. Actual permanent Prepare refusal at -one/six, sixth recovery exhaustion, request/response loss, committed-plan and -expired-owner controls pass: seven PostgreSQL cases and all 2,391 Unit cases, -zero skips and zero-warning/error builds. This is the request/history primitive; -terminal-purpose app cleanup, stronger terminal storage guards, native routing -and final terminal audit integration remain pending and are not activated here. - -The terminal-purpose cleanup foundation adds a fresh, immutable -`TerminalNoStart` recovery receipt. It grants only app-role NoStart and exact -reservation release; it cannot enter Prepare, Execute, Reconcile, ordinary -renewal or finalization. The app reads the actual causal envelope without -constructing module parameters or requiring an Active definition, then checks -complete normal history under the row lock. NoStart and `never_started` release -commit atomically. A purpose/reason-bound history probe preserves the original -physical ACK separately. All 2,396 Unit cases and thirteen focused PostgreSQL -cases pass with zero skips and zero-warning/error builds, including first/sixth -admissions, absent current definitions, acquisition/checkpoint COMMIT request -and response loss, and a reservation CHECK refusal after the marker UPDATE. -The initial failed fixture assertions remain separate receipts; the corrected -Unit descriptor preserves the production probe's strict phase/reason check. -The broader checkpoint/recovery regression then passes all 196 PostgreSQL cases -with zero skips, including those thirteen focused cases. This foundation does -not activate the native terminal lane, terminal audit or stronger terminal -storage guards. - -The forward terminal-history migration freezes a non-NULL request reason and -requires complete positive no-plan history before the first dead-letter write. -It preserves the existing app NoStart/release guards, grants and four-role -boundary. Its initial eighteen-case run passes twelve and fails six: five -expose an ungranted payload-column read in the new guard, and one exposes a -dirty-control fixture that removed existing owner-clearing housekeeping. The -correction uses only permitted outcome metadata and restores the actual prior -function for dirty controls. The corrected build has zero warnings/errors and -all 217 PostgreSQL cases pass with zero skips, including canonical DDL parity, -exact prior-function Down/reapply, first/sixth actual NoStart, malformed prior -history, immutable reason and unadmitted retirement controls. A bounded reviewer -verifies both fixes and finds no further defect; this is no full review-round -credit and does not activate the terminal worker or its audit path. - -#### Native terminal and finalizer policy qualification (2026-10-17) - -The existing terminal lane now owns actual app NoStart cleanup independently of -ordinary terminal SQL. Its main/auxiliary application-source pair raises the -current application-pool floor to 24 and maximum supported floor to 120. Earlier -22/118 receipts above retain their historical meaning. A speculative empty -cleanup lookup does not increment pending outcomes. Stop joins the actual task, -scope and callback; an expired lease never substitutes for cleanup evidence. - -The prepared terminal path retains plan, operation and selected outcome metadata. -Its existing witness has a prepared 40-column returned projection alongside the -unchanged NoPlan 13-column and app 37-column projections. A private-constructed -24-column prepared acquisition carries the exact additional metadata. The -forward migration requires positive complete history before stamping incomplete -business finalization; its Down restores the exact prior transition function. -Audit failure rolls back both terminal completion and the incomplete flag. - -Actual native tests verify permanent Prepare refusal, sixth NoPlan recovery and -an already-recorded NoStart, including real cleanup-lease expiry and exactly one -MUST audit. Native Finalize tests roll back a nested business write, then admit a -fresh Finalize without rerunning the provider. PostgreSQL transaction identity -is captured while live: Npgsql can recycle its transaction object, so object -reference inequality was an invalid initial test premise. The corrected first -qualification passes sixteen PostgreSQL cases with zero skips. - -A later execution deadline could discard an already-classified, positively -cleaned Permanent Prepare or Finalize result. Both now retain that actual result -in the existing bounded control queue; status accounting can outlive execution -permission without reopening app/provider entry. Native timer-disposal barriers -verify this window, host-stop refusal and actual handler cancellation returning -RetainOwnership. Unknown status COMMIT permits only exact historical probes -until rollback is established. Changed ownership ends the old authority without -claiming its COMMIT succeeded. Retained terminal and finalizer history dispatch -precedes generic probe interpretation, including copied-boundary refusals. - -The expanded PostgreSQL qualification passes 214 of 216 cases; two planted-history -fixtures incorrectly ask the restored transition guard to accept damaged history -while expiring scheduling ownership. Correcting only that setup makes both pass. -The subsequent 42-case run passes 41; its remaining new foreign-owner fixture -incorrectly moves an already-expired lease forward. The corrected final focused -run passes fourteen cases with zero skips, including that refusal and a selected -external failure followed by six real Finalize admissions, all five backoffs and -one honest terminal MUST. Explicit fixture eligibility avoids waiting over an -hour; these are not six native delayed wakeups. The production source also has -2,396 passing Unit cases. All qualifying Release CI builds have zero warnings -or errors; initial migration/import build mistakes remain separate receipts. - -The first complete architecture run passes 304 of 330 cases and fails 26. Exact -caller/signature/owner guards require alignment with the new external paths; -their nonempty subjects and planted violations remain required. This is a -recorded failing self-check, not completed architecture qualification or either -full review round. - -Uninvokable cleanup and request routing are implemented without requiring an -Active definition or reconstructing module parameters. The candidate selector -proves positive cleanup history before its bounded page; unresolved earlier -rows cannot consume that page. Historical request probes retain their original -identity, compare selected timestamps independently of session time zone and -reject mixed specialized histories. A forward migration extends only the -positive NoPlan terminal reasons; prepared finalization guards stay unchanged. - -The first foundation builds with zero warnings/errors and passes twenty-eight -existing PostgreSQL terminal-history cases. The subsequent 257-source checkpoint -passes all twenty-one dedicated uninvokable/invalid-envelope cases and the real -native application-source contention case. Its 272-case PostgreSQL run passes -271 cases and fails one index-name assertion: the normal planner legitimately -chooses the newly added matching retirement index for a pending query. All four -actual control-query plan cases, canonical DDL parity and full schema -rollback/reapplication pass. The assertion correction permits only that known -pending/retirement pair, retaining the cutoff, scan-bound and removed-index -controls. Its focused correction run passes all thirty-two PostgreSQL cases, -including the twenty-one uninvokable cases, all four actual control-query plans, -the five ordinary eligibility/index-removal cases and canonical/full-rollback -parity. - -At that same source checkpoint, Unit passes 2,396 cases, Contract four and -Docker-free HTTP integration 176, all without skips. Architecture qualification -runs all 333 cases in two complementary groups: 326 pass and seven fail. The -failures expose stale exact-owner expectations, missing recovery-minter census -coverage, a Cecil mutation-restoration error, a composed table projection and -the published method count. All 1,074 external orchestration dirty/restoration -controls pass. The first correction run passes five architecture cases, including -the exact owner/minter baselines, terminal mutation controls, literal-SQL guard -and corrected count. Expanded minter mutation qualification then passes; the -owner mutation test exposes a further missing multiplicity check between the -two identical external budget projections. Requiring both exact occurrences -closes that false-pass control without removing either mutation. - -The next correction build has zero warnings/errors and Unit again passes all -2,396 cases. Both orchestration facts pass in 4m53s, including all 1,074 external -dirty/restoration controls. The authority and owner group passes three cases in -6m16s, including the corrected budget mutations. Detector-local target-name and -identity indexes preserve fresh baseline/dirty/restored scans; detached targets -remain explicit offenders. These durations are receipts, not a controlled speedup -measurement or evidence that the complete CI backend job fits twenty minutes. -Step 9 retains that complete-job qualification. The first two helper analyzer -warnings and all seven original architecture failures are closed by focused -corrections; the original failed full run remains a separate receipt. - -Commit preparation identifies whitespace/encoding-only corrections in fifty -changed files. They are applied after all running tests stop; final format/build -and representative post-format checks then pass. The complete solution verifies -format without changing any of its 1,268 files, and Release builds with zero -warnings/errors. Post-format Unit passes 2,396 cases, Contract four, architecture -seven and PostgreSQL thirty-three, including the native application-source -contention case. The normal nonempty/zero-skip TRX guard verifies all four test -assemblies. The 258-source SHA-256/mode manifest closes at -`b9187ae8e90976f7b974171cb1563c5b3a4df57e070809f845f3d040678600be`. -No complete current-head suite, PR/CI success or full review-round credit is -claimed. The changed-document audit passes 1,377 relative links and 423 fragments; -all seven ADR parser controls pass. - -The remaining Step 7 checkpoints are explicit: - -| Checkpoint | Current state | -|------------|---------------| -| External stages, durable policy, reconciliation and native terminal/finalizer paths | Implemented; earlier focused receipts above record their source-specific qualification | -| Uninvokable retirement/invalid-envelope cleanup and candidate progress | Implemented; twenty-one dedicated cases, actual retirement-index seek and corrected alternate-index assertions pass | -| Native application-source contention | Genuine contention regression passes with the provider task retained and an unrelated transactional job completing at the application-source floor | -| Complete exact census and relevant backend regression | Focused implementation qualification and correction checks pass; full packet regression/CI remain Step 9 | -| Step commit and two fresh full review rounds | Implementation committed as `6e90a52f`; both full review rounds and verified corrections complete; the round-2 correction and closeout share this commit | - -Both full Step 7 reviews and their verified corrections are complete. -All nineteen packet obligations remain Registered; no -production business definition is added. Steps 8–9 and real PR/CI closeout remain pending. - -#### Step 7 full review round 1 (2026-10-17) - -Implementation commit `6e90a52f` passes normal hooks and leaves a clean tree. -Three fresh independent reviewers inspect the complete Step 7 range from -`0ea50b15`: GPT-6-astra at xhigh for runtime/authority, and two GPT-6.1-sol -reviewers at xhigh for storage/isolation/audit and proofs/composition/corpus. -These are full source reviews, distinct from the earlier slice preflights; -reviewers run no toolchain and supply no additional runtime or CI receipts. - -The unique findings are external capacity deferral, the terminal NoStart -candidate cutoff, and required provider-causality qualification. The runtime -review independently corroborates the capacity and causality findings, with -no additional verified runtime defect. No new tenant/org isolation, privilege, -policy, release or terminal-audit atomicity defect is established. - -External normal admission correctly refuses a full capacity group without -inserting an attempt or reservation. Its shared control disposition still -accepts only the transactional profile, silently leaving the external routing -lease. A real app-admission/native-control regression fails the unchanged -implementation at that retained routing owner. The correction admits the two -ordinary profiles through the same exact pending/routing/token/generation/live -lease fences; finalizer admission remains separate. The corrected real-path -case passes, including the recorded five-second wait, genuine provider/Outcome -release, new admission before the old lease expires, and stale-token refusal. -The twenty-one related PostgreSQL cases and all 2,396 Unit cases also pass with -zero skips and a zero-warning/error Release build. The original red receipt -remains separate; these focused checks are not a complete packet rerun. -A separate source inspection finds no actionable issue in this correction; -it supplies no second-full-review or complete native handoff credit. - -The terminal NoStart candidate query used a volatile cutoff where selection -requires a stable statement timestamp. A real migrated-schema regression seeds -6,000 future terminal audit-backoff subjects with guarded NoStart/release history -and 6,000 unrelated occupied subjects. The original query fails its stable-range -assertion and records 36,000 loop-weighted plan-row visits, not distinct rows. -Stable cutoffs alone still fail the one-due-page work bound: a flattened -reservation EXISTS scans unrelated reservations. A local zero-offset fence keeps -that probe correlated to each due candidate. Full positive history remains before -LIMIT, and fresh post-lock authority checks remain unchanged. - -The exact corrected query passes both idle/one-due cardinalities, the stable -index condition and fewer than 256 loop-weighted visits. Changing only its -available-after cutoff back to the volatile clock exposes the large idle scan. -All thirty-eight selected PostgreSQL cases, including existing control-query -plans and terminal/history controls, pass with zero skips; three architecture -checks pass and Release builds have zero warnings/errors. The first stable run's -integer-only EXPLAIN JSON parser failure is retained separately and corrected to -accept PostgreSQL's numeric row counts. The actual stable-only failures and their -plan remain separate receipts; no measured timeout, forced planner option or -new index/grant is claimed. Independent correction inspection finds no actionable -issue and supplies no second-full-review credit. -The existing provider tests preselected cancellation policy; they did not prove -an actual runtime cancellation becoming a durable Cancelled report and surviving -fresh-host Reconcile. Three new native cases now pass. An actually accepted -Running operation honors the private runtime token and commits Cancelled with -positive provider fencing in its independent database. Its stopped original -owner joins without writing Outcome or releasing occupancy. A fresh host/source/ -Run with no original probe reconciles the same job/operation/attempt/deadline, -checkpoints its exact policy/evidence, releases capacity and commits domain -finalization with both MUST audits. - -The companion permanently fails and durably closes its provider fence before -stop, while holding only the response across stop; fresh recovery preserves that -independent meaning. A third, explicitly dirty adapter changes only a genuine -Cancelled Reconcile report to Failed/Permanent. It leaves the provider journal -unchanged, actually reaches the wrong persisted result, and is rejected by the -same semantic assertion used by the clean companions. This proves adapter -qualification, not generic runtime certification of external causality. - -Independent source inspection finds no actionable issue in the correction design. -The three actual native cases, all 2,396 Unit cases and four Contract cases pass -with zero skips and a zero-warning/error Release build. The initial three analyzer -warnings are corrected by explicitly awaiting provider-owned cleanup independently -of its already-cancelled input. The remaining seventy-one provider/SDK cases -also pass in 8m46s. Together the two disjoint filters execute all seventy-four -cases in that class, including genuine native, lost-reply/ACK, recovery, retry, -finalizer, cancellation/cleanup and source-contention controls. Four architecture -checks pass. The normal runner guard verifies nonempty execution and zero skips -in all four assemblies; its initial suffix-only invocation is retained as an -invocation failure, separately from the passing full-assembly-name invocation. - -Format verification changes zero files. The seven-document audit passes all -1,377 relative links and 423 fragments. The final 261-source SHA-256/mode manifest -closes at `b1404b39d54434ba1fa3233bbe9fb742cc856d828139406d61a6ed11f9df005c`; -the corrected runner invocation has its own receipt without rewriting that manifest. -Capacity and candidate-scan fixes are committed as `ef3cf7b4` and `1ef18e64`. -This correction closes the three verified first-round findings; the second fresh -full review remains pending. No complete current-head backend/CI run or packet -obligation promotion is claimed; Steps 8–9 and the full closure gate remain open. - -#### Step 7 full review round 2 (2026-10-17) - -Three fresh independent reviewers inspect the complete Step 7 range -`0ea50b15..d0eb7596`: GPT-6-astra xhigh covers runtime/authority and a second -GPT-6-astra xhigh covers storage/security/audit; GPT-6.1-sol xhigh covers -proofs/composition/corpus. Runtime and storage report no actionable findings. -The proof review identifies one required coverage gap and one minor live-standard -correction. These are full reviews, distinct from earlier narrow inspections. - -The genuine provider recovery tests did not exercise Failed/TransientNotRepeatable -or Cancelled/TransientRepeatable through Reconcile. The existing recovery theory -now retains its three cases and adds those two; no Fact/Theory method or catalogue -count is added. Original Execute returns a completed report without an exception, -but its application Outcome is deliberately absent. Fresh native recovery reads -the same independent provider attempt before any later execution. - -An actual acknowledged recovered Outcome holds its cleanup before disposition. -App-role assertions bind state, policy, operation, fingerprint, evidence and atomic -quiescent release to the original provider journal. Repeatable cancellation has -no premature failure selection and later spends a distinct normal admission on -the same operation. Nonrepeatable failure commits its ordinary failure finalizer -and exact `external_retry_forbidden` MUST audit without another Execute. Both -new cases and all seven existing retry/recovery/ACK cases pass: nine cases, zero -failures/skips, with a zero-warning/error Release build. - -A temporary Reconcile-only adapter mutation maps the two policies to different -valid policies while leaving provider storage unchanged. Exactly the two new -cases fail at the same stored-policy comparison; the three existing recovery -controls pass. This is an executed adapter-protocol negative control, not runtime -certification of provider truth. The exact fixture bytes and mode are restored -and independently verified against the clean 261-source snapshot. The restored -Release build has zero warnings/errors; its five-case native rerun passes with -zero failures/skips in 1m33s. The restored-source manifest closes at -`33ba204ead511e91fa7f0ad7c63394e07e5fa894874b5d0df14e5290f2ea46db`. - -The live Infrastructure standard now describes the actual stage-specific wait -switch and correct completed Step 6 review status. Independent narrow inspection -finds no remaining issue in the correction or the actual clean/dirty receipts. -The initial clean source manifest closes at -`3654d96f7cb27241deeb049fbe05e8476211bff20ba54828778617ff220ec6e6`; -the separate expected-failure mutant receipt closes at -`2d6ace0de47a4babd374a605e2e6fd5cc11cd7865f5f19039d63320b8159312b`. - -A fresh complete Architecture run on the frozen `d0eb7596` source passes all -333 cases with zero failures/skips in 30m41s; its 261-source manifest closes at -`bc2936a69e07c77c23afb684d7f225f9b192199f0f9e7bbd6f825bdd4200c9ad`. -This includes the earlier seven corrected controls and preserves their original -failing receipts. It precedes the test-only policy extension; it is not a complete -current-head backend/CI receipt. Step 9 still owns CI-duration qualification and -full packet regression. All nineteen obligations remain Registered. The round-2 -correction commit closes Step 7 after both full reviews and verified corrections; -Step 8 follows under the already Accepted plan. No new maintainer decision is pending. - -### P02b-4 Step 8 — durable recurrence and restricted fan-out (2026-10-18) - -**Locally complete after both full review rounds and verified corrections.** -The [round-2 closeout](#step-8-full-review-round-2-2026-10-18) owns final evidence. -Step 7 closes at `69405b16` after both full -independent review rounds and verified corrections. Accepted ADR-0047 authorizes -this step on `development`; no new decision is pending. - -The implementation is organized into three closure units within the unchanged -approved Step 8. They do not replace the implementation commit and two fresh full -review rounds required before Step 9: - -- Frozen monotonic manifests, UTC slots, coalescing and bounded lifecycle pages. -- Actual-row recipient admission, scope recheck and atomic child/recipient receipt. -- Owned runtime/tick integration, fairness, capacity and complete fault proofs. - -The first foundation adds idempotent manifest registration and one locked -materialization quantum. Two actual sources converge; obsolete or conflicting -revisions cannot overwrite the accepted manifest. Historical slots retain their -stored target/policy; a newer manifest cannot be materialized by an older binary. -CoalesceLatest atomically advances to the slot after the latest due occurrence. -Future slots enter the index only when due. Pending/unknown targets defer without -advancing and yield to healthy work. A denied occurrence INSERT rolls back both -occurrence and manifest progress; restoring the narrow grant permits a clean retry. - -The focused foundation Release build has zero warnings/errors. Thirteen existing -recurrence Unit cases pass; the extended PostgreSQL class passes eight cases and -the production authority census passes one, all with zero failures/skips. Its -266-source hash/mode receipt closes at -`09aa9ca0275c531b65d11851a3674788762a8571c499a772e5140fcb62b765d1`. -An initial missing test-helper compilation failure remains a separate receipt; -no tests are credited to that failed build. These focused checks do not qualify -the remaining fan-out/runtime surface or either full Step 8 review round. No -production recurrence or business definition is added; nineteen obligations -remain Registered. - -#### Lifecycle pages and foundation preflight - -Tenancy declares the status meanings as closed metadata. Its additive migration -grants exactly eight SELECT columns; real dispatcher connections reject names, -wider reads and tenancy writes. Raw tenant/organization pages bound examined keys -before eligibility filtering. Frozen upper keys and recipient INSERTs advance in -one transaction; denied INSERT controls leave neither bounds nor progress behind. -The actual tenant query seeks past a 6,000-row ineligible prefix in a 12,000-row -fixture without rescanning it. This is a raw-key eligibility sweep, not an MVCC -snapshot cohort. No organization query-plan result is inferred from that test. - -Two planted same-revision manifest conflicts initially fail at the semantic -materialization assertions. Both materializers now require the exact local hash -when the revisions match, while preserving supported historical targets under a -newer local manifest. Both cases pass in the restored clean run. - -Two independent foundation preflights inspect runtime/isolation and proof/corpus -surfaces. Runtime has no verified finding. Proof review identifies that executing -the canonical grant block after applying the migration cannot detect an omitted -grant. The corrected test starts from a verified empty lifecycle ACL, proves the -same exact-budget assertion rejects a missing required column, then runs the -unaltered canonical block from an empty ACL and verifies its complete budget. -These are bounded preflights, not either full Step 8 review round. - -The 275-source pre-correction receipt passes 35 PostgreSQL cases and both the -positive and planted-violation authority cases, with zero failures/skips. It closes -at `43873ad1a6b7c95bb578b4da04d2db8b7a6818e12be89236a50c949a977863e4`. -After the proof correction and formatting, the Release build has zero warnings/ -errors; 35 PostgreSQL cases, all 2,396 Unit cases and the positive authority case -pass with zero failures/skips. That 275-source receipt closes at -`04894512bcfe8c444a82a5f16b956dd2c8e217d16146f4b88f860f842aa65b6c`. -Earlier compilation failures and the two meaningful conflict failures remain -separate receipts. These checks do not claim full packet regression or CI success. -Restricted child admission and owned runtime/tick integration remain within this -same Step 8, before its implementation/review closeout. - -#### Recipient acquisition continuation - -Foundation commit `69c3998a` preserves the preceding qualification and bounded -preflight correction. Normal hooks leave all 275 validated source hashes/modes -unchanged. Restricted recipient acquisition is the next unit, not a new step. - -The actual locked recipient now yields an opaque single-use claim containing its -stored occurrence, route, manifest, target and fresh acquisition. The compatible -registered manifest supplies its declaration Type; no stored CLR name is resolved. -Publication requires positive claim COMMIT acknowledgement, actual cleanup and a -conservative remaining lease interval. Pending, unknown and same-revision -conflicting binaries defer without publishing authority. Two independent sources -cannot issue one live route twice; a competing application row lock is skipped. -Acquisition itself creates no child or business execution. - -The 278-source qualification passes a zero-warning/error Release build, 41 -PostgreSQL cases, all 2,396 Unit cases and the positive authority case, with zero -failures/skips. Its source/mode/artifact receipt closes at -`cd7961e2b5873fa94b326caedacf265decffaf81cb7552591718fbe927c3eb52`. -An earlier test assertion compilation error remains its own failed-build receipt; -no tests are credited to it. App-role child submission, its completion gate and -acknowledgement-loss behavior remain pending in this same Step 8. Full Step 8 -reviews and runtime/capacity enforcement remain pending. - -The narrow acquisition preflight finds two additional source issues: claim -ordering includes a column absent from the pending index, and declaration-kind -validation rejects metadata accepted at registration. The corrected query orders -by `(available_after, id)`, matching the canonical index. A real 3,000-recipient -zero-jitter backlog proves the actual query uses that index without sorting and -examines a bounded quantum. Restoring the obsolete order in the same query makes -the same detector fail and consumes the backlog before LIMIT. Interface, struct -and open-generic manifest declarations pass the actual registration-to-claim -flow without constructing any feature service; owning-assembly validation remains. - -After these corrections, the Release build has zero warnings/errors; 45 -PostgreSQL cases, all 2,396 Unit cases and the positive authority case pass with -zero failures/skips. The 278-source receipt closes at -`d12a0f5fdaebacf0cfb7e8d93e0df8b65cf32a7e9e107514b39e37add1e8090f`. -Independent correction verification checks the source and hashed artifacts and -closes both findings without a new verified issue. This remains bounded -preflight/correction evidence, not either full Step 8 review round. - -#### App-role recipient submission continuation - -Acquisition commit `2059a7ee` preserves the preceding evidence. The closed -recipient executor now installs the actual tenant/organization route without an -invented child or parent identity and sends one exact framework request through -the existing coordinator. Its participant binds the original source owner, -physical transaction and positive tenant announcement. The app-role owner locks -the recipient, evaluates a fresh database clock and rechecks current lifecycle -eligibility before creating one fixed occurrence-input child. - -The common scheduler INSERT preserves ordinary producer checks and records -produced work only after successful SQL; failure marks the existing owner -rollback-only and rethrows. After owner drain and MUST audit, the participant -checks the full immutable route, original token and live lease and writes the -reciprocal receipt. A conservative monotonic budget covers SQL and cleanup until -the final commit gate. Only the existing coordinator records commit ACK. The -executor retains its source, scope and cancellation ownership through actual -cleanup; it constructs neither the target request nor its handler. - -Real PostgreSQL cases cover tenant and organization success, lifecycle refusal, -single-use replay, a closed gate and independent child-INSERT/receipt-UPDATE -failures. Both writes commit together or neither remains. Construction controls -exercise the actual registered target and handler separately and prove the same -no-construction assertion rejects each. Exact production censuses enroll the new -framework/context/source/owner path and retain the original admission restrictions. - -The 287-source qualification passes a zero-warning/error Release build, 75 -PostgreSQL cases, all 2,403 Unit cases and twelve focused Architecture cases, with -zero failures/skips. Its source/mode/artifact receipt closes at -`464b9554dac3d4b0060b8ca7021a16127741abd8b8d8518948dadf2da3fe18f2`. -Narrow proof review identifies five planted field/constructor mutations that the -first detector incorrectly accepts. All five fail against that original detector; -the corrected detector checks full writer identity, opcode and exact private -constructor/flag shape, and the same controls pass in the qualification above. -Earlier build, SQL and detector failures remain separate receipts. - -Final guard additions pin the recipient executor's exact internal signature and -currently empty production caller set. The shared INSERT proof binds its actual -SQL invocation and await acknowledgement to the same rollback-only/rethrow catch; -produced work must be invoked after acknowledgement and outside failure handlers. -Ten targeted controls move, remove, delegate or detach these actual instructions. -The earlier detector's incorrect compiled-signature assumptions remain a failed -qualification, not a runtime finding. Independent correction inspection verifies -both catch binding and invocation sensitivity without claiming test execution. - -Only that Architecture test file changes after the preceding 287-source receipt. -Its final Release build has zero warnings/errors; all seventeen recipient -Architecture cases and two real auxiliary-cleanup regressions pass with zero -failures/skips. Full formatter verification reports no changes. This source/mode/ -artifact receipt closes at -`65ba343bf9da98134a09e0e6297364d38daf752d57ef0aab2a03d3c2e6b3bd7a`. -These are local, source-specific receipts, not current-head full backend or CI -qualification. - -At this continuation's commit, historical acknowledgement-loss confirmation and -confined skip/defer remain pending; the following record owns their delivery. -Additional fault controls and native runtime/fairness/capacity integration remain -pending. This is not complete Step 8 delivery or a full review round. -No production recurrence or business definition is added. All nineteen -obligations remain Registered; both fresh full Step 8 reviews precede Step 9. - -#### Recipient history and confined disposition - -App-role submission commit `a99e6a8a` leaves all validated source hashes/modes -unchanged after normal hooks. A new confined operation now requires the original -executor's positive cleanup before opening another physical source. Its original -result has immutable authority fields and a constructor restricted to that -executor. A locked-row observation checks the full stored route and reciprocal -child before the old token: the accepted child wins even after token clearing or -a later acquisition, without creating another identity or inventing the original -COMMIT acknowledgement. A skipped lock is unavailable, never proof of absence. - -Without a final receipt, only the original DB-live token permits disposition. -Current lifecycle is rechecked; a deleted/ineligible route is skipped, while a -restored or otherwise eligible route receives bounded deferral. The final UPDATE -repeats the complete route/token/time fence. No app grant or business attempt is -added; this status operation publishes only after its own ACK and cleanup. - -Nine new PostgreSQL cases use real server-COMMIT response loss and unforwarded -COMMIT requests, counted identity creation, actual row locks, actual replacement -acquisition, lifecycle restoration and a throwing scoped cleanup dependency. -They distinguish a stored child observation from the original ACK. The initial -qualification retains one fixture failure at the forbidden live-token rewrite -and the detector's compiled-string mismatch; neither is a runtime finding. -The fixture now expires the lease and reacquires through the actual store. - -The final 289-source Release build has zero warnings/errors; 44 PostgreSQL cases -and 22 focused Architecture cases pass with zero failures/skips. All 2,403 Unit -cases pass before the two test-only corrections. Formatter verification reports -no changes. The final source/mode/artifact receipt closes at -`cbcc6cff06e17f089c4923e0819703e118454e8d68eed103288e896731e979d8`. -Narrow independent source inspection finds no unresolved runtime/test-evidence -issue and claims neither test execution nor full Step 8 review credit. -Remaining admission/fault controls and native integration still precede both -full Step 8 review rounds and Step 9. Nineteen obligations remain Registered. - -#### Recipient admission fault qualification - -History commit `f08f8bf1` preserves the preceding source qualification. Eleven -additional PostgreSQL cases exercise corrupted actual claim facts, context -replacement during identity creation, lease expiry after an observed row-lock -wait, and stop after the actual receipt UPDATE but before commit admission. -The tests check actual identity creation, SQL effects and rollback together; -no production seam or business definition is added. - -Narrow independent inspection identifies that the first context-callback test -cannot distinguish refusal before INSERT from rollback afterward. The corrected -paired test observes an actual server-side INSERT notice. Removing only the -post-identity context guard makes the corrupt case fail that exact assertion -while its healthy counterpart passes. The original production bytes and mode -are restored and verified against HEAD before rebuilding. This deliberately -failing mutation remains a separate receipt, not a production failure. -Independent correction inspection verifies the same assertion's failure, exact -source restoration and passing paired cases; no further issue is identified. - -The restored 290-source Release build has zero warnings/errors; all 55 cases in -the recurrence PostgreSQL class pass with zero failures/skips. Formatter -verification reports no changes. The source/mode/artifact receipt closes at -`022523338fa6f8ee3c3384f2b5ce878bb31b099035e16d07df338e65f995b8d0`. -Only Integration test sources change after the preceding committed production -qualification; Unit and Architecture suites are not repeated or claimed here. -Native runtime, fairness and capacity integration remain pending before both -full Step 8 review rounds. This focused qualification does not close Step 8. - -#### Native recurring-write serialization - -Recipient fault qualification is committed as `35c3e0d5`; normal hooks preserve -its validated source hashes/modes. Actual stock recurring `Job` writes now lock -the exact unsuperseded revision inside the vendor transaction. The explicit -volatile trigger takes a fresh snapshot after earlier waits, and bootstrap checks -the installed volatility with its existing body/language/search-path/ACL contract. -A generated additive migration upgrades already-migrated stores and restores the -preceding exact body on Down. Canonical SQL remains in Standards 05. - -Ten focused PostgreSQL cases use the real stock manager without starting workers. -They cover old-over-new refusal, an unchanged Job omission, retained older hints, -volatility-only drift, independent migration Up and canonical replacement, and -three actual lock interleavings. The same assertions reject the KEY SHARE, -missing-active-predicate and stale nonlocking-snapshot controls. No elapsed sleep -establishes those barriers; the tests observe actual blocking backend identities. - -Narrow source review identifies that applying canonical SQL before Up would mask -an omitted upgrade body. The corrected test first upgrades the actual old body -through the migration alone, then independently tests canonical replacement. -No further concrete issue is identified. Earlier SQL-cast and test transaction -cleanup failures remain separate receipts; a subsequent build-only receipt -grants no test pass. - -The final 297-source Release build has zero warnings/errors. The ten focused -cases and the broader 143-case PostgreSQL selection pass; the broader selection -includes those ten cases. All 2,404 Unit cases pass, with zero failures/skips. -Formatter verification reports no changes. The source/mode/artifact receipt, -including current SQL and canonical carriers, closes at -`aa38ded6b0042cba7a3521bbf02ada212b6cf09ae74c4fdde3ca5deac89aaa97`. -This is local qualification of the guard/storage unit, not full Step 8 review or -packet-wide CI. Owned runtime/tick integration, fairness, physical capacity and -their real fault proofs remain within Step 8. All nineteen obligations remain -Registered; both fresh full reviews still precede Step 9. - -#### Runtime connection and stored quarantine qualification - -Guard/storage commit `c4a93deb` precedes this runtime unit. The existing facade -now owns a recurrence child, one independent native manager flight and at most -four actual recipient application owners. Durable registration, slot, page, -claim and original-receipt history quanta rotate on one SQL lane. Native ticks -only coalesce a memory signal; they construct neither recipients nor feature -work. Exact recipient IDs remain excluded while their original task, cleanup or -receipt history is retained. Failed cleanup supplies no replacement authority. - -The shared observation reads stored recurrence, occurrence and recipient -quarantine independently of the local registry, including unknown older keys. -Each table has a reversible partial presence index. Both observation values -require actual reader/command cleanup and acknowledged ROLLBACK. Failed refreshes -preserve the preceding value and make the observation unhealthy. API composition -supplies Tenancy's existing closed lifecycle declaration as metadata. - -The named capacity inventory adds two privileged connections and four application -main/auxiliary pairs; stock worker and retained-invocation bounds do not increase. -Standards 05 owns the reconciled formulas. Real default/maximum app inventories, -explicit unrelated headroom and actual default/maximum native facade composition -exercise their own boundaries; this does not claim simultaneous saturation of -every runtime lane. Existing owner/caller manifests admit only the new concrete -recipient and recurrence callers, without widening source-acquisition authority. - -The initial runtime build retains three analyzer failures as a separate receipt. -An intervening Unit run passes 2,401 cases and fails three old capacity premises; -after their correction, all 2,404 Unit cases pass. The first two native fan-out cases -reach completed children before their test-created ticks fail the transport's -ambient-culture guard. The corrected test uses the real native owner's invariant -culture boundary; that guard remains unchanged. A subsequent 311-source build has -zero warnings/errors, 2,408 passing Unit cases and 78 passing PostgreSQL cases. -Three new quarantine refresh cases fail because revoking a column grant cannot -remove the existing table-level SELECT grant. Their corrected premise first -proves actual `42501` after revoking the real grant, before awaiting health change. - -The final 322-source Release build has zero warnings/errors; all 2,408 Unit cases, -twelve focused PostgreSQL cases and four focused Architecture cases pass with -zero failures/skips. The PostgreSQL selection covers each corrected cold-runtime -quarantine path, expired-lease exclusion, invalid exclusion sets, populated -recipient query plans, three-index Down/Up, actual facade topologies and actual -native transactional progress at the new app floor. Earlier passing cases include -both tenant/organization fan-out paths, three duplicate stock ticks per path, -reciprocal receipts and each control index's decisive 3,000-row removal control. -The final selection does not rerun or relabel that earlier broad selection. -Formatter verification reports no changes. Its source/mode/artifact receipt closes -at `8722a6b2799ba23d3cc1d8271c56dc9357b649a5b684160df8a4f8beabcc08f8`. - -Two narrow source preflights identify the missing isolated quarantine/index proof -and the exact existing caller enrollments, addressed above. They execute no tests -and grant neither full Step 8 review round. Complete new-owner/tick capability -guards and retained-work, fairness and shutdown fault qualification remain before -both fresh full Step 8 reviews. Nineteen obligations remain Registered; Step 9 is -pending and no packet-wide regression or CI success is claimed here. - -#### Actual native hold and parent-source pins - -Runtime commit `c500bcba` precedes this test-only qualification. An actual Npgsql -diagnostic callback holds the stock recurring manager on its owned native thread. -Two registered keys still produce two completed durable children. This is a -bounded synthetic callback hold, not a network-fault reproduction or a minimum -connection-pool proof. The fixture has explicit unrelated connection headroom. - -The original one-key assertion could pass with the hard native-flight guard -removed because the same-key cooldown independently prevented replacement. A -narrow source review identified that masking premise. Two keys now establish a -second eligible native opportunity; the test reads the actual published owner -under its lock and verifies that its original thread remains the sole owner. -The first strengthened run fails only because a string assertion selects the -wrong overload; its corrected explicit collection assertion preserves the premise. - -Before testing source retention, all ordinary pools, shared maintenance, bridge, -parent control lanes and recurrence loop/cancellation relay positively join. -The held native invocation still prevents parent completion and both actual -source lifetimes from disposing. Releasing the callback permits actual SDK/thread -return, parent completion and positive disposal without cleanup faults. An -independent nested-finally join retains the original thread even when an -assertion or parent shutdown fails. - -Two separate temporary source controls are decisive: removing only the hard -native-flight guard admits the second key and fails the original-owner assertion; -removing only the parent's recurrence completion await makes stop finish early -and fails the finite-stop assertion. Each control builds without warnings/errors, -fails the same test and is restored byte-for-byte with its original file mode. -No deliberate violation is committed. - -The final restored 323-source Release build has zero warnings/errors. All 76 -recurrence PostgreSQL cases pass with zero failures/skips in 43 seconds, including -the actual native hold, tenant/organization fan-out, native races, recipient -receipts/history and stored quarantine paths. The runner's nonempty/zero-skip -guard passes and scoped formatting reports no changes. The source receipt closes -at `c9331866654efc91c83769cb718398416c97084897f38547a0a18f9cd2253416`. -The narrow review supplies no full Step 8 review credit. Remaining recipient -retention/fairness and exact capability guards still precede both full rounds. - -#### Actual recipient ownership, expiry and source cleanup - -Following `dd600e88`, the actual runtime exercises six due recurrence keys with -four real recipient application tasks held before their handler acquires a row -lock. Each retains its original unit, source owner and published operation. -PostgreSQL's clock establishes natural expiry of all four 15-second leases; -the fixture neither rewrites those leases nor substitutes local timestamps. -Durable registration and fan-out continue while all four application slots remain -occupied, including their timed-out actual tasks. - -The otherwise-eligible production selector independently ranks a retained original -first. Three handlers then return through their real closed-gate refusal, -rollback, cleanup and history resolution. Exact original-object eviction permits -a fresh operation for the same ID. Another recipient commits its reciprocal child -and completes while the remaining held row preserves its original token and -operation. Releasing that old attempt cannot attribute a later child's ACK to it. -All six children eventually complete through the actual runtime. - -Two separate source controls fail the same semantic assertions: enlarging the -ceiling from four to five admits six wrapper entries, and removing only the SQL -retained-ID exclusion replaces the otherwise-first held token. The rank helper -does not assert the removed SQL spelling, and full capacity does not mask the -exclusion check. Both controls build cleanly and are restored with exact hashes -and file modes before final qualification. - -Two further cases separate a physically held original cancellation callback from -an actual DI scope's successful asynchronous disposal. The callback case first -proves that the executor, scope and application-source cleanup have returned; -the cancellation relay alone remains held. The scope case instead observes a -positive child COMMIT ACK while actual scope disposal and executor return remain -pending. Every sibling, including any native registration, positively joins -before the original operation and both source pins are checked. Replacing the -all-owner cancellation join with an any-owner wait fails the callback case while -the independent scope case still passes. The original join is restored exactly. - -Narrow reviews correct the exact three-history-owner eviction observation and -the registration fixture's inline-cancellation race. Registration is itself an -owned actual task with a finite setup wait. All barriers release before shutdown; -nested finally blocks independently join registration cleanup and the original -operation. These reviews grant no full Step 8 review credit. - -The initial application-test build records two analyzer errors, corrected without -changing production policy. Earlier clean qualification passes the application -case and both source-pin cases. The final restored 325-source Release build has -zero warnings/errors; all 79 recurrence PostgreSQL cases pass with zero skips in -1m08s. The four focused Architecture cases initially expose the stale published -240-method count; five already-added Step 8 methods make the actual total 245. -After that documentation correction all four pass, including Docker-trait and -planted-trait checks, the non-skip guard and catalogue counts. The runner verifies -nonempty execution and zero skips; explicit TRX checks separately require zero -failures in both final runs. Scoped formatting reports no changes. The source, -mode and artifact receipt closes at -`c463834754105981e5babcad10d39cbf0529a6c8a4b9f3b0358ba0ae94ebec6a`. - -New-owner/native-manager/tick/exclusion capability guards and their planted -controls still precede both fresh full Step 8 review rounds. Nineteen packet -obligations remain Registered, Step 9 remains pending, and this qualification -claims neither packet-wide regression nor CI success. - -#### Recurrence core capability qualification - -After `b72ce6ce`, a new nonempty production census closes the four concrete -recurrence owners' constructors, startup/cancellation callbacks and parent -completion capability. It pins exact declaring assembly, method signature, -visibility, caller, opcode and multiplicity. The internal sealed native client's -primary constructor has public IL visibility; the census records that actual -shape without changing production accessibility. Null-conditional native stop -and thread-exit calls likewise retain their exact compiled opcodes. - -A narrow review finds that name/count checks alone could accept a foreign -cleanup target. Cleanup checks now require the exact trusted .NET 10 facade -identity, full signature, instance/static shape and opcode. Actual configured -awaiter identities preserve multiplicity, including both non-generic native -awaits. Attached foreign capability, Thread and nested awaiter controls must fail -the same detector; each restores the original operand before removing its -temporary in-memory type. No assembly file or production source is mutated. - -Earlier guard runs record incorrect constructor/opcode premises separately; -mutation cases failing their clean baseline receive no dirty-control credit. -The final 326-source Release build has zero warnings/errors. Thirteen focused -Architecture cases pass in twelve seconds with zero skips: the baseline, eleven -clean/dirty/restored controls and the catalogue count. The two added companion -methods bring the published count to 247. Scoped formatter verification reports -no changes. Its source/mode/artifact receipt closes at -`8d62c2fd3956e1bc2d182ea1dcda0f1ff61e7e00f6a5388480e971942ad4c4d2`. - -This qualifies the core capability slice, not semantic task-dataflow enforcement -or the complete recurrence census. Field/holder and publication ownership, -native SDK invocation, memory-only ticks and exclusion-list guards remain before -both full Step 8 review rounds. Nineteen packet obligations remain Registered; -Step 9 is pending. Neither narrow source review supplies full-round credit. - -#### Recurrence ownership, hint and publication guard qualification - -After `59a19e15`, the same two companion methods close the new owners' field -inventories, resource types, exact access sites and whole-production holders. -Actual async attributes identify permitted state-machine holders. Generic -resource identities are checked recursively; same-name foreign resources and -forwarding accessors are rejected. Each completion source retains its actual -concrete owner. Existing physical-source, privileged-entry and rollback caller -allowsets are unchanged. - -Native registration uses the exact stock manager seam, two manifest arguments, -control queue, UTC minute hint and Relaxed misfire policy. The census includes -the stock V2 recurrence interface. The fourteen-method tick closure admits only -its enumerated memory calls/fields and pinned framework/vendor leaves; injected -scheduling, indirect calls, changed tick identity or early readiness reads fail. -This establishes a closed work surface, not an absolute latency guarantee or -general argument/control-flow proof. - -Recipient selection retains its sole caller, bounded collection snapshot, -actual UUID-array parameter and retained-ID SQL exclusion. Source-order checks -pin publication before Start, cancellation join acknowledgement before source -disposal, and positive completion after actual cleanup/thread-exit observation. -The previously recorded actual PostgreSQL/retained-task controls supply the -separate causal lifecycle evidence; structural order alone is not its substitute. - -Narrow independent inspections identify and verify corrections to the V2 -interface census, resource/generic identities, cancellation join acknowledgement, -provider invocation identity and tick token. Earlier build/clean-premise errors -are retained separately. The initial 43-case run has one passing catalogue case -and 42 clean-baseline failures caused by an ambiguous completion-signal selector; -none receives dirty-control credit. The corrected selector distinguishes the -returned signal from positive owner completion. - -The final 330-source Release build has zero warnings/errors. All fifty focused -Architecture cases pass in one minute ten seconds, with zero skips: the baseline, -48 clean/dirty/restored cases and the unchanged 247-method catalogue count. -Scoped formatter verification reports no changes; its workspace-load warning is -not reported as a build warning. The source/mode/artifact receipt closes at -`cc7fcc480cd9234aa9d80ef189d3a602bc32c5e10b884e5393cd797bd22c7b4a`. - -This completes the new guard slice. Both fresh full Step 8 review rounds remain -before Step 9; these narrow inspections award neither round. All nineteen packet -obligations remain Registered. No packet-wide regression or CI success is claimed. - -#### Step 8 full review round 1 (2026-10-18) - -Three fresh independent reviewers inspected `69405b16..332e7a4a`: GPT-6-astra -xhigh covered runtime/lifecycle, GPT-6.1-sol xhigh covered persistence/authority, -and GPT-6.1-sol high covered tests/corpus. These are full Step 8 reviews, distinct -from the earlier narrow preflights. The reviewers ran no toolchain or database -checks; the execution receipts below belong to the root implementer. - -Two Major findings and one Minor corpus correction were verified: - -- A stop winning before the new child's native-client binding or Start caused a - setup exception. The parent/facade could then retain a false cleanup failure - indefinitely despite no issued recurrence work. Both child entry points now - return neutrally for that stopped-before-setup state. Already-bound/started - duplicate refusals and an open nonempty owner's missing-client refusal remain. -- PostgreSQL's finite timestamp range exceeds the CLR range. A schema-legal BC - activation or year-10000 anchor could repeatedly fail decoding the first due - row before its invalid-control branch, starving healthy work. Readers retain - the actual locked locator before decoding and treat unrepresentable dates as - absent facts, never fabricated valid values. After actual reader cleanup, the - exact recurrence, occurrence or recipient is quarantined without issuing work. - Only deterministic conversion exceptions are contained; IO/cancellation/server - failures retain the existing owner/cleanup path. Higher-revision registration - compares the prior activation in PostgreSQL instead of decoding it into CLR. -- The live catalogue introduction still described completed Step 7 qualification - as pending. Both current pointers now agree with its completed record; Step 9 - enforcement remains pending and all nineteen obligations stay Registered. - -The first four regressions ran against unchanged production code and failed at -all four intended assertions, not fixture setup: two bad-date rows repeatedly -failed without quarantine/healthy progress; two late child setup calls threw. -That test-only receipt is -`6613d4652759320ee077261bc6186efef597258d74d832431dc407d584d24299`. -With the five production corrections, the same four cases pass; the first -corrected receipt is -`e54a9f08143b829cac78911e3291a2a7dfafe374e0a9dbee2e7548a6cb94948f`. -Neither receipt is a current-head whole-packet regression or CI claim. - -The expanded qualification adds eight timestamp cases across recurrence -materialization, occurrence paging, recipient acquisition and higher-revision -registration, all under the real confined-role grants and unmodified guards. -Each invalid selected row confirms ACK/cleanup, no authority/progress beyond -quarantine, and healthy sibling progress. BC scheduled routes require BC manifest -activation, so their absent-manifest branch does not independently qualify the -recipient's own-date checks. A future year-10000 incumbent activation returns -Conflict without inserting a revision; a BC incumbent permits the later valid -revision and exact supersession/hash. - -Four lifecycle cases use actual owners and sources. The late setup assertions -inspect the actual null client/native fields, unstarted flag, empty recipients -and positively completed null-loop witness. A synchronous hold on the actual -child monitor orders real parent Start past its admission guard before facade -stop, then joins the original start task, parent/facade completion and both -sources. The open/duplicate controls preserve programmer-error refusals. No -synthetic owner/task/source replaces the real cleanup chain; the parent barrier -is qualified on corrected code, not described as an original-code execution. - -The expanded Release build has zero warnings/errors. All 2,408 Unit, 91 -recurrence PostgreSQL and 57 focused Architecture cases pass with zero -failures/skips. The Architecture run includes all 49 recurrence capability cases, -four existing owner/recipient guards and four catalogue/skip/Docker-trait checks. -The seven changed C# files pass formatter verification with no changes; its -workspace-load warning is distinct from the warning-free build. The 332-source -hash/mode receipt closes at -`afdda5089283dd6eee49f527576466778817bf78f3a041c857d4385bccb00239`. -The local link audit passes 1,740 links and 519 fragments. These focused checks -do not replace Step 9's complete regression or real CI. Round 1 and its verified -corrections are complete; a fresh full Step 8 round 2 is still required. - -Step 9 explicitly owns durable unknown/deployment-mismatch observation, including -an empty-registry restart. Local registration mismatch flags alone do not qualify -that cold durable-health surface. These corrections add no new ADR decision, -role/grant, production business definition or general lifecycle selector. - -#### Step 8 full review round 2 (2026-10-18) - -Three new independent reviewers inspected the complete `69405b16..f687924b` -range: GPT-6-astra xhigh (runtime/lifecycle), GPT-6.1-sol xhigh -(persistence/authority/security), and GPT-6.1-sol high (proofs/corpus). The -persistence lens verified no finding. Runtime and proofs independently found -the same Major acceptance-proof gap, counted once: ADR-0059 explicitly requires -recurrence progress while the actual control generation stays drained/held. -The earlier native-manager-thread hold and empty-registry delayed-job repair -proofs did not establish this composed scenario. No new Step 8 runtime defect -was verified. These full reviews ran no toolchain/database checks. - -The new real-facade test preregisters a due 61-day-old, 30-day-interval manifest, -then locks that actual row before starting the runtime. It holds the actual -control generation's owned Invocation, requests drain, positively joins its -normal children and verifies zero occurrences/native jobs before unlocking. -The retention barrier is explicitly synthetic; no network/business fault is -claimed. A coalesced occurrence skips two slots and completes one reciprocal -recipient/child with one normal attempt while the same generation remains held. -Three real SDK ticks remain Enqueued during drain; three actual duplicate store -quanta add no slot. Releasing and positively joining the original generation -permits a replacement to execute those ticks without another occurrence, child, -normal attempt or feature execution. Actual runtime and both source lifetimes -must confirm cleanup/disposal. - -A separate inherited Major parent-start race was verified against the Step 8 -base as well as current code. Facade startup could pass its final admission, -then encounter an already stopped parent's throwing Start guard and retain a -false cleanup failure indefinitely. This is not attributed to the new child -race or Step 8 diff. It is corrected now within the packet: an already-started -parent still rejects duplicates, but stop before its first start returns -neutrally using RequestStop's actual empty-loop witness. No cleanup flag or -completion promise is reset. - -The new stopped-parent leaf fails at the original guard on unchanged `f687924b` -production, then passes with the correction. Its executed negative receipt is -`6a01365667134f9e6ff9c03d74da65f5fa4e9eac756b7367333d54f2571a9970`. -An initial test-only blocking-Result analyzer error is recorded separately and -receives no execution credit. The corrected actual-facade test holds the real -parent monitor, observes the original facade task's Starting state after its -last admission, then calls stop before parent admission and releases the -monitor. It joins that same startup task, facade and actual sources without -awaiting under a monitor. A distinct already-admitted-parent case preserves -duplicate refusal. The full facade barrier is qualified on corrected code; -no old-code full-facade cleanup claim is made. - -Both focused correction reviewers approve the inspected source and causal test -premises; these are verification of round-2 corrections, not a third full review. -The first corrected 333-source receipt records a zero-warning/error Release -build and four focused PostgreSQL cases passing with no skips: -`88e67c6e998d603c87874635eee1deeac615b124732359ab8860abd82186aa12`. - -A deliberate, uncommitted source control couples control-generation drain to -the shared process start gate. The same held-generation test then fails at -post-drain durable child progress, after its actual join/row-lock premises, -and performs its ordinary barrier/owner cleanup. That dirty receipt is -`ba68cf1a3dd7a77c9490dc82fe1d3208c585569c88ae714cdda10c291ae968fe`. -The generation source is restored byte-for-byte and the corrected source/mode -inventory matches again. No mutant enters the change. The test demonstrates -its ability to reject the forbidden dependency; it is not a production fault -or unconditional delivery-latency guarantee. - -Final clean-source qualification freezes 333 changed/new C# sources and records -a zero-warning/error Release build, 2,408 Unit cases, 94 recurrence PostgreSQL -cases and 57 focused Architecture cases passing with zero skips. The focused -Architecture run takes 4m12s. The final receipt is -`268a030f9ee059860732668f78061973caf5cd6da342d5a43191a526915d9431`. -Scoped formatter verification returns no changes. Both full Step 8 review rounds -and verified corrections are complete; this closes Step 8 locally. - -Step 9 follows under the already Accepted plan. Its scope includes durable -unknown/deployment-mismatch observation, full job metrics and health, complete -nineteen-rule enforcement, the skill/carrier handoffs and full packet regression. -The historical complete Architecture run exceeds the existing backend CI budget; -Step 9 must measure and reduce repeated detector scans while preserving every -subject and clean/dirty/restored control. No nineteen-rule promotion, complete -backend/frontend/demo, packaging, CI-duration compliance or real PR-head CI -success is claimed by Step 8 receipts. No maintainer decision is pending. - - -### P02b-4 Step 9 — enforcement and packet closeout (2026-10-18) - -**Current status:** the [local closeout](#p02b-4-local-closeout-2026-10-18) owns -completed implementation/reviews, exact qualification and remaining PR/CI/merge -work. Earlier slices below retain their as-of evidence. - -**Initial status — implementation in progress.** Step 8 closes locally at -`390515b8` after both full review rounds and verified corrections. This follows the already Accepted -ninth step; no new maintainer decision is pending. - -The step's three internal closure units are: - -1. Complete full job observation, including bounded dimensions, memory-only - immutable gauges, cold durable unknown/deployment-mismatch health and distinct - confirmed-failure versus uncertain outcomes. Reduce repeated Architecture - detector scans without dropping cases, production subjects or any mutation/ - restoration pass; the unchanged whole backend CI budget still requires proof. -2. Match all nineteen packet obligations to actual nonempty production censuses, - behavioural proofs and planted controls; complete carrier/feature handoffs and - the shared repository background-job skill. Catalogue promotion waits for - complete enforcement and qualification. -3. Run complete backend/frontend/demo regression and packaging/boot proofs, - commit, then run two fresh full multidimensional review rounds with verified - corrections and commits. Prepare the development-to-main PR with exact local - evidence; real PR-head CI and maintainer merge remain separate. - -The initial performance preflight is read-only planning, not a benchmark or full -review. It finds repeated whole-production instruction traversals inside one -read-only detector evaluation. A current-source four-case baseline runs before -editing that mechanism. Any index must be fresh for every clean, dirty and -restored evaluation, include every actual operand/owner/opcode and retain exact -identity and multiplicity checks. No shorter filter or increased CI timeout is -proposed. Full observation/enforcement and packet qualification remain pending. - -#### Initial scan and existing-boundary qualification - -The first slice adds complete method/field operand indexes inside one disposable -detector evaluation. Name buckets only prefilter the existing full identity, -opcode, order and multiplicity checks. Every clean, dirty and restored evaluation -gets fresh indexes. Owner strings are computed after candidate selection, and -ordinary call-site ownership is formatted only when its body contains a method -operand. The attribute-based async-owner mapping remains unchanged. - -The four-case current-source baseline passes in 288.801 seconds of summed case -time. Initial indexing passes the same four cases in 160.233 seconds; the later -owner-string refinement records 60.062, 38.801 and 47.214 seconds for the three -existing runtime/bridge cases, plus 3.651 seconds for the expanded cache companion. -These are focused measurements with additional cache controls, not a complete -workflow speedup or proof that the CI budget is met. A deliberate persistent-index -mutant fails the actual membership comparison. A separate stale-owner-string -mutant fails at the same method's `RenamedRun` versus cached `Run` identity. Both -test-only mutations are restored byte-for-byte before clean qualification. - -The complete intermediate Architecture run executes 403 cases: 401 pass, two -fail, and none skip, in 1,837.15 seconds of wall time. Its two failures expose -older source guards that still reject Accepted recurrence readers/task owners. -They do not justify broader runtime permissions. A brief native sample cannot -attribute managed hotspots; no profiling-based attribution is claimed. - -The organization guard now enumerates five exact SQL subjects across four actual -files: three composite point reads and the bounded composite inventory/bounds -queries. It pins direct command arguments, minimal projections, tuple seeks, -page limits and actual tenant/organization parameter bindings. The original -validator's READ ONLY/announcement ordering and the EF primary-key ban remain. -The parallelism guard permits only nine exact invocation spans in three retained -recurrence owners, with method/signature/count and suppressed-flow publication -checks; the rest of each file is still scanned. Neither change adds whole-file -exemptions or substitutes for the separate database grants and resource proofs. - -Focused independent inspections identify and close reader-discovery and binding -false passes: JOIN/interpolated/constant-concatenated readers, transformed SQL -literals, nonexecuted bindings, protected-key overwrites and captured parameter -rebinding. The actual-source dirty/clean companions exercise the same detectors. -Two new companions bring the published Architecture method count to 249; all -nineteen P02b-4 obligations remain Registered. These inspections are not either -full Step 9 review round. - -The final 338-source snapshot passes a CI Release build with zero warnings/errors -and all 39 selected Architecture cases, with zero failures/skips. The selection -includes both corrected source guards and their companions, cache sensitivity, -catalogue consistency and both complete orchestration mutation companions. Its -source/artifact receipt is -`832548288722970b30482e75a1f814e07675476210784f93d6913a7eb07f9b81`. -The final two orchestration cases take 54.310 and 239.371 seconds, supplying the -fresh baseline for the next bounded optimization. The unchanged twenty-minute -whole-backend CI budget remains unqualified. Full job observation, complete -packet regression and both full Step 9 review rounds remain pending. - -The next two-file slice removes eager orchestration identity formatting while -retaining the complete declaration and field-access inventories. Actual delegate -resolution uses a name bucket followed by the unchanged exact identity and unique -match policy. Field owners remain actual attributed method references until the -original name/type filters select them; string deduplication and opcode/write/ -address counts stay in their original positions. An independent companion -compares the old/new declaration policy with foreign namesakes and overloads, -then checks every field group and ordered occurrence before the full mutations. - -Both complete orchestration companions pass with zero failures/skips after a CI -Release build with zero warnings/errors. Their summed case time changes from the -fresh 293.681-second baseline to 191.688 seconds (33.271 and 158.417 seconds). -This approximately 35% reduction applies only to those two companions, including -the additional equivalence checks. The final 338-source/artifact receipt is -`3a8555f7481c4fb74a8123676a9ab61c5141f6e71d8cdccd393db8e2962a43f6`. -A focused independent inspection finds no correction; it supplies no full Step 9 -review credit or whole-workflow duration proof. The twenty-minute CI budget and -the remaining observation/enforcement/packet work stay open. - -#### Bounded mutation-collection qualification - -Eight existing heavy companion Facts move into three public nested sealed -partial classes. Each Fact still owns its independent Cecil graph and complete -clean/dirty/restored sequence. Canonical rule Facts remain in the outer class. -An explicit per-class collection attribute caps the Architecture assembly at two -runner threads; neither the CI filter nor its timeout changes. - -All 249 source method token sequences and compiled signatures/attributes match -before/after. Complete runner discovery preserves all 405 cases with exactly -eight declaring-class substitutions and no missing, extra or duplicated cases. -The first comparison omitted the custom-display NetArchTest meta case from its -404-row namespace subset; the corrected comparison includes that unchanged case. -A scratch actual-detector control proves distinct module/type/method/instruction -objects, an offender in graph A with graph B clean, and both restored clean. -The pinned xUnit factory selected by the actual assembly attribute assigns four -distinct collection identities to the outer class and three nested classes. - -The 341-source snapshot passes a zero-warning/error Release build, all eight -moved companions and six corpus/cache cases, with zero failures/skips. Scoped -formatter verification reports no changes; a focused independent source review -finds no correction. The source/artifact receipt is -`21c209eaefce9e70e5bc55117b02629cfa6be7fa45a9f9bddf0c7dac0dfd1482`. -The eight-case run takes 869.24 seconds of wall time; summed case durations are -1,433.773 seconds. Completion-time/duration reconstruction is consistent with -two overlapping collections. The adapter's TRX StartTime usually equals result -receipt time, so it is not independent execution-start telemetry. These figures -are workstation qualification, not a same-source speedup benchmark or CI proof. - -Repeated/full Architecture and complete backend-budget qualification remain -pending, together with full job observation, nineteen-rule enforcement and both -full Step 9 review rounds. No catalogue promotion or packet completion follows -from this focused slice. - -#### Durable observation foundation qualification - -The existing serialized status-read owner now publishes one complete immutable -aggregate after acknowledged rollback and actual resource cleanup. Frozen local -metadata classifies unresolved jobs, relevant historical recurrence manifests, -unfinished occurrences/recipients and unreleased reservations. The dispatcher -reads no payload or causal envelope and receives no new grants, source, task or -physical acquisition slot. Four independent indexed quarantine aggregates remain -in the same statement. A failed or stale refresh retains the prior sample and -cannot report healthy empty work. - -Cold native-runtime controls use genuinely empty definition and recurrence -registries. Four isolated fixtures retain future jobs/manifests or future retry -availability on unfinished children, without deployment-error markers. Completed -or fully superseded parents cannot mask a missing child aggregate. Each real -runtime reaches an otherwise healthy snapshot; only the copied deferred bit -changes its health result. Observation leaves the durable records untouched and -constructs no feature handler. - -The actual SQL hash CTE agrees with the independent .NET registry fingerprint -for thirty-six schedule/policy/date combinations, including microsecond limits, -unequal activation/anchor atoms, pre-epoch instants and maximum positive revision. -Two additional revisions prove discovery of frozen history needed only by an -actual pending occurrence. Diagnostic projections retain all production CTEs and -bindings and run under two session timezone/display formats. Epoch-offset, -repeated-anchor, omitted-history and removed-date-bound mutants fail their same -assertions. The unmodified full reader also accepts the valid population. - -An intermediate fourteen-case cohort passes eleven cases and fails three new -test assertions that incorrectly require a nonempty business queue in control-only -fixtures. Explicit empty-queue versus single-job assertions correct that test -error. The final 348-source snapshot passes a CI Release build with zero -warnings/errors and all twenty-three selected PostgreSQL cases, with no failures -or skips. This includes real rollback-response hold/loss, refresh grant refusal, -last-sample preservation and actual-query partial-index removal controls. Its -source/artifact receipt is -`606e8b2a5945cec409c20f23d7c1c25f0ae8d0cb74d0a920848bfc336d1f951a`. -Paired assertions in existing real admission, recovery, capacity and external -checkpoint tests qualify status eligibility against actual stored transitions. -They distinguish future original due time, retry availability, live/expired -routing, execution ownership, actual retained identities, unknown/Pending/retired -definitions and profile mismatch. Unreleased reservations remain counted after -expiry under their declared group or fixed unknown label. Repeatable/no-start -history admits real Normal routing after the proved backoff; selected outcomes -admit real Finalize routing independently of the six-normal-attempt ceiling. -These guarded state pairs do not claim independent removal tests for every -redundant storage defense. - -The final eligibility cohort passes fifty-two PostgreSQL and sixteen model/health -cases with zero failures/skips after a zero-warning/error CI Release build. Its -348-source/artifact receipt is -`af8b73b5899ffa0136cc0cdcd942d6cb5a003c904456be321043b760dcca7e80`. -The six production files remain byte-identical to the focused source inspection -and earlier three passing Architecture owner baselines. Focused inspections close -three hash-fixture proof gaps; none supplies a full Step 9 review round. - -Complete metric emission, nineteen-rule enforcement, full regression/CI duration -and both full Step 9 reviews remain in progress. No catalogue promotion or packet -closeout is claimed by this slice. - -#### Native observation projection qualification - -The immutable runtime snapshot now projects actual running/retained work, -generation counts and capture/join/cleanup facts from their existing owners. -Confirmed metadata timestamps remain nullable: an actual successful announcement -can confirm monotonic zero, while no confirmation remains absent. Returned pool -and maintenance collections reject replacement through their collection interfaces. -These additions introduce no scheduling, SQL, source or release authority. - -The first two-case PostgreSQL run passes the existing facade health case and -rejects a new fixture that supplies a separately reconstructed topology. Using -the host's actual frozen registry corrects the fixture without weakening the -production identity check. A focused inspection also closes its failure-path -cleanup gap: generation stop starts before either heartbeat or stop is awaited. -The final 350-source cohort passes both cases with zero failures/skips after a -zero-warning/error CI Release build. Its source/artifact receipt is -`733c1d57536c2c870810d27bb826b2cbf614cb153609ac6db01218e3f6dcb598`. -Three Architecture owner cases pass against the same production projection. -The manual real metadata callback does not claim Core's scheduling-cadence proof. -The focused inspection has no open findings and supplies no full Step 9 review -credit. Metric emitters and complete packet qualification remain pending. - -#### Memory-only job metric collector qualification - -One required concrete observation singleton binds the actual API runtime after -its snapshot owners initialize and before either source pin. The shared -API/Seeder composition creates no runtime or worker. Five observable families -project counts, exact SQL eligibility age, confirmed heartbeat age, component -state and fixed monotonic control observations. Each callback captures one -immutable memory snapshot and materializes its finite sparse measurements. -The [metric inventory](../standards/10-observability.md#required-metrics) owns -names and dimensions. Queue age remains the stored SQL sample; the earlier -acquisition/freshness timestamp cannot extrapolate it. Retained aggregate and -per-pool series remain distinct even for a legal pool named `none`. - -Actual MeterListener controls cover required DI, missing registration, -bind-once/disposal authority, conservative freshness, missing versus confirmed -heartbeats and complete empty-sample zeroes. Real PostgreSQL/native controls -observe cold unknown work under empty registries, preserve prior quarantine -samples through actual grant refusal and check complete metric identities for -the legal `none` pool. Fifty-eight unit and ten PostgreSQL cases pass with zero -failures/skips; their production and fixture sources remain unchanged through -the subsequent Architecture corrections. - -Three new Architecture companions inspect actual singleton descriptors, consumed -instrument/callback arguments, binding receiver/order/dominance and the transitive -memory method graph, including reached static initializers. Balanced clean/dirty/ -restored controls reject indirect SQL, arbitrary delegates, hidden or extra Meter -registrations, name/callback bait and skipped binding. An initial seven-case run -passes six cases and fails a new fixture's ambiguous instance/static constructor -selection. After that correction, a four-case run passes three and reveals an -unreachable skipped-binding mutation: existing branch targets bypass its prefix. -Moving the mutation onto the actual landing instruction corrects the control; -the final three metric companions pass with zero failures/skips. The complete -existing runtime/source-owner companion passes against the same shared walk. - -The final 356-source snapshot builds in CI Release with zero warnings/errors; -its source/artifact receipt is -`0327dabd84b0f91c0db248312f7747e0f6439756491160756bd6bfae43740100`. -Focused collector and guard inspections close their verified findings; neither -supplies a full Step 9 review round. Stage/event instrumentation, complete -control-path accounting, nineteen-rule enforcement, whole regression/CI-budget -qualification and both full Step 9 reviews remain pending. - -#### Actual executor stage measurement qualification - -Three synchronous families add execution duration, confirmed stage failure and -uncertain write/effect observations to the five memory collectors. Seven actual -executor owners record after their existing scope/Activity/context/authority/ -source/auxiliary/registration cleanup. Duration excludes subsequent metric -notification and the outer native owner's later private-token cleanup; a blocked -listener still belongs to the actual task. Each instrument contains catchable -listener faults independently, reports observation unhealthy and preserves the -original result. A physical acknowledgement remains successful through cleanup -or notification faults. - -The private provider-issued bit records the existing typed bridge's successful -entry CAS immediately before the actual call. It grants no execution, checkpoint, -retry or release permission. Construction/entry faults before that point do not -become uncertain external effects. Valid Running reports remain pending; -explicit Unknown and issued-call faults remain distinct from provider Failed. -Capacity cleanup without acknowledgement or uncertain COMMIT uses neutral -`NotCommitted`, since its existing result does not distinguish refusal from -failure. Business cancellation registration disposal now completes before its -final classification and measurement. - -All 364 Jobs unit cases and 25 selected real PostgreSQL cases pass with zero -failures/skips. The latter retain actual dropped-COMMIT-response, post-ACK scope -and Activity faults, held cleanup, throwing metric listeners, unissued provider -constructors, genuine provider/finalization, Running/Unknown and issued reconcile -fault/timeout premises. Measurement assertions accompany those durable facts; -they do not substitute for them. These cases do not independently qualify every -capacity, recipient or stored-selection metric branch. - -The first seven-case Architecture cohort passes six and fails a new stage-call -scan on a deliberately detached method reference. Narrowing to an attached exact -observer target before formatting identity fixes that detector regression. -Focused review also closes call-reference versus call-opcode, synchronous unit/ -numeric metadata and actual stage-root selection gaps. Balanced method-group, -seconds-to-milliseconds and direct SQL mutations exercise those same checks. -The hidden-Meter boundary permits only the exact instance constructor; a dirty -actual observer static initializer proves that distinction. The final seven -Architecture cases pass with zero failures/skips, including the complete prior -runtime/source and orchestration companions. - -The final 357-source snapshot builds in CI Release with zero warnings/errors; -its source/artifact receipt is -`847271cf34791d5cb0d930202de07500776afac2adc5463249e0bfe7d524e616`. -Production and unit/PostgreSQL fixture sources remain byte-identical through the -final guard corrections. Focused implementation and guard inspections have no -open findings in this slice and supply no full Step 9 review credit. Named-source -tracing/Start ownership, remaining branch/lease/control instrumentation, -nineteen-rule enforcement, whole regression/CI-budget qualification and both full -Step 9 reviews still precede packet closeout. - -#### Named-source tracing and cleanup ownership qualification - -The required observation singleton owns `learnstack.jobs`; its finite factory -returns an unstarted W3C Activity. All eight actual owners capture it before -`Start`. Recipient and pre-envelope recovery reads start independent roots; -terminalization keeps the real suppressed control lane. Trusted envelopes supply -the other parents. Recipient startup clears the caller's context before central -enrichment; it invents no tenant tags before the actual route context exists. -All seven executor owners independently attempt Activity and tenant restoration, -including a restoration callback fault after an actual COMMIT acknowledgement. - -Absent, refusing, propagation-only, sampled and throwing samplers preserve the -factory contract. The first unit run detects an all-zero fallback parent; -omitting `SetParentId` for a default parent produces a genuine root. The corrected -373 Jobs unit and 70 real PostgreSQL cases pass with zero failures/skips. Actual -recipient, capacity, stored-selection/no-start, recovery, held/faulted cleanup and -lost-ACK premises accompany source/parent/measurement assertions. The first PG -selection accidentally includes a helper-name filter and is canceled; it earns -no full passing receipt. The replacement uses 35 exact test-method identities. - -The source census binds the consumed source name, readonly owner, factory and -disposal receivers, actual retained Activity slot and Start/Dispose instructions. -Its memory walk follows the actual factory through helpers and static -initializers. Name bait, early Start, spare slots, hidden sources, helper SQL and -helper Start controls pass in the corrected ten-case Architecture cohort. Final -disposal method-group controls additionally distinguish an actual call from a -captured reference; all ten final Architecture cases pass with zero failures or -skips. The final 362-source receipt is -`ca0549e92bcb4bad50ea5fc7d82218bc3831a2bc9bcad49c21c6c6000095c9f9`. -Only the tracing guard differs from the preceding 373-unit/70-PostgreSQL source -snapshot; all production and behavioral fixtures remain byte-identical. Caller -operation/parent policy is behavioral qualification, not a general IL dataflow -claim. Focused reviews supply no full Step 9 review-round credit. - -Complete control/lease/late-settlement accounting, nineteen-rule enforcement, -whole regression and unchanged CI-budget qualification, and both full Step 9 -reviews still precede packet closeout. - -#### Control transition counter qualification - -Actual control owners retain physical renewal, retry and terminal observations -even when subsequent cleanup refuses release. The original completion request -counts its retry once; a clean locked probe can confirm that exact transition. -Same-generation routing repair and changed ownership do not imply a retry. -The external execution owner likewise distinguishes its actual retry ACK from -its original locked confirmation. Renewal history has a separate fixed -`renewal_history_confirmed` cell and never reopens the closed execution lease. -No counter recorder creates a source, task, listener invocation or authority. - -The new actual-owner PostgreSQL theory covers ACK, lost ACK with a real blocked -confirmation query, and a later real admission that changes the original owner. -All three corrected cases pass. The existing nine native known-outcome/recovery -cases additionally assert direct retry ACK totals. The initial new theory uses -an invalid 25 ms polling bound and leaves its probe pacing at the 30 s default; -those setup defects are corrected to the accepted 50 ms and 5 s bounds. Its -initial three failures do not constitute counter-runtime failures. The first -build also rejects a nonexistent test-row property, replaced by an independent -database generation read. - -The final source census roots each of the three recorders and the finite retry -predicate in the existing memory walk. Reached/unreached SQL helpers and clean -restoration distinguish these paths; exact references and typed bookkeeping -owners remain bounded. Real-listener projection uses distinct acknowledged and -history-confirmed renewal values. Focused reviews grant no full Step 9 round. - -The final CI-mode Release build has zero warnings/errors. All 373 Jobs unit and -six final Architecture cases pass with zero failures/skips. The three corrected -owner cases and nine native PostgreSQL cases cover byte-identical production and -PG fixture inputs; the final changes affect only four guard/unit files. The -final 363-source receipt is -`067bf593428c041bcbb0b0e1857c0c2e1c8a635f55b0bed3608eb6c6fd7362e8`. - -#### Control branch qualification - -Fourteen actual-owner PostgreSQL cases pass together with zero failures/skips. -They cover external retry ACK, lost ACK with blocked original-history confirmation -and changed ownership; both native Finalize retry paths; ordinary retry plus -actual grouped-capacity rollback/release; physical versus history-confirmed -renewal; and terminal MUST audit followed by held or refused scope cleanup. -The existing prebound late-renewal case also passes with the selective proxy. -History-confirmed renewal never reopens execution permission. Terminal counting -preserves an acknowledged audit even when actual cleanup refuses release. - -The proxy holds the actual renewal COMMIT by its returned column inventory; -other control transactions cannot consume that fault. Actual owner results, -durable state and row-lock waiters constrain the observations independently. -The grouped retry case qualifies a physical ACK, not grouped lost-ACK history. -The deliberate terminal cleanup failure disposes its inner scope before throwing; -the finite observation task joins actual lanes while public cleanup remains -unconfirmed. Isolated external retry ownership does not establish native -Hangfire handoff. The focused source review reports no verified findings and -grants no full Step 9 review-round credit. - -The final CI-mode Release build has zero warnings/errors; scoped formatting -reports no changes. Production source remains unchanged from `c581f798`. -The final 364-source receipt is -`fb03a92a9e6e96b22aae6953c233fe5b4106d02567421b6e355d1741627b06b1`. -Connection-cleanup fault combinations and grouped retry history are not claimed -by this bounded cohort. Recurrence/bridge/lease/late accounting, nineteen-rule -enforcement, whole regression and unchanged CI-budget qualification, and both -full Step 9 reviews remain open. No catalogue obligation is promoted here. - -#### Recurrence progress qualification - -The actual recurrence owner records six fixed process totals from original -acknowledged occurrence/page results before cleanup qualification. These cover -inserted occurrences, skipped slots, pages, raw routes examined, inserted -recipients and completed fanout cursors. Registration, native ticks, null results, -unacknowledged values and later history add no original ACK. The existing -eight-family metric inventory projects them through fixed control-total -operations without identity labels, new SQL, sources, tasks or authority. - -Both-scope actual-runtime PostgreSQL cases examine three raw lifecycle routes, -including a suspended tenant, and create two recipients in two pages. Independent -stored state, child/context checks and actual listener samples establish one -occurrence, two skipped slots and one completed cursor. Repeated collection and -duplicate native ticks preserve the totals. Two isolated actual-store/owner-hook -cases lose the physical COMMIT response after proving the server write: their -nonnull results and later no-op queries never become acknowledged progress. -They qualify occurrence and empty-page uncertainty, not native-runtime handoff -or nonempty-page lost-ACK inserts. - -Eleven unit cases feed the actual generic owner observation hook with synthetic -ACK facts and real resource-model cleanup. ACK plus failed cleanup preserves -the totals and retained ownership; no ACK remains zero. This is not genuine -PostgreSQL transaction/connection disposal-fault injection. Distinct scalar -listener projection is supplementary to actual-runtime producer qualification. -The transitive memory census includes the private recorder and rejects reached -SQL and an extra caller; exact typed field access and emitted compiler cache -owners remain pinned. The two source-review findings, a missing namespace import -and assertion-failure teardown path, are corrected before the first build. -The focused review has no remaining findings and supplies no full Step 9 credit. - -The CI-mode Release build has zero warnings/errors. All 384 Jobs unit, 52 focused -Architecture and four PostgreSQL cases pass with zero failures/skips. The final -366-source receipt is -`10600bb7dd16c847e74001e3e1af3b375dc1e1057cbdf6c0ea1caeaab073a6b5`. -Bridge/lease/late accounting, nineteen-rule enforcement, full regression, -unchanged CI-budget qualification and both full Step 9 reviews remain open. -No catalogue obligation is promoted by this slice. - -#### Bridge repair qualification - -The locked bridge candidate classifies prior acknowledged hint, expired prior -token without a hint, or unmarked state before replacing its token. Hint takes -precedence. Two fixed process totals count the disjoint marked-repair subsets -only after actual startup/native exit and a true fenced ACK return. Unmarked is -not first-ever work: a prior creation-failure deferral can clear its markers. -Deployment-mismatch deferral now counts only a true fenced status change. -The existing eight metric families and authority/source/grant boundaries stay -unchanged. - -Thirty-two PostgreSQL cases pass, including actual stock repairs for missing, -failed and succeeded vendor hints; old-marker precedence; an actual stale ACK; -and false mismatch deferral after real claim cleanup expires its fence. Two -runtime/stock-client cases project both repair cells through the live listener. -Their prior-hint setup uses a synthetic numeric hint, not a claimed earlier -stock creation; the separate stock repair cases cover that provider boundary. -Actual native startup/stop/join controls preserve zero repair counts while -ownership is retained. - -The real status-connection cleanup is held after its matching COMMIT. A separate -database read proves the vendor ACK while counters remain zero until the actual -bool call returns. A throwing Closed-event cleanup control instead leaves zero -visible ACKs and one retained logical owner; the actual native thread, observer -and test callback have ended. The bool API cannot expose the ACK hidden behind -cleanup failure, so no current-row inference backfills it. Exact locker/role -barriers and nested finally cleanup constrain these tests. - -The corrected CI-mode Release build has zero warnings/errors. All 384 Jobs unit, -six focused Architecture and 32 PostgreSQL cases pass with zero failures/skips. -The first build rejects a test-local variable-name collision, corrected without -runtime changes. Focused review also corrects the exact classification-getter -caller census before testing; no findings remain and no full Step 9 credit is -claimed. Exact typed fields, immutable classification and reached memory-only -observation remain guarded. The final 369-source receipt is -`ae0bb0721b6bce47230b38c07098cfa245a56fe51f16263d79a3e4254e62b799`. -Lease/late accounting, nineteen-rule enforcement, full regression, unchanged -CI-budget qualification and both full Step 9 reviews remain open. No catalogue -obligation is promoted here. - -#### First lease-loss observation qualification - -Two fixed process totals retain the first observed renewal refusal or elapsed -local lease per validated start publication or clean recovery receipt. The -execution's cause CAS precedes its Interlocked-only persistent parent recorder; -recording adds no task, source, grant, listener or execution authority. Existing -identity publication stays in place. Already-visible stop, settlement, join, -cleanup fault or permanent renewal closure suppress a new count. Gate observation -does not establish universal atomic ordering with concurrent host stop. - -The seven-case unit matrix covers refusal, actual timer callback after controlled -clock advance, stop, join, settled work, missing publication and repeated recording -while Run remains open. The latter distinguishes a real first-cause CAS from -duplicate suppression supplied by a separately closed gate. Existing held timer -Change/disposal controls preserve zero counts. Real renewal-owner PostgreSQL cases -distinguish a physical ACK from lost ACK plus original locked history. Actual -Outcome ACK with held cleanup, including stored recovery selection, remains zero. - -Eight recovery-timer cases use real acknowledged PostgreSQL acquisition and -actual held timer factory/Change handles. Six stop/fault cases preserve zero; -two advance only the local monotonic observation clock during a held lease timer -prefix, then observe one elapsed loss before identity publication and no provider -entry. These are controlled-clock proofs, not wall-clock lease-duration benchmarks. -Cleanup still owns the actual returned handle; a hidden failed handle remains -retained. They do not independently qualify expiry before recovery Bind or every -normal publication/renewal elapsed branch. - -All 519 selected Jobs unit and five focused Architecture cases pass with zero -failures/skips. The first PostgreSQL run passes eleven cases and finds two fixture -shutdown omissions: elapsed-only cases had not closed generation starts before -awaiting completion. After that test-only correction, all thirteen pass in -94 seconds. Production and Architecture/unit source hashes are unchanged between -receipts. The corrected CI-mode Release build has zero warnings/errors; scoped -fourteen-file format verification reports no changes. The initial build's helper -return-type analyzer warning is corrected. Focused source review closes an async -metadata/discarded-task enforcement gap with transitive scheduling rejection and -balanced dirty/restored controls. This is not either full Step 9 review round. - -The final 370-source receipt is -`8ef7ac676619345655f818c371ee63cbf995564009703bd9243408724862795e`. -Late settlement, nineteen-rule enforcement, full regression, unchanged CI-budget -qualification and both full Step 9 reviews remain open. All nineteen obligations -remain Registered. - -#### Actual late-settlement qualification - -Seventeen fixed `late_<stage>_settled` process totals distinguish an elapsed -stage from eventual positive cleanup of its actual invocation. Only the stage -clock records the effective elapsed-stage marker; host stop, lease loss, timer -fault and a returned wrapper wait cannot invent it. Consumption happens once, -after actual framework/execution, timer, cancellation-callback and private-resource -cleanup. The existing bound invocation forwards only a fixed Interlocked update. -No task, data source, grant, execution admission or new metric family is added. - -Each stage requires its actual typed task and positive cleanup. Recovery -confirmation follows the current NoPlan/retry/acquisition branch and never -substitutes an older clean probe. Whole-framework completion covers history and -NoPlan loops beyond their final SQL slot. These are settlement observations, -not durable ACKs, successful business outcomes, rollback or provider-quiescence -certificates. Permanently retained cleanup contributes no settled count. - -Five new classifier cases cover absent tasks, observer join, exact business -stage, current confirmation branch and positive disposition. A live Meter unit -case checks all seventeen fixed projections, zeros and repeated scrapes. Wait -controls preserve predecessor/prospective-stage semantics and zero markers for -host stop or timer fault. All 525 selected Jobs unit cases pass with zero skips. -Four real stock-worker/PostgreSQL cases pass: two held framework-scope paths and -two provider-recovery paths distinguish actual clock expiry from host stop. -The latter holds private cancellation cleanup after provider return and confirms -zero until release, then one elapsed settlement or zero for host stop. This is -not positive native coverage of all seventeen stage kinds. - -The initial five-case Architecture run passes both orchestration censuses and -singleton registration; two metric companions expose exact emitted `call` -opcodes where the new guard expected `callvirt`. After guard-only corrections, -all three metric cases pass. Additional framework-task/cleanup-field ownership -and a planted extra-cleanup-writer control also pass those three cases. No -production, unit or PostgreSQL source changes between these receipts. The -CI-mode Release build has zero warnings/errors; scoped eighteen-file formatting -reports no changes. Initial missing namespace imports are corrected before that -qualified build. Focused independent source inspections leave no open finding -and provide neither full Step 9 review round. - -The final 375-source receipt is -`7cd762f4870900a03420ed4e14b416d89d15eeddae890a98fb6b2d391f62c1cf`. -Nineteen-rule enforcement, shared workflow guidance, full regression, unchanged -CI-budget qualification and both full Step 9 reviews remain open. All nineteen -obligations remain Registered. - -#### Shared background-job workflow guidance - -The shared `add-background-job` skill now describes the actual typed scheduler, -explicit registry/catalog composition, ordinary transaction owner, external -prepare/execute/finalize and three-state failure policy, capacity declaration and -recurrence path. The common skill catalogue links it for every agent runtime. -A focused source review corrects release wording for known failed/cancelled but -quiescent effects, distinguishes capacity declarations from optional entitlement -keys, and preserves all seven framework requests when replacing empty defaults. -It provides no full Step 9 review-round credit or feature business definition. - -The preceding late-settlement commit's hook changes only six property-pattern -indents and one trailing blank line. Reconstructing the exact pre-hook bytes -matches its recorded hash; no semantic tokens change. Its test receipts remain -pre-hook source receipts, rather than a newly claimed post-hook test run. - -#### Production manifest and route qualification - -A single fresh structural census compares every disk-discovered production -project and each module's four assemblies with the loaded population. It pins -both empty-registry factory paths and catalogue implementations, rejects -business/recurrence constructors in scaffold modules (including delegate/async -forms), and checks frozen registry state. The actual Program provider separately -resolves both registries, catalogue aliases, seven framework requests, exact -pool/queue/worker topology and nonempty runtime/health/hosted registrations before -asserting empty business/tombstone/recurrence manifests and unopened sources. -Missing/duplicate registrations and valid nonempty fixture registries exercise -the same predicates; recurrence rejection remains independent of definitions. - -The actual fourteen-route/method/handler multiset includes eight public actions, -liveness, OpenAPI, Scalar UI and its three static assets. Real extra dashboard, -recovery, neutral-path and probe-controller endpoints fail that predicate. -Whole-production IL additionally pins all four endpoint-registration call sites -and concrete/inherited public controller actions, covering paths not executed by -the Development host. Pinned dashboard method/type and generic middleware -capabilities have dirty controls without adding a dashboard runtime dependency. -A focused source review closes conditional-route, default-dashboard-options and -inherited-action false passes; it is not either full Step 9 review round. - -Seven focused Architecture/corpus/discovery cases and the actual API composition -case pass with zero failures/skips. Sixteen actual PostgreSQL policy-selection -cases pass, including the added accepted nonrepeatable Failed outcome at admission -six and rejected false-exhaustion projection; SQL source is unchanged by later -guard corrections. The initial host assertion omitted Scalar's static assets; -its approved exact inventory now includes them. The corpus counter exposed four -previous observation companion methods absent from the prose tally; the -mechanically verified total is 254, including the new manifest method. The final -CI-mode Release build has zero warnings/errors. Three-file format qualification -reports no changes. - -The final 377-source receipt is -`532c29d65f6362a9ea6d25a3c3d2e30827baa19213211847429821748f457105`. -Constructor-time context proof, combined privileged capacity qualification, -complete nineteen-rule reconciliation, full regression/packaging/CI-budget proof -and both full Step 9 reviews remain open. All nineteen obligations remain -Registered. - -#### Constructor-time context and trace qualification - -A four-case real executor theory covers tenant-wide/organization work, each with -success or cancellation while its actual business task remains held. After real -routing/admission cleanup, observation-only fixture hooks capture parameter, -root-request and handler constructors plus Body entry/continuations. Every -mandatory capture sees the exact stored tenant/org, SystemActor, causal actor, -job/incoming identity, module and correlation. Both sampled ActivitySources retain -the stored causal trace: parameter/root observe `job.execution`, while handler -and Body keep their genuine MediatR child and execution ancestry. The unrelated -caller context and Activity retain their exact references throughout and after -actual cleanup. - -The same assertion rejects a real parameter construction before job ownership. -A separate trace-only capture at the genuine constructor preserves correct job -context but selects the caller Activity; context facts pass and the independent -trace predicate rejects it. These are oracle controls, not a claimed production -source-reorder mutation. Static hooks restore their exact prior values only after -the actual task becomes terminal. A failed bounded join supplies no cleanup -claim. Caller AsyncLocal isolation alone does not prove each explicit finally -setter; existing cleanup/Activity fault cases remain complementary. - -All 24 selected business PostgreSQL cases pass, including the four new cases, -with zero failures/skips in 17 seconds. The final CI-mode Release build has zero -warnings/errors and scoped two-file formatting reports no changes. Initial -generic-assertion/cancellation-forwarding analyzer warnings are corrected with -explicit intentional noncancellation of the held Body waits. Focused independent -source inspection finds no defect; it is not either full Step 9 review round. -No production context writer or execution authority changes. - -The final 378-source receipt is -`e77b70cd875f2b208d46deaac82f248b21e508dbcbd9bb5598a9b0030cf14a7c`. -Combined privileged capacity, complete nineteen-rule reconciliation, distribution -and full regression/CI-budget qualification, and both full Step 9 reviews remain -open. All nineteen obligations remain Registered. - -#### Published distribution gate qualification - -The existing backend CI job now publishes the actual Release API into a fresh -owned temporary directory, then runs both existing offline distribution -verifiers against that publish and its exact API/Infrastructure build graphs. -Failure remains gating; only JSON receipts join its test-result artifact. The -required job name, filters and twenty-minute ceiling stay unchanged. The kit -README documents the prerequisite Release restore/build/publish commands. - -A fresh local framework-dependent publish completes in 1.176 seconds. All four -stock shared DLLs, corresponding-source archives and licence/notice inventories -verify. Fifteen dirty distribution controls reject, and the recipient-modified -Core inspection succeeds without a runtime restriction. The original 178-file -publish remains byte-identical after controls. These checks take 0.801 seconds; -replacement inspection does not prove a modified assembly executes compatibly. -The exact new workflow shell block also passes locally, emits both JSON receipts -and removes its owned temporary publish. `actionlint` and diff checks pass. - -This is artifact/graph and workflow-step qualification, not API boot, full CI -success or proof that the entire job fits its unchanged ceiling. Combined -privileged capacity, complete nineteen-rule reconciliation, full regression and -both full Step 9 reviews remain open. All nineteen obligations remain Registered. - -#### Canonical obligation ownership alignment - -Fourteen existing test methods now carry their catalogue identifiers in place. -Their complete source bytes reverse to the prior files after replacing only that -one identifier: bodies, attributes, Theory data, traits and dirty companions are -unchanged. The two existing canonical owners and the three substantive manifest/ -constructor owners provide the other five names. Compiled Architecture and -Integration discovery finds all nineteen names with their real case rows. The -Architecture method total stays 254. CI-mode Release compilation has zero -warnings/errors; scoped fourteen-file formatting reports no changes. - -This is naming/discovery qualification, not a new executed-test receipt, a claim -that any one named method covers its full assertion, or catalogue promotion. -Each complete obligation also retains its schema, native runtime and fault -companions. Combined privileged capacity and complete regression/packaging/boot/ -CI-budget qualification remain pending before full Step 9 reviews and closeout. -All nineteen obligations remain Registered. - -#### Combined physical-capacity qualification - -The actual registered job runtime, outbox and delivery processors share the -captured keyed guarded source at Pooling=true/MaxPoolSize=52. Their actual -completion tasks remain bound; the fixture explicitly starts those instances, -without claiming GenericHost startup ordering. One real stock expiration -invocation waits on a unique-key conflict for its exact resource. An independent -observer identifies its backend through the setup transaction's blocking PID; -a finite caller wait expires while that actual invocation remains Retained. - -Two independently selected terminal-audit scopes forward the genuine writer and -hold cleanup after their actual terminal/MUST commits, before connection disposal. -Three distinct confined-role, tagged backend PIDs and all pending cleanup facts -are checked before and after TenantB's actual native job creates an organization, -commits its business/MUST row and reaches stock Succeeded. An absent-owner control -fails the same conjunction. Observers use a separate source. Finally every hold -releases, all three real owners join, Busy reaches zero, native server rows vanish -and the disposed tagged pool has no remaining backends. - -The [canonical ledger](../standards/05-database.md#shared-dispatcher-source-lifetime-and-capacity) -counts all current simultaneous/nested/retained owner classes.52 remains a -conservative supported floor, not a measured exact peak. Pinned source review -corrects an earlier planning premise: ordinary Worker state-lock disposal precedes -PerformJob, so its wrapper lifetime does not establish an extra nested checkout. -The existing actual composition51 refusal and maximum158 topology/cleanup proofs -remain complementary; no52-socket saturation or51 impossibility claim is made. - -Validation: CI=true Release build has zero warnings/errors. Four real PostgreSQL -cases pass with zero failures/skips, including the new combined case, both actual -messaging/source lifetime cases and retained-expiration native progress. The -closed382-file source receipt is -`b1fbb3344ff9df6f905937705a5c6ce493e59792f7facdccc947a8074aa9b451`. -The initial new-case run reached its business observer but failed on a test-only -text/UUID comparison; the corrected observer and all four cases pass on the final -receipt. Independent focused source review confirms the corrected expiration -physical witness, selective audit forwarding and actual joins, with no remaining -verified finding. This is not a full Step9 review round or complete packet -regression. All nineteen rules remain Registered pending that qualification. - -#### Step 9 full review round 1 (2026-10-18) - -Three fresh independent reviewers inspect `390515b8..d2bb2ee7` and the necessary -adjacent paths: runtime/security/ownership, enforcement/test falsifiability, and -corpus/composition/CI/distribution. The corpus reviewer also inspects the later -two-file frontend inventory correction. These are full Step 9 reviews; earlier -focused preflights do not count toward this round. Reviewers perform read-only -source inspections and do not claim independently executed regression results. - -No Blocker or Major is verified. One Minor finding identifies two live -observation summaries that still describe delivered stage/trace/lease/control -signals as pending. Both summaries are corrected and independently rechecked; -full packet qualification remains explicitly pending. All nineteen catalogue -obligations remain Registered. - -The complete non-Docker CI filter executes 3,043 passing cases with zero failures -or skips: 2,452 Unit, 410 Architecture, 177 HTTP Integration and four Contract. -Its local wall time is 1,641.70 seconds, with part of the run sharing the host -with Docker validation. This is not a hosted-runner benchmark or proof of the -unchanged twenty-minute whole-job budget. Repeated observation-body selection -inside a fresh detector evaluation is the next measured optimization candidate; -case identity, every mutation/restoration and the parallelism bound must remain. - -Full frontend typecheck, lint and build pass. Its first full test run exposes -unclassified offline Hangfire probe/kit files. An exact 32-path inventory fixes -that test-only classification; unknown probe/vendor/runtime paths still reject, -and runtime import modelling is unchanged. The corrected complete guarded test -run passes all 1,616 cases with zero skips/todos; corrected typecheck and lint -also pass. No application build output changes with these test-helper edits. - -The complete Docker complement is still running on the same frozen C# source. -It exposes an exhaustion-plan fixture whose entire population makes the broad -and narrow indexes equivalent, and a routing-wait observer that requires an SQL -suffix beyond PostgreSQL's default activity-text buffer. Source cross-checks -identify test-fixture defects, not demonstrated production failures. Corrections -and actual PostgreSQL reruns remain pending until this frozen run ends. A third -failure compares the latest schema to a historical predecessor while assuming -only the terminal-history function changes; later indexes invalidate that -premise. The correction will test the exact target/predecessor boundary and -retain a separate complete latest job-inventory round trip. Full -regression, demo/boot, CI-budget qualification, promotion and fresh full round 2 -remain open; this record does not declare Step 9 or P02b-4 complete. - -The completed Docker run executes 2,428 cases: 2,425 pass, the three identified -fixture cases fail, and none are skipped. Local wall time is 2,287.77 seconds; -this also supplies no hosted-runner or whole-job budget claim. The closed -382-file first-run receipt is -`1f44da4ddb710b882952141858a2a4fc49bf4e962ce9741c5ed1c3660eecf25c`. - -Corrections retain the real planner and exact exhausted-index assertion by adding -an independently counted due, zero-attempt population; stable cutoff and volatile -dirty-control bounds remain unchanged. The routing observer opens before the -operation and uses the exact blocking backend dependency, with absent/wrong-PID -controls and a genuinely pending operation before caller cancellation. The -rollback test retains singleton function differences at its exact target boundary, -then separately compares the entire latest job inventory. No production SQL, -lease/retry limit, migration, grant or schema exception changes. - -The observation traversal now groups actual bodies by reference-identical owner -once per fresh detector evaluation. Every original root, diagnostic and -clean/dirty/restored visit remains; the existing companion independently checks -actual group identity/order/multiplicity, linked async bodies and missing owners -through its real metadata mutations. No Fact or case is removed or added. - -CI-mode Release build has zero warnings/errors; scoped formatting reports no -changes. All twelve affected real PostgreSQL cases and eleven Architecture cases -pass with zero failures/skips, including the cache, credential, runtime, three -metric and five corpus guards. Their closed 383-file receipt is -`7337d9765902903797a50a222ad44adc41033444917c8a23e3d5ab2fb2bc3e95`. -Independent correction checks of all five C# files find no remaining issue; these -are round-1 fix verification, not full round 2. The runtime-lifetime case records -129.93 seconds versus 176.09 in the earlier full run, while the credential case -records 211.55 versus 204.60. Different cohorts/shared load prevent attributing -those durations to an isolated speedup or claiming CI-budget fit. Whole-job -qualification remains required without raising its ceiling. - -#### Canonical enforcement reconciliation - -All nineteen packet obligations now report Implemented in the -[catalogue](../standards/21-architecture-tests-catalogue.md#backgroundjob_submission_is_transactional_and_stamped). -Each status names its actual compiled canonical owner and links its exact source; -the full assertion also retains its structural, native runtime and PostgreSQL -companions. Ten canonical owners run in Architecture and nine in Integration, -including the actual Program composition case in the non-Docker partition. - -The closed first full run executes all 35 case rows of those nineteen methods -successfully. The later runtime-detector correction also passes its canonical, -metric, credential and independent mutation-equivalence cohort. This executed -evidence replaces the earlier discovery-only receipt; identifier alignment alone -did not authorize promotion. The three failed full-run fixture cases are -separately corrected and qualified as recorded above. - -The five corpus guards pass after promotion: 254 Architecture method declarations, -221 Implemented catalogue entries, 131 canonical Architecture entries and 90 -outside that assembly. Integration statuses name their own canonical class; -Architecture companions do not silently reclassify those rows. Link/fragment and -diff checks pass. Related live infrastructure/architecture summaries now reflect -implemented enforcement and the completed Step 8 reviews. Full Step 9 round 2, -demo/boot, packet closeout and exact PR-head CI/job-budget qualification remain -separate pending work. - -#### Step 9 full review round 2 (2026-10-18) - -Three new independent reviewers inspect the complete 150-path Step 9 range -`390515b8..720fca12` and necessary adjacent paths. Runtime/security/ownership, -enforcement/falsifiability and corpus/composition/CI/distribution lenses close -with no verified Blocker or Major. Reviews inspect source and existing receipts; -they do not claim independently executed regression or CI. - -Three deduplicated Minor prose inconsistencies are verified: the live catalogue -preface still calls promoted entries Registered, the glossary still calls stage -instrumentation remaining work, and the architecture summary still calls both -full reviews pending. Narrow corrections point to the owning status record and -retain the distinction between local qualification and packet/CI closure. Both -affected reviewers independently recheck the actual corrections and canonical -owners/counts, with no remaining verified finding. This is correction verification -within round 2, not another full review round. Both full Step 9 reviews and their -verified corrections are now complete. - -An inspected provider-stage `NeverStarted` label is not treated as a defect: -stage telemetry preserves the raw pre-checkpoint report, while the durable owner -still treats the unresolved report after ExecuteIntent as Unknown and grants no -quiescence, retry or release. The current observation contract distinguishes -those meanings; no runtime or vocabulary change is justified by this candidate. - -At that correction check, the catalogue, glossary and architecture hashes are -`35a184d078b587817fdffb1dcc07e2bb7ec332dbb8510adeac88548cc8aeae52`, -`b2597922840fa98a7992721f05de816565820a093f56133af27727999bdaa311` -and `bdaf367b047bed602dd8a2c4597eef90851b6f236522b3dd9e549b687a017494`. -These three prose corrections change no C#. The fresh complete non-Docker -rerun subsequently passes all 3,043 cases with zero failures/skips in 1,660.34 -seconds. Its closed 383-file source/artifact receipt is -`f6f01737022f2013483967ddbff89e06daa4abd2eea6dd1ffbeed7a7de80e3dd`. -This local result does not establish fit under the unchanged twenty-minute -whole-job limit; real PR-head CI/job-budget qualification remains required. - -#### Fresh demo and browser/audit qualification - -A fresh actual `development` checkout at `d2bb2ee7` contains no private root/web -configuration or previous demo artifact. Later commits change only tests and -documentation; the functional sources are unchanged. The normal seven-service -CI lifecycle restores, migrates, seeds, stops Keycloak, builds and boots the real -API/native HTTPS renderer, then exercises all nine linked seeded pages. The -earlier archive-only preparation boots successfully but cannot pass the required -Git source-provenance check because it lacks `.git`; that failed setup attempt is -retained separately and is not described as a product or audit failure. - -The actual clean-checkout `make demo DEMO_MODE=ci` exits zero in 662.69 seconds. -The proof completes in 582.168 seconds, within its unchanged twelve-minute bound. -All 27 JSON/HTML audit pairs and nine browser screenshots are present; every -automated accessibility score is 1, maximum normalized gzip JS is 106,575 bytes -and maximum CLS is zero. English catalog and Turkish lesson screenshots are also -visually inspected. These checks preserve earlier human/VoiceOver evidence and -do not claim a new complete manual accessibility audit. - -The nine LCP medians remain advisory at 2,012.61–2,197.74 ms against the existing -1,500 ms warning threshold; response-time and blocking-time medians raise no -warning. No timing advisory is relabeled a hard-gate success. Cleanup passes: -owned processes stop, the disposable Compose project is empty, private files, -environment and lock disappear, and application ports are free. Only sanitized -receipt/report/screenshot artifacts are retained. Artifact/graph distribution -verification and real API boot are separate evidence; this demo runs the normal -Release build output and does not claim modified-library or publish-folder -execution. Real PR-head CI and whole-job budget qualification remain pending. - -#### Final completion-budget scan qualification - -After the second full review and the completed 3,043-case run, a source-only -performance correction replaces six whole-instruction walks for three owner -budget fields with the existing fresh field-name index. Exact declaring identity, -opcodes, private/instance declarations, permitted/forbidden owners and duplicate -write counts remain. The standalone canonical Fact opens the same disposable -detector scope already used by each mutation evaluation. No Fact, case, mutation, -restoration, production subject, filter, timeout or concurrency bound changes. - -Independent applied-diff inspection verifies both hunks and all 35 unchanged -mutation call sites/fixtures. CI-mode Release build has zero warnings/errors and -scoped formatting reports no changes. All eight canonical, actual owner-mutation, -independent instruction-index and corpus cases pass, zero failures/skips, in -110.92 seconds. Their names match the preceding complete-run receipt. The owner -mutation case records 109.69 seconds versus 186.35 in that earlier full cohort; -different cohorts/load prevent claiming an isolated causal gain or CI-job fit. -The closed 383-file source/artifact receipt is -`e39d6d9a101b8d5b56246f262dd946c8ec82206c75db9bfd603ce363a6610dbe`. -This is qualification-correction verification, not a third full review round. -Real exact-head CI must still qualify the complete unchanged job budgets. - -### P02b-4 local closeout (2026-10-18) - -**Local implementation and review complete; [PR #32](https://github.com/HodeTech/LearnStack/pull/32) open.** -All nine approved steps are delivered on `development`. Every step completed both fresh -independent review rounds and its verified correction checks. The full Step 9 -rounds and final qualification corrections are recorded above; focused checks do -not count as additional full rounds. Accepted ADR bodies/metadata and earlier -as-of receipts remain intact. - -| Step | Delivered | Implementation / two review rounds | -|---|---|---| -| 1 | Typed contracts, closed registries and ordinary authority ceiling | Complete / complete | -| 2 | Authoritative/vendor storage, exact grants and guarded bootstrap | Complete / complete | -| 3 | Immediate transactional submission, trusted stamping and committed admission | Complete / complete | -| 4 | Recoverable wakeups, independent pools and owned lifecycle/cleanup | Complete / complete | -| 5 | Existing transaction owner, fenced completion and atomic terminal MUST audit | Complete / complete | -| 6 | Cross-instance tenant capacity and quiescence-bound reservations | Complete / complete | -| 7 | Durable external prepare/execute/finalize and known-failure policy | Complete / complete | -| 8 | Durable UTC recurrence and recipient-bound tenantless fan-out | Complete / complete | -| 9 | Complete observation, nineteen enforcement owners, skill/distribution and regression | Complete / complete | - -LearnStack state remains authoritative; stock Hangfire carries only opaque wakeup -references. Production business and recurrence manifests remain empty. The actual -Program manifest/route census, context restoration, transaction/terminal witnesses, -capacity and external uncertainty, recurrence/fan-out, grants/RLS and real worker -proofs back the nineteen Implemented catalogue obligations. The catalogue records -221 Implemented rules: 131 Architecture and 90 elsewhere, with 254 Architecture -method declarations. Discovery-only alignment was not used as executed evidence. - -**Local validation.** CI-mode Release build passes with zero warnings/errors; -scoped formatting passes. The final complete non-Docker command before the last -test-only optimization passes 3,043 cases, zero failures/skips: 2,452 Unit, -410 Architecture, 177 HTTP Integration and four Contract. Its closed receipt is -`f6f01737022f2013483967ddbff89e06daa4abd2eea6dd1ffbeed7a7de80e3dd`. -The completion-budget correction receipt above qualifies the final changed -detector and unchanged case identities. Local command duration remains explicit -above; it is not substituted for the unchanged real CI job limit. - -The full Docker complement executes 2,428 cases, with three fixture failures -retained honestly in the first receipt. All three are corrected without changing -production code or test limits; twelve affected real PostgreSQL cases then pass -with zero failures/skips. The source is frozen separately for each run. No fully -current all-green local Docker rerun is claimed; the actual PR-head integration -job must execute the whole complement. Frontend typecheck/lint/build and all -1,616 guarded tests pass, zero skips/todos. The fresh real demo/browser/audit and -complete cleanup receipt is recorded above. Packaging checks qualify the actual -publish artifacts/dependency graph, both offline verifiers, replacement-source -kit and dirty controls; actual normal Release API/native-renderer boot is proved -separately by the fresh demo. No modified-library execution is claimed. - -All PR commit messages pass the actual strict hook. ADR lifecycle, relative -links/fragments, source/count/no-skip guards, workflow lint and diff checks pass. -The working branch remains `development`; protected stashes are preserved. - -**Accepted limits and next owner.** ADR-0059 permits a whole pool to wait until -actual work/cleanup ends; ADR-0060's bounded unsafe startup/unwind class can kill -the API process. Neither process exit nor lease expiry releases uncertain -external reservations. Phase 03 owns operator recovery permissions/routes and -privileged execution; Phase 04 owns actual media adapters/process-tree quiescence; -Phase 11 owns mapped readiness, supervision/dumps, retention and measured -production capacity. P02b-8 still owns the erasure inventory. These are the -Accepted workload boundaries, not undisclosed unfinished P02b-4 mechanisms. - -The next packet is **P02b-5 API authentication**, beginning with G10/G11/G12 -(client), G14 and G20 decision review. No authentication/session implementation -starts in this closeout. P02b-5–8 and the overall Phase 02b exit remain open. -Real exact-head seven-job CI, its unchanged duration ceilings and the maintainer's -PR review/merge remain separate; this local closeout does not claim them passed. - -#### PR handoff and current CI ownership - -[PR #32](https://github.com/HodeTech/LearnStack/pull/32) opens `development` → -`main`, based on `ed60157c14d33fad926fd201b49c08e2d24eed1f`. The locally qualified -implementation is committed at `199b033e`; this handoff adds only documentation. -The closed C# receipt above remains byte-identical after normal commit hooks. - -The PR's [live checks](https://github.com/HodeTech/LearnStack/pull/32/checks) own -current exact-head CI results, durations and downloadable artifacts. The initial -[run](https://github.com/HodeTech/LearnStack/actions/runs/39120117263) starts on -`199b033e`; a subsequent documentation push supersedes that unfinished run and -requires a fresh complete check set. No partial or superseded result establishes -final-head success. All seven required names and strict freshness remain enabled; -backend, integration and demo keep their unchanged twenty-minute job ceilings. -The maintainer owns PR review and merge; no merge is claimed here. - -#### Hosted CI qualification follow-up (2026-10-18) - -The completed [run 39120501520](https://github.com/HodeTech/LearnStack/actions/runs/39120501520) -at `2e1d227ad1e0150fcbdcbde8df6d68374dc2f682` is **failed**. Frontend, -meta, secret scan and OpenAPI pass. Backend and integration reach their unchanged -twenty-minute ceilings; backend's completed TRXs retain 2,452 Unit, 177 HTTP and -four Contract passes, with Architecture unfinished. Integration has actual early -native-supervisor failures as well as cancellation; no complete Docker TRX passes. - -The actual native preflight reports `collector_pipe` on the hosted kernel. -Zero inherited core limits do not qualify a piped collector. Earlier topology -failures may race that refusal, but their precise endpoint states are unrecorded. -[ADR-0062](../decisions/0062-native-crash-proof-ci-provisioning.md) proposes explicit -disposable-VM provisioning authority; it is not accepted or implemented. ADR-0060 -does not allow a failed precondition to authorize a host-wide setting change. - -The demo hits its separate sixteen-minute outer setup/proof budget during final -report handoff; its inner proof lasts 659.906 seconds. Twenty-seven clean report -pairs on disk do not repair the incomplete 26-row accepted receipt. Cleanup is -confirmed; the run remains failed. Independent corrections address repeated -architecture identity work and duplicate migration/API builds, preserving all -cases, assertions, complete filters and existing deadlines. Final exact-head -hosted success remains pending. The earlier local receipts and completed review -rounds retain their stated scopes. - -The demo correction is committed at `bc3691fb`: normal migration entry performs -one fresh Release API build before all unchanged EF chains consume that build, -and the demo launches the resulting API without a duplicate build. Nine executed -Makefile controls cover freshness, chain discovery/order and sticky failures. -The guarded frontend suite passes 1,625 cases with zero skips/todos; typecheck and -lint pass. A fresh Git clone at that commit completes the actual CI-mode demo in -658.115 seconds: setup 71.168 seconds, proof 575.766 seconds and confirmed cleanup -10.686 seconds. All 27 accepted report pairs and nine screenshots are present; -maximum normalized gzip JavaScript is 106,574 bytes, CLS is zero and all 27 -accessibility scores are one. Nine LCP medians remain advisory warnings. Owned -processes/containers, private configuration and locks are removed. This local run -overlaps Architecture CPU work and does not establish hosted budget fit or new -manual accessibility evidence. - -The first census correction completes the unchanged non-Docker filter with 3,043 -passes and zero skips: 2,452 Unit, 410 Architecture, 177 HTTP and four Contract. -Every case identity matches the preceding full run. Its closed 383-file C# receipt -is `c367357d21cf39ae2d339b0d166651a5969891cb1d6c55a4c1a7bbaad22dc9e0`. -Local duration is 1,565.200 seconds; this is not a passing twenty-minute CI claim. -A subsequent measured-cost correction uses fresh per-evaluation instruction/name -indexes while retaining exact identities, opcodes, duplicates, all original -mutation controls and independent raw-traversal comparisons. It additionally -requires the actual authority detector to reject an unrelated detached target. -Plain fixture setup SQL uses the same real PostgreSQL through an owned nonpooled, -non-enlisting connection; the roles script retains its actual `psql -f` path. -The four added transport rows and 311 existing role/guard/migration/provider cases -pass together (315 passes, zero skips, 73.715 seconds). They verify actual roles, -ambient isolation, intact batches, rollback and observed physical-session exit. -The short server-cancellation row does not prove expiration of the helper's own -thirty-second deadline. Independent targeted source reviews find no blocking or -major defect; they are correction checks, not another full Step 9 review round. -The latest ten selected Architecture cases also pass with zero skips in 390.999 -seconds, including actual authority/application-source/runtime mutations, exact -raw/index parity and the catalogue/Docker-trait controls. Their requested case -identities match exactly. These and the 315 PostgreSQL cases close the unchanged -385-file C# receipt -`919b1ef74b5b6d456abd628ac6e664f5f61fbd9c6184fde9737234a219dd259c`. -The Release build has zero warnings/errors; scoped whitespace formatting is clean. -PostgreSQL qualification overlaps Architecture CPU work; these subset timings -are not causal speedup measurements. Final hosted full-filter results remain -pending; no complete current Docker run or seven-check success is inferred. - - -##### ADR-0062 revision and read-only baseline (2026-10-18) - -The maintainer's review requests changes; it is **not approval** of ADR-0062. -The revised [proposal](../decisions/0062-native-crash-proof-ci-provisioning.md) -selects a dedicated native-proof VM, verified fixed-pattern setup without -restoration, and complete native/ordinary Docker partitions behind the existing -fail-closed required result. It preserves seven required names and each existing -twenty-minute execution ceiling. Host changes, the partition and its launcher -remain unimplemented pending approval. The unmeasured 17:30/150-second allocation -is withdrawn; actual fit remains a qualification gate. No Accepted ADR body or -protection setting changes in this proposal pass. - -Two fresh independent targeted proposal reviews cover governance/authority and -CI/process/coverage ownership. Both find no Blocker/Major; the first review's -container-versus-VM wording is corrected. The final CI review has no remaining -finding. These are proposal reviews, not a third full Step 9 round or hosted -qualification. Private research also executes an isolated unprivileged -.NET 10.0.10 nondumpability spike against the existing file collector: every exec -resets the flag, per-child set/readback succeeds, actual FailFast gives SIGABRT -without cleanup markers, and the benign twin keeps both. No pipe is installed or -exercised; the pre-managed startup interval is not qualified by this experiment. -The ADR records that narrower alternative and its boundary rather than claiming -host mutation is technically unavoidable. - -[Run 39131069558](https://github.com/HodeTech/LearnStack/actions/runs/39131069558) -measures source `0fe0db2b5b584d141fc2c37aeeaf102f8ba0781c` with read-only observation -and the unchanged complete filters. Its PR merge checkout is -`c705ea2eaa39df1c1ccafc0ee67b615b573383a1`; artifact metadata ties it to that source. -There is no provisioning, changed collector, new partition or shortened deadline. -The actual observation classifies `systemd_coredump`, four CPUs, VM present, -container markers absent, noninteractive sudo available, writable proc mount but -no caller write access, inherited host soft core zero/hard unlimited, and an -empty readable all-state Docker baseline. These are closed observations, not -exclusive-VM attestation, successful-write evidence or child-limit qualification. - -The full Docker command is canceled at the twenty-minute job ceiling. Console -retains 629 recognized completed rows: 600 passes and 29 failures. Six direct failures report -native supervisor refusal; 23 phase failures comprise fifteen exact pipe refusals -and eight membership failures. The latter's endpoint states are still unknown; -do not relabel them. Ordinary completed rows continue until cancellation, but no -complete Integration TRX exists; three zero-selection assembly TRXs do not supply -that missing evidence. The full non-Docker command also reaches its ceiling after -16:21 in tests and 3:52 setup/format/build. Its final TRXs confirm 2,452 Unit, -177 HTTP and four Contract passes with zero skips; Architecture retains 346 -completed passing console rows but no final TRX. No complete Architecture/job -result or budget fit is inferred from those partial rows. - -Meta, secret scan, OpenAPI and demo pass. The actual demo retains all 27 accepted -report pairs, nine screenshots, maximum normalized gzip JavaScript 106,551 bytes, -CLS zero and all 27 accessibility scores one. Setup is 173.023 seconds, inner -proof 653.561 seconds and confirmed cleanup 12.742 seconds; whole job is 15:04. -This supersedes no historical failed demo receipt and supplies no new manual -accessibility claim. - -Frontend's hosted run has 1,564 passes and one source-census failure: the two new -CI-only Python files lacked explicit non-runtime classification. All nine new -Makefile cases pass on actual hosted Ubuntu. Commit `641ba365` adds only those two -exact paths; the unknown-Python rejection and runtime import graph remain intact. -The corrected local guarded frontend runs all 1,625 cases with zero skips/todos; -typecheck/lint pass. This local correction is not a passing hosted frontend result. -Final full-source CI remains red; native authority approval and independently -measured backend/Docker budget corrections still block PR closure. - - -A subsequent independent budget correction retains typed owners until the capacity -and recipient detectors select their actual targets, and formats recipient field -writers only for the two target-type families the detector actually consumes. -Global detached-target checks, exact assembly/signature/opcode/duplicate checks, -all existing mutation schedules and fresh per-evaluation caches remain intact. -Three standalone recipient checks use the same disposable evaluation scope. -An independent applied source review has no finding. The CI-mode Release build -has zero warnings/errors. All 29 selected capacity/recipient rows, raw/typed/index -parity companion and five corpus guards pass with zero skips in 191.804 seconds; -case identities exactly match the previous complete run. The unchanged 385-file -source receipt is -`c2521f3b2fe67289f796c9442e77f0977f96a9ec6272d2bfa39f7ef3e8d96c09`. -These local subset timings are not a causal speedup measurement or a full hosted -budget result. Other completed hosted cost evidence and repeated fresh-database -migration work remain assigned to P02b-4's active CI qualification; no case, -required check, timeout or production behavior is removed to obtain a pass. - -The complete unchanged non-Docker filter at `82d5307c` subsequently passes all -3,043 cases: 2,452 Unit, 410 Architecture, 177 HTTP and four Contract, with zero -skips and the exact previous case-identity multiset. The closed unchanged -385-file C# receipt is -`6ee75c41c60c1f4f48d7e096834b43f5e7c54574d2a90cc10d4e56acab0fdfe0`. -Local test-command duration is 1,221.712 seconds, excluding hosted setup and -artifact work; this does **not** qualify the twenty-minute whole-job budget. - -A separate local setup measurement invokes the existing fresh database CREATE, -all five real migration chains and DROP six times on one owned fixture. The cold -migration observation is 0.770250 seconds; five subsequent observations have a -0.296865-second migration median and a 0.317290-second CREATE/migrate/DROP median. -The first scratch run's empty receipt is rejected; after correcting only its -writer initialization, all fixed numeric stage rows and successful disposal are -verified, with no new container remaining. The CSV receipt hash is -`15cb39f977c200bb5374819dfa7b21610ba071f5899edfdea4b1feadb8b29c1a`. -This private measurement is not a committed regression, per-test seed/host/body -measurement, template-equivalence proof or hosted fit claim. No template path is -adopted from it. A collection-only parallelization is also rejected: distinct -databases leave shared mutable dynamic hooks and Hangfire filter restoration -exposed to races. The original serial proof semantics remain intact. - -A further narrow source-cost correction selects the three concrete completion -owner writes from the existing fresh field-name instruction index. Exact full -constructor identity, attached type, opcode, multiplicity, task constructor and -live instruction adjacency checks remain unchanged. Two independent targeted -source reviews find no issue. The CI-mode Release build has zero warnings/errors; -all twelve selected pool, metric, tracing, credential, raw/index-parity and corpus -cases pass with zero skips and unchanged identities in 106.375 seconds. Their -closed 385-file C# receipt is -`1da1475eb0d13b473007d10bbc69047903b7140c6a3a3081b8d814e9a115351e`. -This correction has focused validation; the complete 3,043-case receipt above -belongs to the preceding `82d5307c` source. No new full-run or hosted budget result -is inferred, and ADR-0062 remains Proposed pending maintainer approval. - -##### ADR-0062 acceptance and CI implementation (2026-10-18) - -The maintainer explicitly approves revised ADR-0062 at `51346376` and authorizes -implementation on `development`. Acceptance and ADR-0060's dated disclosure are -committed before dependent CI code. The exact required integration name remains -`backend integration (Testcontainers)`; it becomes a fail-closed aggregate of -both complete Docker execution jobs. The other six required names, strict -protection settings and twenty-minute execution ceilings remain unchanged. - -This follow-up implements one coherent CI boundary: closed provisioning and its -offline meta controls; native process/cgroup ownership, complete complementary -partition and result validation; then actual hosted qualification with complete -artifacts and measured failure-cleanup reserve. It receives two fresh independent -review rounds, with verified findings fixed and committed before final CI closure. -Existing native child assertions and all ordinary test cases remain mandatory. -No passing hosted result, new catalogue enforcement or completed implementation -is claimed by this acceptance. The earlier failed and source-specific local -receipts remain historical evidence; native separation alone is no budget proof. - - -###### Native CI implementation and local qualification - -Acceptance commit `c4e64b52` precedes this implementation. The closed provisioning -owner validates copied scalar workflow identity, actual platform/checkout, -container/VM evidence, empty all-state Docker baseline and eligible collector -before privilege. It independently compares actual reads and verifies either -no-change or the one fixed literal write. Sixteen offline copied-owner subprocess -controls pass; no developer host setting is changed by those controls. - -The native launcher owns finite execution/cleanup/export allocations, a delegated -non-root systemd unit and separate supervisor/work cgroups. The live supervisor -retains the work subtree until actual child join and an existing populated-zero -witness; unit disappearance is not proof. Ordinary Docker receives equivalent -process ownership on its separate VM, with no collector provisioning. The same -required integration name is an always-running fail-closed aggregate of both -successful, complete matching artifacts. The launcher's 203-second reserved tail is an allocation, not measured fit. -Twenty offline launcher/result controls pass, including actual subprocess, -setsid, live/missing cgroup, precise discovery IDs, sanitized TRX, incomplete -aggregate, bounded export and composed pre-privilege collector controls. Actual -hosted ownership, failure-tail -measurements and whole-job fit remain pending. - -The CI-mode Release build passes with zero warnings/errors. Nine selected source, -corpus and native predicate cases pass with zero skips; no canonical rule or test -method count is added. The source census covers qualified/partial identities, -shared traits, actual launch markers and transitive declared helper dependencies, -with planted dirty and clean controls. It does not prove arbitrary dynamic-call -analysis. The unchanged all-source snapshot covers 1,209 C# files; its snapshot-file -hash is `91e9be8b8c7fb77954ed70638168ace4dabd761283526d8b0b19a8eaa7120b27`. - -Fresh actual Release discovery selects 2,432 Docker case IDs: 31 native and 2,401 -ordinary, disjoint and complete; the other three test assemblies select none. -Twenty display-name collisions make a name-only set insufficient. The launcher -parses only bounded identities from private VSTest protocol diagnostics; raw -serialized theory inputs are not export artifacts. - -The complete local native partition passes all 31 cases with zero skips and exact -fresh-discovery IDs, including benign twins and actual same-child mutants over -real PostgreSQL. Its test interval is 166.889 seconds. The source snapshot stays -unchanged; no new container remains and all 22 pre-existing container states are -unchanged. Its TRX hash is -`1cc3004dd5d67f18a577088bc52a06cd80e91e7ed984037dca63eb20750e63f7`. -This qualifies the existing local native fixture, not hosted provisioning, -systemd delegation or either twenty-minute whole-job path. - -Guarded frontend validation passes all 1,625 cases with zero skips/todos; -typecheck and lint pass. Only the four new CI Python paths gain exact non-runtime -classification; unknown paths and runtime import coverage remain guarded. Seven -ADR-parser and five read-only observer controls, actionlint and changed-document -links/fragments pass. Two fresh follow-up review rounds and actual final-source -hosted qualification remain pending; PR #32 stays open and no merge is claimed. - - -###### Native CI follow-up review round 1 - -Commit `ee11bc94` contains the coherent implementation after acceptance -`c4e64b52`. Normal commit hooks pass and preserve all 24 validated source hashes. -Two new independent reviewers inspect the exact committed boundary through -process/authority and coverage/corpus lenses. Their four findings are verified -against that source before correction: - -- A failed optional preflight-log inspection drops the already bounded topology - facts from the exported reason. The exact topology form now permits an absent - preflight suffix while retaining its finite fields and refusal allowlist. -- A contradictory positive TRX skip counter is accepted and then erased by - sanitization. Counter parsing now checks nonnegative values, row reconciliation - and zero error/skip/incomplete buckets before projecting a file for export. -- Display-name-only interrupted records cannot distinguish 20 duplicate display - rows. The private incremental VSTest execution stream now supplies actual - assembly/case IDs, outcome and duration independently of final TRX. -- A statically declared instance-extension helper escapes the source closure. - Its planted dirty control fails the original detector; source method symbols, - reduced extension declarations and ambiguous candidates now retain the helper - edge. An unrelated same-named extension remains a clean control. - -The extension correction builds with zero warnings/errors and all seven selected -source/corpus controls pass with zero skips. This modifies only the Architecture -source file; all native fixture and production C# files remain unchanged from the -31-case local native proof. No extra rule or test method is added. - -Twenty-four corrected Python controls pass, including interrupted colliding IDs, -partial event lines, completed tails, missing/duplicate/wrong identities, truthful -failed rows, contradictory counters and missing optional diagnostics. The actual -pinned runner also executes the two existing pure native predicates with -`RunConfiguration.BatchSize=1`; each result arrives in its own StatsChange event, -and the real parser's five-field records exactly match both actual TRX rows. -Without that setting this small run delivers results only at Completed. Raw -execution diagnostics remain private. The setting changes event batching, not -case membership or assertions; nonempty projects receive distinct private streams -and zero-case projects retain complete discovery coverage. - -This narrow wire experiment and offline controls do not qualify the hosted unit, -provisioning, full ordinary partition or tail budget. The -[VSTest 17.12 configuration](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.ObjectModel/RunSettings/RunConfiguration.cs) -and [result cache](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.CrossPlatEngine/Execution/TestRunCache.cs) -are the pinned source basis. The corrected commit and a second fresh independent -review round still precede actual hosted qualification; PR #32 remains open. - -###### Native CI follow-up review round 2 - -The round-1 correction is committed at `779b6007`. Two fresh independent -reviewers inspect the complete acceptance-to-correction boundary: GPT-6-sol -xhigh reviews runtime/authority and GPT-6.1-sol xhigh reviews proof/partition -and corpus claims. The runtime review reports no verified finding; the proof -review identifies two additional issues, both verified before correction: - -- GitHub's absent job-services context serializes as `null`, while both owners - accept only an empty object. Both now accept exactly those two empty forms; - missing, malformed, non-object and nonempty service contexts remain refusals. - Copied-owner controls exercise the real absent-services input before launch. - All 17 provisioning and 25 launcher controls pass. -- A native call under a compiler-defined conditional symbol is invisible to - a parser with no defines. The source census now reuses the existing bounded - MSBuild symbol reader against the actual Integration Release project, - including SDK implicit defines. Whole-class and method-body controls under - `NET10_0` and `TRACE` reject unclassified callers; inactive `DEBUG` source - remains a clean control. The planted control fails the original parser. - -The corrected Release build has zero warnings/errors; all seven selected -source/corpus cases pass with zero skips. Scoped whitespace verification passes -with the separately reported workspace-loading warning. No native fixture or -production C# source changes in this correction, and no rule/method count changes. - -The actual complete 31-case native fixture also passes with private incremental -execution diagnostics and `RunConfiguration.BatchSize=1`. All five exported fields -for every result match the final TRX exactly, including fresh-discovery IDs; -there are zero skips, zero remaining new containers and unchanged states for -all 22 pre-existing containers. The TRX hash is -`03e826a07d94e06ec22f748ca80586eef1fe709de279a4914d29569c21729bf9`. -This is a local fixture/protocol receipt, not hosted systemd/provisioning, -ordinary-workload or whole-job timing qualification. Both full independent -follow-up rounds are complete; verified corrections and final-source hosted -qualification still precede PR closure. PR #32 remains open and unmerged. - -###### First hosted split qualification and meta control correction - -Source `6daa9a1c` is pushed normally on `development`; PR #32 remains open. -[Run 39140874785](https://github.com/HodeTech/LearnStack/actions/runs/39140874785) -starts actual hosted qualification. Independent API readback confirms all main -protection settings, including seven required contexts and strict mode, are -unchanged. - -The meta job passes all 17 provisioning controls, then exposes a synthetic-file -race in the launcher suite: a forked fixture child truncates its fake -`cgroup.events` before writing `populated 0`, while the owner reads concurrently. -The strict production parser correctly refuses the impossible empty snapshot. -The fixture now publishes the complete snapshot through same-directory atomic -replacement; production checks are unchanged, and missing/malformed-event dirty -controls remain. All 25 launcher controls pass after correction. An independent -focused review confirms the race and correction without broadening the owner. -This correction does not make the failed meta receipt pass; final-source hosted -qualification remains required. Other jobs continue to measure their actual paths. - -The native job builds successfully with zero warnings/errors, then refuses -before collector provisioning or test launch on `unexpected_crash_artifact`. -Its read-only environment receipt confirms an empty Docker baseline and -`systemd_coredump`; the retained receipt does not identify the matching file. -No legitimate source/build candidate is established, and no exclusion is added. -The scanner retains its exact roots, predicates, deadline and strict refusal, -using NUL-delimited private output to classify only a finite root/name category -in the refusal. Paths, contents and provider text are not exported. All 26 -launcher controls pass; an independent focused review confirms that nonempty -or malformed candidates still refuse. Actual hosted requalification remains -pending; this diagnostic correction supplies no passing native proof. - -###### First split-run result and bounded topology proposal - -Run 39140874785 completes with failure on source `6daa9a1c`, merge checkout -`853678c01c2c877e8bf5d7f81f559fc86ffbc9c4`. Backend reaches its twenty-minute -ceiling: complete TRXs contain 2,452 Unit, 177 HTTP Integration and four Contract -passes with zero skips; Architecture has no final TRX. Its 152 recognized passing -console rows do not qualify the remaining population or a complete run. - -Ordinary Docker discovers all 2,401 cases and records 503 distinct passing case -IDs before `deadline_exhausted`; 1,898 cases remain censored. There is no final -Integration TRX. Failure cleanup positively joins its owned workload in the -recorded 0.475-second path, with forced cleanup and no successful natural Docker -disposal claim. The aggregate correctly fails. This is measured failure of the -current arrangement, not permission to change timeouts or omit cases. - -Frontend passes all 1,625 cases and its ingress proof; OpenAPI and secret scan -pass. Demo's verified artifact contains 27 JSON/HTML report pairs, nine screenshots, -accessibility 1 throughout, CLS 0 and maximum normalized gzip JavaScript 106,553 -bytes. Its setup/proof intervals are 182.954/658.518 seconds; 10.647-second owned -cleanup passes. These successes remain specific to this source. - -Corrections `14584012` and `37ff4c59` are pushed normally after that run finishes. -[Run 39142456800](https://github.com/HodeTech/LearnStack/actions/runs/39142456800) -requalifies the separate meta/native corrections. Meta, frontend, OpenAPI and -secret scan pass. Native still refuses before provisioning/test launch; its new -closed reason is `unexpected_crash_artifact_docker_dump`. The actual matching -file/format remains unknown. No candidate is excluded, no host setting is -changed and no native hosted pass is claimed. - -A further read-only diagnostic invokes fixed `/usr/bin/file` only for the -private NUL-delimited candidate and maps its captured description to a finite -format label. It shares the original scan's twenty-second allocation. Every -candidate still refuses, including unknown formats and failed/timed-out probes; -no description, path or contents are exported. All 26 launcher controls pass, -and an independent focused review finds no defect. Actual classification and -native hosted qualification remain pending; this adds no collector authority -or file exclusion. - -Diagnostic commit `b4ee65b2` is pushed normally with the Proposed ADR-0063 -documents. Run 39142456800 is superseded/canceled after its independent -meta/native observations; no complete backend/ordinary result is inferred. -[Run 39143417261](https://github.com/HodeTech/LearnStack/actions/runs/39143417261) -again passes meta, frontend, OpenAPI and secret scan. Its native job builds -successfully but refuses before provisioning/tests on -`unexpected_crash_artifact_docker_dump_unknown`. Further fixed diagnostic labels -distinguish Docker storage regions and common formats/probe refusal, without -changing scan traversal, predicates or any failure decision. All 26 controls -pass and independent focused review approves. The candidate remains unexplained; -no allowlist, deletion, shard implementation or passing native result is claimed. - -Diagnostic source `d39233d5` starts -[run 39144033895](https://github.com/HodeTech/LearnStack/actions/runs/39144033895). -Meta, frontend, OpenAPI, secret scan and demo pass. Native still refuses before -provisioning/tests, now classified as an overlay-area `.dump` with generic binary -data format. Neither its contents nor image ownership is established by that -classification. Ordinary Docker records 146 passing case IDs before -`owned_completion_missing`; its failed receipt records forced cleanup and a -positive cleanup-ownership witness, not successful execution or natural Docker -disposal. No final Integration TRX exists. This early failure is distinct from -the earlier measured deadline exhaustion and remains under investigation. - -The next read-only diagnostic compares the private candidate's canonical path -with exact-ID-bound image-layer metadata from the fixed local Docker socket. -Only classic `overlay2` at the expected root is understood; stable inventory and -canonical paths are required. Only finite match/no-match/unavailable labels can -leave the owner. Every crash candidate still refuses, including a positive -image-layer match; no path is pruned or declared benign. A separate closed -workload-error fact supplements a failed ownership receipt without replacing its -failure or supplying completion evidence. Malformed ownership remains a failed -receipt; a planted control first exposes an unguarded cleanup shape and then -passes after the explicit dictionary guard. The provisioning owner is unchanged. -All 30 launcher controls, the unchanged 17 provisioning controls and seven ADR -parser controls pass. The independent focused source/proof review verifies the -corrections and reports no remaining finding. This is offline diagnostic -validation; actual hosted provenance, workload cause and full qualification -remain pending. Main protection is independently read back unchanged in full, -including strict mode and all seven required contexts. - -Source `f53c36fc` starts -[run 39145489321](https://github.com/HodeTech/LearnStack/actions/runs/39145489321). -Meta, OpenAPI and secret scan pass. Its native job still deliberately refuses, -but now positively binds the private candidate to a presently inspected image -layer: `unexpected_crash_artifact_docker_overlay_dump_binary_data_image_metadata_match`. -This proves that candidate's path provenance on that source, not its content or -earlier runs' files. Docker's -[classic overlay2 documentation](https://docs.docker.com/engine/storage/drivers/overlayfs-driver/#image-and-container-layers-on-disk) -distinguishes image lower layers from the separate writable container layer. - -The resulting applicability correction retains the first scan unchanged. Only a -fresh, stable exact-ID image snapshot containing that same candidate authorizes -a second scan over every original root, pruning solely verified existing image -`diff` directories. A complete matching snapshot after that scan is mandatory -before a clean return. Unsupported/unreadable metadata, non-directory layers, -drift, malformed output, budget exhaustion and all nonpruned candidates remain -failures. Each pre-launch and cleanup scan independently requalifies its own -snapshot and records only its verified-directory count. No filename, format, -overlay-parent or writable-container allowance is added; no file is deleted. - -All 32 copied-owner controls pass. They include real `find` traversal in an owned -temporary tree: the image file is first, yet a later writable/prefix/merged/work/ -volume artifact still appears; malformed and post-scan-changing metadata cannot -make the result clean. No developer Docker state or host collector is changed. -Focused review and actual hosted qualification still precede closure. - -The first fresh focused scope review approves `7cd07a18` without findings and -independently passes all 32 controls. A second fresh independent review follows. -Run 39145489321's ordinary job separately records `workload_internal_refusal`; -its failure remains red. The child now classifies unexpected faults solely by -a fixed owner-stage map and finite exception families, never exception text, -provider type names, filenames or stack output. The closed fact supplements -the failed receipt; no retry, passing result or completion witness is invented. - -The second fresh focused review approves `f53c36fc..e710bb61` without findings, -independently passing all 33 controls. On source `e710bb61`, -[run 39146395561](https://github.com/HodeTech/LearnStack/actions/runs/39146395561) -passes the complete hosted native job in 420 seconds. The verified artifact -contains 31 passing native cases, zero skips and exact fresh-discovery IDs; -all five completed-result fields equal the final TRX and every exported hash -matches. Actual setup/execution/cleanup intervals inside the launcher are -2.825/231.561/10.628 seconds. Ownership and natural Docker absence are positive; -forced cleanup is false. The collector changes from `systemd_coredump` to the -supported file policy with inherited zero limits. Independent pre/post scans -verify 78/94 image directories respectively; neither reuses the other's snapshot. -This qualifies that source's native job, not the complete PR or another source. -The same hosted meta job passes 17 provisioning and 33 launcher controls, -including actual GNU `find` traversal. Backend/ordinary fit remains separate. - -An independent source/filesystem investigation also verifies a normal VSTest -diagnostic-rotation incompatibility. It does not establish the cause of any -hosted ordinary failure. The inspected release sources -[v17.12.0](https://github.com/microsoft/vstest/blob/v17.12.0/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/RollingFileTraceListener.cs) -and [v18.6.0](https://github.com/microsoft/vstest/blob/v18.6.0/src/Microsoft.TestPlatform.PlatformAbstractions/common/Tracing/RollingFileTraceListener.cs) -rename the current file to one expected backup before publishing its replacement. -The old reader rejects a shorter replacement; a reproduced exists/open race -throws `FileNotFoundError`. The package pin `Microsoft.NET.Test.Sdk` 17.12.0 does -not itself pin the SDK console; the observed local console is -`18.6.0-release-26329-109`. Release-source equivalence is not an assertion about -an unobserved hosted build commit. - -The reader correction owns generation zero before launch, retains its descriptor -and requires exact device/inode/backup continuity before each handoff. It drains -old tails, preserves partial lines and defers only a live rename gap; a final -unresolved gap, missing generation, unknown backup, truncation or replacement -remains red. The cumulative 64 MiB bound spans generations; handoffs are bounded -and descriptors close on success/refusal. All 38 copied-owner controls pass, -including actual rename/race, hidden generation and cumulative-bound controls. -Two real local pure predicate cases also pass with the pre-owned file and actual -SDK writer: exact discovered IDs and all five final-result fields match TRX. -This small append/protocol receipt does not qualify actual rotation, Docker, -hosted cgroups or whole-job fit. Fresh review rounds and final-source hosted -qualification remain pending for this independent reader correction. - -Reader implementation `9aad3c57` completes the first fresh review without -findings; the reviewer independently passes all 38 controls and verifies both -private append/protocol receipts. A further controlled local experiment fills -only its private pre-owned generation zero above 10 MiB, triggering the -unmodified SDK writer's actual normal rotation. The reader follows one handoff -across 10,613,523 bytes; both real predicate cases pass with exact discovered IDs -and all five result fields equal TRX. This is deliberate local feasibility, not -a reproduction of a hosted fault. The new reader still owes final-source hosted -qualification and its second fresh review. - -Run 39146395561's ordinary artifact is independently verified: 517 unique passing -case IDs belong to the 2,401-case expected set; 1,884 cases remain censored and -no final Integration TRX exists. Its error is `deadline_exhausted`, distinct from -the earlier internal fault. The 0.777-second cleanup positively witnesses owned -join but is forced and supplies no natural Docker-disposal success. The -integration aggregate correctly fails despite the separate native success. - -ADR-0062's reopen condition is met. Proposed -[ADR-0063](../decisions/0063-complete-bounded-ci-test-shards.md) describes one -backend-base VM retaining non-test gates and cheap non-Docker suites, four -Architecture method shards, ten ordinary Docker method shards and the unchanged -native VM. The two backend required names become complete fail-closed aggregates; -all seven names, strict protection and twenty-minute execution ceilings remain. -Actual Release discovery and exact method-filter rediscovery must prove every -theory row has exactly one owner, with independent aggregate recomputation. -Timing estimates are advisory; the proposed counts are not a hosted fit proof. -Repeated restore/build across fifteen base/Architecture/ordinary VMs replaces -two such VMs; the runner and queue cost is explicit. No shard code is implemented -before maintainer acceptance. The proposal names three implementation steps, -each requiring commit and two fresh independent review rounds. - -Two independent proposal reviews (GPT-6-sol xhigh and GPT-6.1-sol xhigh) -approve the revised ADR and index without remaining findings. They independently -check retained failure artifacts, the pinned method-filter contract, exact -bounded supersession, cross-VM population agreement, aggregate-side independent -assignment recomputation, backend-base non-test gates and the sixteen-VM cost. -Actual selection, ownership, reserves and fit remain pending implementation and -hosted qualification. This is proposal review, not maintainer acceptance. - -###### ADR-0063 review revision (2026-10-18) - -The maintainer's response reviews the proposal; it does **not** accept it. -ADR-0063 remains Proposed. The initial `3f5f09e3` proposal and its first two -reviews above are historical inputs, not reviews of this revision. No shard -implementation or ADR-0062 amendment is authorized yet; `development` is retained, -PR #32 is open and P02b-5 has not started. - -Fresh read-only API/artifact verification of -[run 39148006960](https://github.com/HodeTech/LearnStack/actions/runs/39148006960) -binds source `3553ff16` to merge checkout -`6de31fcce66d7f53e4d5d28fd163f65ab8af4d85`. Native succeeds in 465 job seconds: -31/31 cases, zero skips, exact fresh IDs/TRX fields/hashes, positive ownership, -natural Docker absence and no forced cleanup. The launcher-only intervals are -1.535/240.221/10.468 seconds; these exclude checkout/restore/build. Both fresh -reader correction review rounds are complete. Meta passes 17 provisioning and -38 launcher controls; frontend, OpenAPI, secret scan and demo also pass. - -Backend again lacks a completed Architecture TRX and reaches the configured -ceiling. Its API interval includes the cancellation/post-step tail; that does -not extend its twenty-minute configuration. Ordinary is a distinct failed path: -416 passing IDs, 1,985 censored cases, no final TRX, `owned_completion_missing` -and `workload_internal_membership_io`. Forced 0.459-second cleanup witnesses -cleanup ownership, not successful workload completion. The retained facts do -not identify an errno or establish the root cause. ADR-0062 owns that correction; -sharding cannot count it as a measured deadline or waive it. The integration -aggregate correctly fails despite native success. Protection API readback still -has the same seven app-bound contexts and strict mode; no setting is changed. - -Review dispositions are verified against the current tree and retained evidence: - -| Review topic | Verified disposition | -|---|---| -| Stale native/meta Context and reader follow-up | Corrected source-scoped history: meta race fixed; image provenance and reader both reviewed; native now passes. Earlier ordinary internal/completion faults remain separate. | -| Four Architecture bins, 152 versus 346 rows | Confirmed weak sizing, not a fit proof. First/current/earlier console prefixes are 152/294/346 with no final TRX. Ordinary's ratio cannot predict CPU-bound Architecture. Local maximum is not a hosted upper bound. | -| Sum/wall confusion and 782-second window | Corrected: the window includes discovery/fixtures/test lifetime; 203 seconds already includes 60 seconds upload. Historical sums do not establish spare capacity or ordinary-only wall time. | -| Backend-base sizing | Newly extracted complete suite intervals and pre-test walls appear in ADR-0063. Base candidate remains one VM; its new discovery/owner/export and isolated fit still require measurement. | -| Repeated fixture/discovery costs | Confirmed: SharedSchema spans 75 classes; split VMs repeat container/migration/seed and other fixtures. Missing per-fixture/CPU measurements are unknown, never zero. | -| Fixed counts and new ADR per tuning attempt | Revised proposal permits reviewed manual Architecture 4–6 / ordinary 8–12, at most twenty backend/test execution VMs; initial 6/12. No automatic/dynamic expansion or larger ceiling. | -| Process composition and independence | Require two genuinely different A/B assignments on the same source via two full attempts; bin renumbering cannot qualify. Fix actual dependence if exposed. | -| Collection versus process/VM alternatives | Existing Integration collection parallelism and Architecture's two-thread cap clarified. Separate processes on fewer VMs are a credible unqualified alternative; VMs are not required merely to isolate static state. | -| Non-Docker cgroup privilege | Explicit new bounded hosted-only transient systemd authority requires acceptance; child stays non-root. Non-Docker gets no Docker baseline/cleanup, crash scan or collector authority. | -| Plan, timing/default costs and selector bounds | Proposed tracked JSON/owner, versioned frozen weights with provenance, unknown-method census, explicit 60-second estimate and finite direct-argv/filter bounds; actual selection still independently rediscovered. | -| Aggregate outcomes/names/ceilings | Backend requires base/all Architecture; integration requires all ordinary/native. Each unique required name belongs solely to an always-running aggregate, each bounded to five minutes. All seven protection settings remain. | -| Rerun/attempt/artifact semantics | Single-attempt receipts with immutable artifact IDs and attempt-specific job verification. Failed/aggregate-only reruns cannot reuse old siblings; recovery is Re-run all jobs. | -| General control owner and meta ceiling | Proposed general `CI_Test_Shards_Are_Complete_And_Bounded`, Registered only at acceptance, then Implemented with actual Python/meta controls. Native/Hangfire and Docker-trait rules keep their own scope; meta stays five minutes. | -| Cost, queue, toolchain and filter identity | Public standard minutes are free; effective organization concurrency is unknown. Queue extends feedback, not running ceiling. Each receipt records actual console/adapter; actual xUnit FQN producer is cited. | -| Probe path, terminology, diagnostics | Full probe README named; base is project-owned, only Architecture/ordinary selector-sharded. Finite/private diagnostics remain bounded; raw provider output is not added. | - -The first fresh full revision review (GPT-6.1-sol, xhigh) approves with no -Blocker/Major/Minor finding. It independently verifies native result integrity, -base intervals, the current ordinary failure, source/merge identity and all seven -strict app-bound protection contexts. Its suggestions are incorporated: explicit -initial A/B algorithms and the 56-second current meta baseline with a provisional -30-second new-control allocation. Only aggregates propose -job-level `actions: read` beside `contents: read`; no execution token gains -permission. - -The second fresh full review (GPT-6-sol, xhigh) independently approves -`3553ff16..b3ee4ea6` with no Blocker/Major/Minor finding. It verifies the actual -A/B/retry contract, bounded new authority, retained API/artifact/timing evidence -and current primary toolchain contracts. Seven ADR parser controls, all 653 -relative links/anchors in changed documents, prose width and diff checks pass. -Both revision review rounds are complete. This is proposal review, not acceptance -or hosted fit; ADR-0063 remains Proposed and its implementation waits for the -maintainer's explicit decision. - -The revised three steps are specified once in -[ADR-0063 Implementation Notes](../decisions/0063-complete-bounded-ci-test-shards.md#implementation-notes): -actual selector/plan controls; bounded execution/phase evidence; workflow/aggregate -and two-assignment qualification. Each retains commit and two fresh independent -review rounds before advancing. New general-rule registration and ADR-0062's dated -bounded replacement/additive disclosure happen **only after acceptance**. Their -future implementation must update actual catalogue counts in the enforcement -change, not preclaim them here. Full execution fit and the independent ordinary -owner failure remain open qualification work; no runtime feature is added. - -###### ADR-0063 acceptance and implementation (2026-10-18) - -The maintainer explicitly approves revised ADR-0063 and its three implementation -steps and requests implementation. Acceptance binds -`b3ee4ea6`, with two fresh independent review receipts recorded at `2e1fedc7`. -It authorizes the initial base + six Architecture + twelve ordinary + native -plan, manual Architecture 4–6 / ordinary 8–12 under twenty execution VMs, -complete A/B attempts, confined non-Docker systemd ownership and aggregate-only -read Actions API authority. Seven required contexts, strict protection and -execution twenty-minute / aggregate five-minute ceilings remain unchanged. - -ADR-0062 Amendment 1 discloses the bounded replacement/additive seam without -rewriting its Accepted body/metadata. The new general CI rule is Registered; -implementation and actual final-source fit remain pending. This acceptance -commit precedes any dependent code. The three steps follow ADR-0063's canonical -plan, each with commit and two fresh independent review rounds. Verified owner -faults remain corrections under ADR-0062, not presumed consequences of sharding. -Work stays on `development`; PR #32 stays open and the maintainer owns merge. - -###### ADR-0063 Step 1 — complete selector plan (2026-10-19) - -Implementation follows acceptance commit `94f201ab`. The tracked JSON plan starts -with six Architecture and twelve ordinary owners, bounded by the Accepted manual -range. Its method weights retain artifact hashes, partial/local provenance and -unknown fixed costs; estimates never select membership. The actual discovery -protocol supplies assembly, case ID, display name and `FullyQualifiedName`. -The owner builds whole-selector A/B assignments, bounded direct filters and exact -per-owner/complete-union checks. Shared-fixture class observations support the -independence witness; they do not define the test population. The general -catalogue rule remains Registered until execution and aggregate enforcement ship. - -Fresh Release discovery identifies 5,475 cases: 3,043 non-Docker and 2,432 Docker, -the latter exactly 31 native plus 2,401 ordinary. Both A/B plans independently -rediscover all 44 generated project filters and match every assigned case field; -their Architecture, ordinary and shared-fixture co-memberships differ. This -local selection proof took 38.429 seconds after complete discovery, using SDK -10.0.302. It does not execute the assignments or establish hosted fit. The -assignment digests are -`8c4459848fae3279b4bc60b7c4614945a282db4862042ca6565c331e9e56f4ad` -and `8a113fac9c26a7595d930effcc1c307f030cd7ede1b8d38592c55cac7d55099c`. - -Real discovery/result reconciliation also exposed two existing identity edges: - -- An Exception-valued Unit theory advertised one discovered ID for three executed - rows. Primitive inline inputs now construct the same three exceptions inside - the test, preserving all assertions and producing three distinct IDs. -- VSTest's TRX logger escapes supplementary Unicode as UTF-16 code units. Result - validation binds assembly/ID first and accepts only the exact discovered name - or its exact forward XML representation. It does not decode arbitrary names or - relax the raw completed protocol. Unicode test inputs remain unchanged. The - [resolved VSTest source](https://github.com/microsoft/vstest/blob/e2f248338b5756f82d38c0d9551ff08bea0947de/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs#L652-L689) - supplies this transformation. - -Local validation: normal solution Release build passes with zero warnings/errors; -the corrected Unit suite passes 2,452 cases with zero skips and unique discovered -IDs. All those TRX identities reconcile: 2,450 names directly and two through the -expected-bound XML representation. This Unit run did not capture the completed -protocol, so it is not claimed as a complete new launcher receipt. The actual -TRX SHA-256 is -`0597c5be316aab7ddb50ca1754e3b7cd29f2d3e689ae8862fea4fddc1375b395`. -Five focused corpus checks pass. Twenty new offline controls pass in 0.183 seconds -and all 38 existing launcher controls pass in 17.340 seconds. The changed C# file -passes project format verification; the solution-format invocation reported a -workspace-load warning, so it is not a clean full-solution format claim. - -The new controls run in meta inside a finite 30-second allowance. Workflow test -matrices, new execution authority, aggregate/API enforcement and actual two-attempt -hosted qualification remain Steps 2–3. Step 1's commit and both fresh independent -review rounds must complete before Step 2 starts; their receipts follow here. - -**Step 1 review round 1.** A fresh `gpt-6.1-sol` reviewer at `xhigh` examines -`94f201ab..480fb1b4` across the standards and code-review lenses. One Major is -verified: disjoint case-ID populations could still split the same assembly/FQN -between original trait partitions. Manifest validation now refuses that conflict; -controls cover every non-Docker/native/ordinary boundary under both assignments. -All 21 controls pass, including the supported equal-FQN/different-assembly case. -The reviewer independently verifies the prepared fix, all five timing artifact -hashes, complete discovery/filter diagnostics and unchanged A/B assignment -digests. No other actionable finding is confirmed. - -The reviewer also replays a real focused VSTest protocol/TRX proof: all eleven -cases across both Unicode methods and the three corrected exception rows pass -with unique IDs and exact completed-stream fields. Its local execution took -1.082 seconds; this supplies the protocol boundary proof missing from the full -Unit run, without claiming cgroup or hosted execution qualification. The fix -commit precedes the fresh second review. Step 2 has not started. - -**Step 1 review round 2 and closeout.** A new `gpt-6-sol` reviewer at `xhigh` -independently reviews `94f201ab..0c97dd29` and approves with no actionable finding. -The reviewer verifies the committed partition refusal, all 21 new and 38 existing -controls, all 44 real selected-filter diagnostics, both exact unions and changed -co-memberships, all five timing-source hashes and both Unit identity/protocol -receipts. The current plan reports three ordinary selectors with unknown weights; -they remain owned and use the declared advisory default. Step 1 is complete with -both required review rounds and the verified correction committed. Step 2 now -owns bounded execution and resource/identity receipts; Step 3 owns workflow/API -enforcement and actual two-attempt hosted qualification. No hosted fit follows -from this closeout. - -###### ADR-0063 Step 2 — bounded shard execution (2026-10-19) - -After Step 1 closeout `357b97fd`, the existing CI execution owner gains the -finite base, Architecture, ordinary and native-shard paths. They use complete -fresh selector discovery, recomputed plan ownership, independent selected-filter -rediscovery before execution and exact completed-protocol/TRX reconciliation. -All new dotnet argv pass the plan's byte bound before spawning. Base retains -format and actual Hangfire publish/distribution/replacement controls; normal -Release builds remain a prerequisite in the Step 3 workflow arrangement. -Existing unsharded workflow paths remain active until that wiring ships. - -Non-Docker paths qualify the exclusive hosted Ubuntu 24.04 VM and use only the -owned systemd/cgroup process boundary. They perform no Docker census/cleanup, -collector read/write or crash inventory. The native setup writer remains -native-only; a read-only qualification call explicitly excludes Docker for -non-Docker jobs. Only the delegated owned unit enables CPU/memory accounting. -The supervisor retains positive join and empty-subtree evidence before reading -its work-cgroup CPU/memory peak. VM memory is separately sampled during polling: -its observed maximum includes other VM work and is not a continuous peak bound. -Container-specific peaks and uninstrumented fixture counts remain unknown. - -Receipts retain the actually selected SDK/console versions and binary hashes, -the loaded adapter's diagnostic version/path-bound binary hash, per-project -first-result and test-process intervals, discovery/selection, non-test gates and -result export intervals. Advisory estimates retain unmeasured fixed terms and -no invented wall bound. The existing finite whole-job/cleanup/upload budget is -unchanged; forced termination cannot become success. Workflow/API aggregate -validation of these receipts and actual hosted fit remain Step 3 obligations. - -The independent ADR-0062 membership fault is also addressed narrowly. Linux can -return ENOENT/ESRCH when an enumerated task exits before its cmdline read. Only -that candidate read, or a positive vanished-task recheck, is tolerated. An -enumeration fault, non-exit cmdline fault, unreadable live candidate cgroup or -outside testhost still refuses with finite stage/reason diagnostics. The -previous hosted receipt lacks errno/suboperation evidence, so this is not a -claim that ESRCH caused that run or that the hosted fault is already closed. - -Local checks: all 31 shard controls pass, including real owner selection/result -flow, negative pre-spawn selection/bound checks, non-Docker parent authority -controls, exit-race controls and metadata/resource shape checks. All 38 existing -launcher controls and 18 provisioning controls pass. The latter execute a -byte-verified copy through real temporary subprocesses, including the new -non-Docker runtime reader with no Docker/collector/sudo operation. The reviewed -provisioner source hash is updated for its explicit read-only Docker exclusion; -all other copied bytes still must match. Actual local SDK/console observation -and retained loaded-adapter diagnostics resolve SDK 10.0.302, console -18.6.0-release-26329-109 and adapter assembly 2.8.2.0. These controls and local -observations do not qualify hosted systemd, cgroups, Docker disposal or fit. - -Step 2's implementation commit and two fresh independent reviews follow before -Step 3 begins. The general CI catalogue rule remains Registered; no final-source -hosted success, complete packet CI or merge is claimed. - -**Step 2 review round 1.** A fresh `gpt-6.1-sol` reviewer at `xhigh` reviews -`357b97fd..17f9cd4f` and approves with no actionable finding. All 31 shard, -38 launcher and 18 provisioning controls independently pass. The reviewer checks -the authority split, independent pre-execution selection, exact results, -retained lifecycle/deadlines and honest resource/toolchain observations against -the Accepted decisions and primary Linux/systemd sources. This unprivileged -review does not supply actual hosted containment or fit. The second fresh review -is required before Step 3 begins. - -**Step 2 review round 2.** A new `gpt-6-sol` reviewer at `xhigh` reviews -`357b97fd..9d3c7b4f`. All 31/38/18 controls pass independently, but one Major -startup fault is verified: accounting can refuse before publishing readiness, -while the parent waits for that file without observing an already failed unit. -The original path can consume the execution allocation and hide the prerequisite -failure behind `deadline_exhausted`. Root independently reproduces zero terminal -unit observations on that path. - -The correction publishes a bounded closed startup-failure record before any -workload fork, observes terminal unit state during readiness and caps the entire -startup handshake at thirty seconds inside the existing execution budget. A -live but unready unit times out; a terminal unit refuses immediately with the -allowlisted cause. Failed startup still stops only its owned unit, starts no -business workload and cannot become successful ownership/cleanup evidence. -All 34 shard controls pass, including real leaf refusal before fork, prompt -parent detection, finite live-start timeout and retained failed-start cleanup. -The fix commit and fresh focused verification follow before Step 3 starts. - -**Step 2 correction verification and closeout.** The correction is committed at -`fc67d1f8`. A fresh `gpt-6.1-sol` reviewer at `high` approves the focused change -without findings. All 34 shard and 38 launcher controls independently pass; -42 supplemental assertions exercise malformed/absent startup diagnostics, -terminal/disappeared units, readiness races, earlier deadlines and cancellation -followed by actual parent cleanup. These unprivileged controls do not qualify -hosted Linux containment. Both full Step 2 reviews and the verified correction -are complete. Step 3 now owns finite workflow/API aggregate enforcement, corpus -reconciliation and actual two-assignment final-source qualification. - -###### ADR-0063 Step 3 — workflow and aggregate enforcement (2026-10-19) - -After Step 2 closeout `83be42d6`, the workflow connects the initial base + six -Architecture + twelve ordinary + one native execution arrangement. Every -execution remains on an exclusive Ubuntu 24.04 VM with a twenty-minute ceiling; -both always-running required aggregates retain five minutes. Their canonical -names and the other five required names remain unchanged. Only aggregates gain -job-scoped read-only Actions permission; execution gains no token authority. - -The aggregate source owner parses actual workflow YAML through the runner's -bundled Ruby/Psych safe parser, with duplicate keys, aliases, tags and complex -keys refused. No package is added. Literal indices/counts, unique protected -names across workflows, mandatory Release/execute/upload gates and narrow -permissions must agree with the tracked plan before execution. PR head and -actual merge checkout remain distinct and are related through the raw commit's -parent header, including shallow checkouts. - -Every aggregate uses current-attempt job API outcomes and immutable artifact -IDs/digests before independently recomputing complete selection/result unions. -Private bounded ZIP extraction allows only named sanitized files and refuses -paths, symlinks, duplicate entries and oversize evidence. Case IDs, five result -fields, complete TRX counters, non-test gates, actual toolchain hashes and -scoped resources are checked again. Native provisioning/crash/no-refusal and -natural Docker disposal stay mandatory. Missing, failed, skipped, stale or -forced work cannot become a passing aggregate. Partial reruns cannot reuse -previous-attempt siblings; recovery is Re-run all jobs. - -Source enforcement and its planted controls update the general CI catalogue -rule to Implemented; its mechanically verified count is now 222 Implemented, -131 in Architecture and 91 elsewhere, with 254 declared Architecture methods -unchanged. This does not close Step 3 or qualify fit. Implementation commit, -two fresh comprehensive reviews, verified corrections and two genuinely -different complete final-source hosted attempts remain required. No complete -P02b-4/PR CI or merge is claimed by local validation. - -Step 3 local validation passes 47 actual-owner shard/aggregate controls (34 -retained plan/execution controls plus 13 new result/API/topology controls), -37 launcher controls and 18 provisioning controls. The retired unsharded -aggregate's single test is replaced by the new complete API/result controls; -its duplicate discovery/workload/aggregate and CLI paths are removed. The -launcher descriptor-cleanup proof now exercises the real shard workload. -Five CorpusConsistency cases verify the new catalogue counts, and seven ADR -parser controls pass. Changed-document relative links and diff whitespace are -clean. A retained predecessor native artifact is independently downloaded by -immutable ID and its exact API ZIP digest is verified by the new safe extractor; -this is archive-format evidence, not final-source execution qualification. -No host privilege, collector, Docker mutation or Linux containment is exercised -by these local offline controls. The implementation commit and required fresh -reviews precede final qualification. - -**Step 3 review round 1 and verified corrections.** A fresh `gpt-6.1-sol` -reviewer at `xhigh` reviews `83be42d6..10e1b164` and requests changes with one -Blocker (cross-scope concordance) and one Major (mutable PR projection). All -47 shard/result, 37 launcher, 18 provisioning, seven ADR parser and five -CorpusConsistency controls independently pass on that reviewed source. Root -verifies both findings before correction. The cross-scope coverage gap is: matching manifests inside each aggregate alone -cannot prove that the two scopes agree on the same classification. Integration -now additionally requires the same current-attempt immutable base artifact that -backend already verifies. All producers' full manifests/toolchains are bound -transitively to that common witness; integration's union/count excludes base's -non-Docker cases. A planted whole-selector classification change is refused. - -A second verified API issue concerns old-event reruns: REST's pull-request -projection follows the current branch head even while the run's head SHA stays -at its original event. Root independently observes this on run 39148006960. -Verification retains immutable run head plus the raw checked-out merge-parent -relation, and binds the PR number without treating its mutable head as a run -snapshot. A control supplies a newer PR projection with the older valid event. - -The initial hosted run 39170247704 exposes one additional frontend failure: -the exhaustive product-source classifier does not yet classify the new CI -files. The five exact CI plan/owner/control paths are added to its existing -non-runtime inventory, with classification assertions. Unknown scripts remain -refused. The guarded full frontend suite then passes 1,625 cases in two -packages with zero skips/todos; lint and typecheck pass. No product behavior or -broad extension exemption changes. All 48 shard/result controls and 37 launcher -controls pass after these corrections. These local results do not qualify the -initial hosted execution or the final two assignments. - -**Step 3 review round 2 and final control corrections.** A fresh `gpt-6-astra` -reviewer at `xhigh` reviews `83be42d6..98ae41a8` and approves the source with no -new Blocker/Major. Independent checks pass 48 shard/result, 18 provisioning, -seven ADR parser, five CorpusConsistency and 19 targeted frontend cases. The -37-launcher suite first exposes an existing 200 ms fixture-start race; an -unchanged rerun passes, and a fixture-only 250 ms startup delay reproduces the -race. Root replaces that proof's timing assumption with actual first-result -and partial-next-event admission before deterministic cancellation, under a -separate five-second test guard. A delayed real child still runs, is actually -joined, preserves the exact completed ID and leaves incomplete JSON/no TRX. -Production execution and cleanup budgets remain unchanged. - -The second verified Minor is that non-native preflight checks but discards the -weekly image release. Receipts now retain its already validated OS/release, -CPU/kernel/virtualization values; aggregates validate and retain each producer's -observed identity independently, without inferring equal images from equal -labels or SDKs. Controls reject missing/invalid image evidence. The suites now -pass 49 shard/result and 37 launcher cases. - -The initial hosted run also exposes one stale environment-control assertion -that expects test filters directly in the former backend execution job. It is -adapted to the actual complete topology owner and verifies that the read-only -collector/Docker observer runs only before native execution. Non-Docker paths -gain no observation authority. All five environment controls pass. The other -four read-only observer controls remain intact. - -Initial source `10e1b164` supplies a real passing base receipt: 2,633 cases, -393 seconds whole job, actual SDK 10.0.402/console 18.7.0-release-26505-111, -43.811 seconds discovery/selection and 113.792 seconds non-test gates. -Immutable artifact 12152067468 and its API ZIP digest, exact results, natural -ownership and raw merge-parent relation are independently verified. This is -pre-correction base evidence only, not final-source/global fit. Initial -ordinary-10 reports two failed facade cases; their related three rows pass -locally in isolation and exact-shard diagnosis continues. A fresh focused -correction review and full final-source hosted qualification remain required. - -**Focused correction verification and hosted diagnosis.** A fresh -`gpt-6.1-sol` reviewer at `high` approves `98ae41a8..70c8fdea` with no findings. -It independently passes 49 shard/result, 37 launcher, five environment and -18 provisioning controls, plus malformed-image, distinct-image aggregate, -actual cancellation/reaping and topology-mutation probes. Both full source -reviews and those verified corrections are complete; actual hosted -qualification remains separate. - -Initial run 39170247704 finishes with all six Architecture producers, base, -native and eight ordinary producers passing. The backend aggregate passes; -integration correctly refuses failed producers. Four ordinary producers fail -five facade cases: ordinary-0 capacity completion, ordinary-3 grouped cleanup, -ordinary-9 common database outage, and ordinary-10 control timeout and -never-started admission. Their failure receipts report forced cleanup and -missing owned completion, not natural completion. Frontend and meta expose -the already corrected classifier and obsolete observer assertion above. -This predecessor run is not final-source qualification. - -An independent investigator runs the exact initial ordinary-10 assignment -locally: all 176 IDs match its hosted selection and pass in 212.449 seconds. -The three focused facade rows also pass. This macOS/SDK 10.0.302 evidence -does not close the hosted Linux/SDK 10.0.402 failures. No test budget, method -assignment, policy or outcome is changed on that evidence. - -To locate the next actual failure without exporting provider diagnostics, -the existing measurement receipt retains only fixed source codes for the -five affected facade source files and bounded line numbers, tied to an -already validated failed case ID. Raw stacks, paths, exception types and -messages remain private; missing frames remain unknown. Successful aggregate -validation requires no failed-location entries. A real two-failure probe -using the pinned SDK/adapter confirms the actual wire field and sanitization; -49 shard/result and 38 launcher controls pass. This diagnostic provides no -completion, containment or passing-test evidence. A fresh focused review and -subsequent full hosted runs remain required. - -The fresh `gpt-6.1-sol` / `high` diagnostic review approves -`70c8fdea..4a14a812` with no findings. It independently passes 38 launcher and -49 combined selector/aggregate controls, 18 focused privacy/boundary probes -and eight rehashed measurement mutations. Passing cases export no diagnostic; -missing or nonempty failure-location evidence cannot qualify a successful -producer. The next hosted source incorporates both full review corrections -and this independently verified diagnostic. Five failed facade rows and -complete final-source A/B qualification remain open. - -**Candidate `ec5b045a` hosted diagnosis.** Run 39172490912 incorporates both -verified full-review corrections and the focused diagnostic. Frontend and meta -now pass. Its native artifact 12153083206 independently verifies 31 passing -cases, exact results/hashes and natural ownership/cleanup in a 497-second job. -The five affected facade methods also pass all eight exact IDs in a task-owned -local Linux ARM64 / SDK 10.0.400 focus; this is not the hosted x64 toolchain. - -The hosted outage failure repeats. Its finite source locations identify the -post-pause all-heartbeat-fault premise, not a proven runtime cause. The -90-second case deadline includes startup and pre-pause work; stock heartbeats -wait thirty real seconds, and a failed transient attempt remains faulted while -the manual pacing clock is frozen. A new public admission rendering failure -has no retained source location under the original five-file diagnostic. - -The next narrow diagnostic adds that verified test basename and decodes only -its existing closed helper stage/detail, or the outage's existing bounded -elapsed/pause/since-pause durations and finite per-pool generation facts. -Extraction is limited to the two exact failed test identities, with unknown -values left unknown. No raw error text, path, provider value or free-form -state crosses the diagnostic boundary. These facts neither change test -outcomes nor satisfy ownership/containment. Root causes, focused review and -complete final-source A/B qualification remain open. - -The first fresh diagnostic review (`gpt-6.1-sol`, `high`) verifies one Major -in `ec5b045a..2b8d6cbe`: the pool parser expects an internal metadata property -that the actual record's generated text omits. All forty synthetic controls -pass, but reflection over the real Release record reproduces absent pool -details. Root verifies that actual output, removes the nonexistent suffix and -aligns the control with the real shape; an extra-field mutation remains -unknown. The corrected parser consumes all three actual record strings, and -all forty launcher controls pass again. No application record or runtime -policy changes. A new second focused review follows before publication. - -The fresh second `gpt-6-astra` / `high` review approves -`ec5b045a..30ef90d4` without findings. Forty launcher and fourteen aggregate -controls independently pass, alongside actual-record decoding, seven invalid -protocol/privacy probes and rehashed success-receipt refusal mutations. Root -also runs two deliberately failed pinned-xUnit scratch cases through the real -wire: the exact test names expose only their closed stage or all three real -record snapshots, both remain Failed, and the private canary is absent. - -Run 39172490912 finishes with 24 successful jobs and three failures: ordinary-9, -ordinary-11 and their required integration aggregate. Backend and the five -other required checks pass. Its longest Architecture job is 779 seconds; -the longest ordinary job is 683 seconds and base is 314 seconds. These -observations do not waive the two failed cases or qualify final-source A/B. -The next source publishes the twice-reviewed diagnostic without changing any -test, assignment, runtime behavior or bound. The live PR owns subsequent -source/run receipts until packet closeout. - - -The next full run, 39174286516 at `e0124baf`, finishes with 24 successful -jobs and three failures: ordinary-9, ordinary-11 and their integration -aggregate. The actual outage record now exposes all three original pools: -control reports a heartbeat fault, while external and transactional do not; -none is draining. The pause completes at 503 milliseconds and the failed -observation follows 89,497 milliseconds later. This rules out insufficient -post-pause allowance and prior drain for that observation, but does not -locate the two unfinished heartbeats. The independently hashed ordinary-11 -artifact instead identifies the capacity-control lost-checkpoint test; the -public-rendering case passes in this run. Its missing source location is -not evidence of any particular failed stage. - -Pinned source inspection confirms three separate native heartbeat threads. -A narrow owned Linux/Npgsql pause experiment returns every open, UPDATE and -disposal within 15.029 seconds; it does not reproduce the hosted stall or -qualify a total hosted provider deadline. The next diagnostic records only -heartbeat entries, attempt count and the closed lifecycle-wrapper phases -Created/Acquiring/Invoking/Disposing/Returned. These are non-atomic observations -of progress, not successful-cleanup, join or admission authority. Invoking -includes the stock provider's own connection acquisition, SQL and release. -No timeout, scheduler policy, retry, ownership or assignment changes. -The verified capacity-control basename joins the closed source-location map. - -Local validation of this observation includes the warnings-as-errors Release -build, 2,452 unit cases and three actual PostgreSQL heartbeat/capacity-control -cases, all without skips. The actual compiled diagnostic record is passed -through two deliberately failed pinned-xUnit wire cases: three pool details -retain their bounded phase/count facts, both cases stay Failed, and the -private canary is absent. The fresh `gpt-6.1-sol` / `high` and -`gpt-6-astra` / `high` focused reviews each approve `e0124baf..2c7d4300` -without findings. Both independently pass forty launcher and 49 combined -shard/result controls; the second also runs the fourteen result controls -separately and probes actual compiled phases, numeric boundaries and privacy. -The observation supplies no root-cause correction or ownership witness. -Actual hosted root causes and complete final-source A/B remain open. - -**Candidate `89fd8450` and native qualification corrections.** Run -39176455522 finishes with 22 successful jobs and five failures: ordinary-1, -ordinary-3, ordinary-4, ordinary-9 and their integration aggregate. All six -Architecture shards, base, native and the other five protected checks pass. -The independently hashed ordinary-9 artifact records all three metadata -heartbeats inside their first stock invocation, without a published fault, -89,553 milliseconds after the database pause. This narrows the observation -to the provider invocation; it does not distinguish physical acquisition, -SQL or provider release. An owned Linux ARM64 experiment using the hosted -SDK version, 10.0.402, returns paused pooled calls within 15.014 seconds and -fresh opens within 5.009 seconds. It does not reproduce hosted x64 behavior. - -The other three failed cases concern the lost capacity checkpoint ACK, -completion after row-lock expiry, and retained auxiliary cleanup. Their -original failure locations are absent from the previous closed map. Source -inspection also verifies a qualification race: a native hint can complete -without business admission while the bridge ACK holds the application row; -the committed ACK then leaves repair behind its accepted grace, longer than -the fixture's initial wait. A new real-PostgreSQL control deliberately locks -that row, observes the actual skipped native hint and zero business attempts, -commits the real ACK, and resends through the real stock provider. Exactly -one business execution and attempt complete. This proves the fixture gap is -reachable; it does not establish the cause of earlier hosted failures. - -Execution-focused fixtures now observe either their actual start signal or -the committed bridge ACK before supplying that additional native hint. A -started body need not wait for an ACK blocked by its own row lock. Existing -repair, lease, execution and cleanup bounds remain unchanged. Their explicit -finally blocks preserve the original body failure together with a cleanup -failure. This does not claim to cover every later implicit disposal fault. -All facade source basenames join the fixed diagnostic map. A thread-local, -synchronous observation adds PhysicalOpening around the actual connection -factory; it has no admission, retry or cleanup authority and does not flow -into child work. - -Local validation passes the warnings-as-errors Release build, all 2,452 unit -cases, eight actual PostgreSQL regression rows, five affected Architecture -boundary cases, forty launcher controls and 49 selector/result controls, -without skips. Two deliberately failed pinned-xUnit wire cases retain both -original and cleanup source locations and the three actual compiled -PhysicalOpening records, while private canaries remain absent. The earlier -full Architecture run passes 410 cases at `2c7d4300`/`89fd8450`; the five -focused cases cover the changed production boundary. Two fresh correction -reviews precede publication. Actual hosted root causes and the two complete -final-source A/B attempts remain open. - -Both fresh correction reviews (`gpt-6.1-sol` / `xhigh` and -`gpt-6-astra` / `xhigh`) approve `89fd8450..15d5161d` without introduced -findings. Each independently passes 24 storage unit cases and forty launcher -controls, inspects the actual wire proof and verifies the authority limits. -The second review separately confirms the same pre-existing fixture gap in -capacity admission, never-started admission and control-lock execution tests. -An adjacent audit applies the helper to those and the equivalent capacity -cleanup/stop/takeover, combined-pool and held-expiration execution premises. -Initial bridging, repair, future-due and fairness subjects keep their paths. -The additional eight test files change only start qualification and its -signals; all original assertions and bounds remain. Their fourteen real -PostgreSQL rows pass without skips in 84 seconds, and the warnings-as-errors -Release build remains clean. This adjacent correction receives its own -focused reviews before publication; it supplies no hosted failure attribution. - -The fresh focused `gpt-6.1-sol` / `high` and `gpt-6-astra` / `high` reviews -both approve `15d5161d..6f5025ce` without findings. Each independently traces -the actual-entry signals, lost-admission-ACK branch, stock hint and duplicate -admission fences, and verifies all fourteen distinct passing PostgreSQL rows -and the clean build receipt. Neither repeats the suites or claims hosted fit. -The original eight and adjacent fourteen regression rows supply twenty-two -local passing cases. Publication includes both twice-reviewed corrections; -the next full hosted A attempt, then a complete same-source B attempt, must -still qualify the final source. No required check or ownership rule is waived. - -**Candidate `c3564e08` and acquisition-path correction.** Full hosted run -39180047008 completes with 25 successful jobs and two failures: ordinary-9 -and its integration aggregate. All six Architecture shards, base, native, -the other eleven ordinary shards and the other six required checks pass. -The independently hashed ordinary-9 artifact identifies only the common -database-outage case. Control/external heartbeat attempts return their faults; -the transactional heartbeat remains inside PhysicalOpening after 89,293 -post-pause milliseconds. That phase includes the authority check, lazy-source -resolution and driver open/physical initialization; it does not identify a -specific internal driver stage. The failed run reports missing owned completion -and forced cleanup, not successful natural resource release. - -An unchanged actual Linux ARM64 fixture on SDK 10.0.402/runtime 10.0.13 passes -alone in 39.343 seconds. The exact independently verified ordinary-9 cohort -then passes all 207 actual case IDs, including that case in 38.127 seconds, -without missing/extra/duplicate/skipped rows. Both use the direct Docker bridge; -all their PostgreSQL containers are naturally absent after completion. These -local results do not establish the native hosted x64 cause or final CI fit. - -Independent pinned-driver source inspection and an owned socket-pair experiment -verify a separate acquisition hazard: the pinned -[read-buffer timeout setter](https://github.com/npgsql/npgsql/blob/v10.0.0/src/Npgsql/Internal/NpgsqlReadBuffer.cs#L49-L57) -truncates a positive sub-millisecond budget to socket timeout zero. The actual -pinned read buffer stays held -past that budget until its exact owned peer sends a byte; the same buffer's -asynchronous cancellation source cancels a real asynchronous socket read. -This is source-level evidence, not a reproduction of the hosted open path. - -The stock synchronous factory now joins the guarded source's supported -asynchronous acquisition, retaining its actual completion and existing budgets. -The shared physical-role initializer's query/disposal awaits are context-free. -No vendor SQL, role grant, timeout, owner, admission, retry or assignment changes. -An actual-driver control holds its asynchronous physical initializer: the factory -cannot return early or dispatch through a caller's deferred synchronization -context, and a planted synchronous initializer refuses. A second actual-factory -control verifies the unmodified role guard on a fresh connector, a planted -NOBYPASSRLS refusal and restoration. Validation and two fresh correction reviews -precede publication; actual final-source A/B qualification remains open. - -Local validation passes the warnings-as-errors Release build, all 2,452 unit -cases and 24 actual PostgreSQL factory/role/heartbeat cases without skips. -Temporarily restoring only the old synchronous factory call makes the new -async-initializer premise fail; restoration of the correction is checked again. -Both restored factory cases pass, with no skip. -A separate Ubuntu 24.04 SDK 10.0.402/runtime 10.0.13 x64 process passes the -actual corrected outage case in 42.882 seconds. The local engine and child -PostgreSQL remain ARM64, so this cross-architecture experiment does not claim -native hosted x64 equivalence or root-cause closure. Its two PostgreSQL -containers are naturally absent afterwards, with exact owned cleanup verified. - -The first fresh review verifies the factory correction and identifies bootstrap -as the other production synchronous source caller. Owning its startup wait does -not remove the same acquisition hazard. The correction moves to their shared -`PrivilegedDataSource.OpenConnection` entry, preserving the authority check before -lazy resolution. Both direct/bootstrap-source and factory paths now receive the -same actual-driver initializer/context control. Bootstrap verification SQL stays -synchronous; neither all SQL internals nor the hosted root cause are claimed -corrected by this acquisition change. The central source correction is requalified -before its fix commit and the second fresh review. - -The central implementation passes the warnings-as-errors Release build, all -2,452 unit cases, 26 actual PostgreSQL source/factory/role/bootstrap/heartbeat -cases and both exact credential/bootstrap Architecture guards, without skips. -Restoring only the old driver call at the shared source makes both direct and -factory initializer controls fail their actual async-entry premise. These -controlled mutations are not passing regression evidence; the corrected source -is restored before the fix commit and follow-up review. -All three corrected source/factory cases pass again after restoration. - -The fresh `gpt-6.1-sol` / `xhigh` round approves `c3564e08..78c51320` -without introduced findings and verifies bootstrap's adjacent existing hazard. -After its central correction, a fresh `gpt-6-astra` / `xhigh` round approves the -combined `c3564e08..da8a5958` source without findings. It independently traces -both callers, actual driver failure/disposal, authority and role checks, and the -recorded positive/mutant/restored results. Both correction review rounds are -complete; no retrospective hosted root cause is certified. - -At this source freeze, complete final-source A/B CI remains a required exit -gate. [PR #32](https://github.com/HodeTech/LearnStack/pull/32) owns its subsequent -live source/run/attempt status and immutable API/artifact receipts. Dated records -above remain historical observations against their named source, not a substitute -for the PR's current qualification or the maintainer's review/merge. - -**Candidate `0634280b` and remaining execution premises.** Its full A run -39183839130 verifies the common-outage case on hosted Linux x64 in 39.170 -seconds. The API-hashed ordinary-9 receipt passes all 235 cases with natural -ownership/cleanup and no forced stop; the new source/factory theory rows also -pass in ordinary-10. This is positive current-source execution, not proof of -the predecessor's internal driver cause. Fresh discovery owns 5,479 actual cases. - -Ordinary-6 instead fails the native business-overrun/private-callback case -after 30.890 seconds at its body-entry wait. Its API-hashed artifact retains -that exact source location and a failing ownership/forced-cleanup result; -neither is accepted as successful qualification. Source inspection verifies -that this execution/cleanup subject and the admitted-renewal subject still -rely only on the initial bridge hint. Both receive the existing actual-start -or committed-handoff qualification before their entry wait. All original -assertions and deadlines remain; no runtime code, assignment or retry changes. -The separate terminal-backlog fairness proof retains its natural bridge path. -The run ends with 25 successful jobs and the ordinary-6/integration aggregate -failures; it is not a complete A receipt and no B rerun is requested. - -An independent remaining-premise audit inventories all facade entry waits and -adjacent native external subjects. Five external constructor/recovery-cleanup -rows also leave the repair grace at 60 seconds while waiting for entry under a -30-second startup token. Both normal routing and external recovery may skip -the actual ACK-locked row without provider entry. These execution-only subjects -receive an external-specific qualifier: actual entry short-circuits; otherwise -a committed vendor handoff supplies its current stored wake generation for one -real stock external hint. Provider/recovery, cancellation, accounting and final -state assertions remain unchanged. Intentional bridge/repair, fairness, -future-due, recurrence and no-admission subjects retain their natural paths. -This is a verified permitted interleaving, not a retrospective cause claimed -from the failed hosted artifact. Release warning-as-error build passes. Four -actual PostgreSQL business/locked-hint/fairness cases and six external -constructor/recovery/history cases pass, with seven corpus/Docker-trait guards; -all have zero failures/skips. Two fresh reviews precede publication. The next -final source still needs complete A/B qualification. - -Correction `65afb4d5` completes two fresh independent reviews: Round 1 -(`gpt-6.1-sol`, high) and Round 2 (`gpt-6-astra`, high) approve without verified -findings. Both independently trace the actual normal/recovery locks, stock -route, ownership, cleanup and unchanged subjects against the passing receipts. -Round 1 additionally verifies the live job API and immutable artifact hashes -for the source-specific claims above. These are completed correction reviews, -not a claim that either final hosted assignment has passed. - -**Candidate `39adff20` and owned completion witnesses.** Full A run -39185926530 finishes with 24/27 successful jobs. Ordinary-6 now passes; the -31-case native and 2,633-case base receipts pass with actual cleanup and -API-matching archive hashes. The two failing cases are ordinary-1's public -client-pool disposal proof and ordinary-8's grouped no-start/private-callback -proof; their API-hashed archives retain the failures. The integration -aggregate rejects the failed execution evidence. No B is requested for this source. - -The public case's exported result has no raw assertion message or mapped source -location, so its precise hosted assertion is unknown. Independent pinned-source -inspection verifies two missing synchronization premises: client connector -closure does not join PostgreSQL backend exit, and competing framework host -disposals need not join one another's service cleanup. The proof now observes -the actual captured application-source lifetime without disposing it itself, -requires a used, uniquely tagged pool and refused borrowing after disposal, -then boundedly observes only that pool's server sessions disappear. Another -connection's exit cannot hide a leak. - -The no-start artifact identifies its exact generation-snapshot assertion but -does not retain the observed tuple. Source inspection confirms that the -optional qualification hint may itself own the held callback; waiting only for -the bridge hint's success does not establish its native wrapper's return. -That case and the matching auxiliary-cleanup case now retain the optional hint -identity and await its actual stock success before the unchanged exact snapshot. -The callbacks remain held throughout. An independent sweep checks all eighteen -qualifier calls; the other sixteen already use sufficient actual owner/cleanup -or retained-only witnesses. Native snapshot and held-owner assertions remain -intact; runtime, assignment and retry behavior do not change. -The next final source still requires both complete hosted assignments. - -Local qualification passes a warning-as-error Release build, 35 actual -PostgreSQL public-site/native-owner cases and seven corpus/Docker-trait guards -with zero failures/skips. The public-pool case also passes alone. Removing -only child-factory disposal makes that case fail its bounded actual-completion -wait; exact source restoration, a fresh clean build and the isolated case pass -again. This planted failure is a falsifiability control, not passing suite -evidence. Two fresh correction reviews precede publication. - -Correction `18ba1700` completes fresh Round 1 (`gpt-6.1-sol`, high) and Round 2 -(`gpt-6-astra`, high) reviews with no actionable findings. Both independently -verify real lifetime/consumer ownership, tagged pool use, passive completion, -refused borrowing, native hint identities and held callbacks against the -source-specific passing and planted-failure receipts. The restored source is -clean. These approvals do not infer a missing historical assertion or replace -the next final source's complete A/B qualification, owned live by PR #32. - -### Durable outbox dispatch - -P02b-1 Steps 2/3 implement `IOutbox`, replace Packet 3's step-7 shell with -an enrollment/invariant guard, and supply owner-side domain collection and the -first publisher. P02b-2 delivers hosted producer dispatch and production-census -enforcement; all four steps and both independent review rounds are complete and -merged. The [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns final -verification. P02b-3 delivers independent subscriber execution and enforcement; -it is complete and merged, with final CI/review/merge verification in its -[merge closeout](#p02b-3-merge-and-closeout-2026-10-15). -The table shipped in Packet 6. - -A handler calls `IOutbox.EnqueueAsync` and the row commits on the same **transaction** -as the aggregate change — the ambient one `IUnitOfWork` owns -([ADR-0040](../decisions/0040-ambient-unit-of-work.md)), not a shared `SaveChanges`, a -formulation [ADR-0033](../decisions/0033-audit-durability-model.md) withdrew. [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md) -accepts immediate INSERT through that connection/transaction. Step 7 is an -enrollment/invariant guard; the transaction owner drains domain events before -MUST audit and commit. Raw transactions without an enrolled producer frame -cannot enqueue. P02b-3 delivers production acceptance and subscriber execution wiring. - -#### Process topology - -`OutboxProcessor` is a `BackgroundService` — the shape -[Events and Outbox § OutboxProcessor](../architecture/15-event-and-outbox.md#outboxprocessor-backgroundservice), -ADR-0006 Amendment 1, ADR-0010 and the glossary all specify, with a 200 ms poll no job -schedule expresses. This phase hosts it in `LearnStack.Api`, the only web host. -`LearnStack.Tools.Seeder` is a separate one-shot executable, not a worker host. -P02b-2 Step 3 registers the mandatory hosted processor. The corpus's gateway -route table puts `/admin/hangfire*` on that -host ([API Gateway](../architecture/30-api-gateway.md), route id 3, upstream -`learnstack-api`), and the production image is -[Phase 11](phase-11-production-hardening.md)'s. A second worker host is not a -configuration change — a second process consuming an integration event is ADR-0035's -Dapr trigger verbatim — so it stays with Phase 11. - -- The phase declares itself **single-instance**. The cache-invalidation deferral above - depends on that premise, and so does the ordering bound in § Ordering. -- `ConnectionStrings:OutboxDispatcher` carries the `learnstack_outbox_admin` credential, - registered as a keyed guarded facade with an internal lazy pool and boot-time - role guard, on - the pattern `Platform_DataSource_Resolved_Only_By_PlatformAdminScope` already holds. - `LearnStack_OutboxAdmin_Role_OnlyUsedBy_OutboxProcessor` is **Implemented** - with Step 4's nonempty credential caller census and passing planted controls; - all four steps and both independent review rounds are complete and merged. - The [merge closeout](#p02b-2-merge-and-closeout-2026-10-13) owns final verification. -- The three carriers that say the credential lives in "the worker host" — - [Database Standards § Database roles](../standards/05-database.md#database-roles), - `architecture/15` and `.env.example` — are derived cells, not a topology decision; - ADR-0003's own role table has no host column. They are corrected to name the API host - in the same change. - -#### The dispatcher - -- **The lease.** A committed normal claim uses a fresh canonical UUID token in - `locked_by`, database-time expiry and one just-in-time row. Every acknowledgement, - failure and terminal transition checks row ID, token and unexpired lease. - Recovery first replaces an expired token with a fresh one; it never publishes - or increments attempts. Stale callbacks cannot clear a later lease. -- **The migration** adds lease/terminal columns and exact status-column grants - together. [Database Standards § Outbox](../standards/05-database.md#outbox) owns - canonical DDL/checks/indexes. Audit-chain INSERT-only privilege enables the - separate fifth audit writer on the same confined transaction. -- **Retry** counts six committed normal claims, including claim-before-crash. - The five delays are 1 s, 5 s, 30 s, 5 min and 1 h. Failure clears the lease; - exhausted or invalid rows request terminalization without another publication. - A failed terminal MUST audit rolls back terminal state and retries only - terminalization. Stored descriptors are closed codes capped at 256 UTF-8 bytes. -- **The SQL form.** Parameterized commands use only the confined data source; - no EF materialization or set-based API owns dispatcher status. Required Pending - subscriptions and their aliases are excluded before claim/payload validation; - intentional absence is the only known-type zero-subscriber acknowledgement. -- **Deadlines.** The accepted bounds are in the P02b-2 package. Ignored - cancellation retains and observes the task, blocks its local partition and - makes health unhealthy; four retained overruns stop new claims. Late work - cannot acknowledge the row. There is no forced task termination promise. - -#### Ordering - -ADR-0046 accepts deterministic eligible selection by -`(available_after, occurred_at, id)` within one processor. It promises no enqueue, -commit, retry, cross-process or unconditional same-key publish order. Interleaved -transactions and retry deferral are proof subjects. Partition-key derivation -remains the separately delivered ADR-0057 contract; a key alone proves no durable -sequence. See [Ordering](../architecture/15-event-and-outbox.md#ordering). - -#### Domain events collected and dispatched - -**Implemented by P02b-1 Step 3 — ADR-0057.** The shared SaveChanges -interceptor stages source events and promotes them only after successful -persistence, in both API and Seeder compositions. Failed/canceled saves promote -nothing. Collection retains source/frame attribution and transaction generation; -repeated saves, detach and delete cannot lose or duplicate a successful event. - -Only the transaction owner drains the collected FIFO queue, at one dispatch site, -before producer invariant checks, MUST audit composition/write and commit. At most -256 domain events belong to one transaction; exceeding this total fails the whole -unit. This is a total count, not recursive cascade support. - -Domain-event handlers translate facts into outbox messages only. They do not -mutate roots, use write stores, send nested requests, raise further events, -publish notifications or invoke external providers. Unexpected enqueue/contract -faults throw and roll back. Expected business decisions stay in commands or later -integration consumers, preserving the returned version and one-root boundary. - -Each producer invocation keeps a sticky receipt after a successful outbox INSERT -or successful-save promotion, also recorded in every ancestor. A `Result.Fail` -from any frame with that work poisons the shared unit before its UoW frame is -resolved, even when an ancestor absorbs the refusal. Ordinary event-free refusals -retain ADR-0040's semantics. Joiners neither dispatch nor clear the owner's queue; -every terminal path clears transaction-scoped source/collector state exactly once. - -#### The consumer side - -**Delivered by P02b-3 Steps 1–6 under Accepted ADR-0046.** Construction-free manifests -carry stable versioned subscription IDs, compatible aliases and required -Pending/Active readiness. Active publication durably accepts every matching -delivery without running business handlers. The independent executor owns retry -budgets, leases and terminal state in a separate delivery ledger. - -One shared `inbox_messages` is keyed by `(tenant_id, subscription_id, event_id)`. -The transport opens the app-role unit of work, announces envelope tenant and -organization, then claims before handler construction. Completed duplicates skip -construction. Business state, completed inbox, produced outbox, MUST audit and -fenced ledger completion share one physical transaction. Rollback removes a new -claim; completed inbox rows never reset. Ordinary delivery uses SystemActor and -refuses privileged work; Phase 03 owns erasure's separate audited boundary. - -Timeout poisons the business owner, preventing late success. An uncertain COMMIT -is Indeterminate, including the final claim; atomic ledger/inbox state decides -recovery. The bypass scheduler sees only enumerated identity/routing/status -columns, never envelope payload. P02b-3 supplies canonical DDL, exact RLS/grants, -capture exclusions and the ADR-0023 minting correction before runtime. - -A poisoned subscription leaves siblings untouched. Its fenced terminal state and -Tenancy-owned `platform.delivery.dead_letter` MUST security-event commit together. -Internal replay resets only that ledger pair and invokes its executor, never -`PublishAsync`. Phase 03 retains producer reset and operator permission/reason, -fencing and surface contracts. Phase 11 retains purge intervals and broker -binding. External effects need subscription/event idempotency or an outbox intent. - -#### Observability - -[Observability Standards § Required Metrics](../standards/10-observability.md#required-metrics) -is the sole inventory of names and dimensions. P02b-2 supplies producer duration, -failure, terminal and lease-loss diagnostics, immutable backlog/eligible-age/ -deferred/heartbeat snapshots and registered `outbox` health. No metric has a -tenant label; event-type labels come only from the bounded registry. Required -Pending rows, completed and terminal rows are excluded from normal eligibility. -P02b-3 delivers independent subscriber terminal/dedup signals and minimizes the old -transport diagnostics. Separate producer/subscriber failure signals describe -separate budgets. Health is registered, not mapped; `/healthz` stays liveness and -Phase 11 owns `/readyz` and production alert windows. - -### Background jobs - -**Current implementation — 2026-10-18.** P02b-4's nine implementation steps and -review gates are locally complete under Accepted ADR-0047/0058/0059/0060/0061. -The [local closeout](#p02b-4-local-closeout-2026-10-18) owns exact qualification -and remaining PR/CI/merge work. The pre-acceptance checklist below is historical -preparation; the Accepted decision package and delivery records above own current -authority. - -**Historical pre-acceptance preparation (not current authority).** - -No Accepted record selects the general background-job runtime. ADR-0028 selects -Hangfire specifically for future audit maintenance; that narrower decision must -be retained or explicitly superseded, rather than described as absent. **G9** and -**ADR-0047** are the first work item; runtime implementation waits for acceptance. -The record has to close, at minimum: - -- **Storage under the closed four-role model.** Infrastructure Stack Standards - prescribes a `hangfire` schema; Database Standards says the database has one schema, - `public`; all four roles are `NOCREATEDB` and none holds `CREATE` on the database, so - no role can create that schema, and every structural Row Level Security sweep reads - `public` only. Each default here breaks a written rule, which is why the storage - decision owes a dated ADR-0003 Amendment for a changed schema/role/grant boundary, - not merely for a tenant table following the existing policy. -- **One writer of `ITenantContextAccessor.Current` on the job path.** ADR-0036 § Rules - names the Hangfire `JobActivator`; `architecture/09` names a `LearnStackJob<TParams>` - base class; the catalogue carries both spellings. The writer allow-list in - `TenantContextConstructionTests` currently names HTTP, bus and delivery-executor - files (two logical entry classes). The job writer is added deliberately, and - whichever competing job spelling loses is retired rather than left in place. -- **Who owns a job frame's transaction and announces `app.tenant_id` on it.** Restoring - the accessor announces no GUC, and a job touching a module `DbContext` therefore - throws. ADR-0040 has exactly two entry points and eight setters, and the set is - closed: the `ISender` shape keeps it at eight, a runner-owned transaction makes it - nine and owes an amendment. -- **The enqueue-site rule.** Enqueuing a job from inside a handler is the dual write the - outbox exists to prevent, and the corpus currently draws it as a sibling of - `IOutbox.EnqueueAsync` off the same handler. `IUnitOfWork` has no post-commit seam. -- **The retry and dead-letter contract**, one taxonomy shared with dispatch and - delivery, with its counter registered in Observability Standards and its audit row - under **G7**. -- **The ADR-0035 classification.** The job *tenant contract* is a one-way door — it is - in ADR-0035's own list of things that touch every job payload — and the runner is - additive. Ship the contract and the port; the classification decides whether the - vendor adapter is gated, and no scheduling port name exists in the corpus to inherit. -- **The queue grammar and job-id convention.** Infrastructure Stack Standards carries a - dotted job-name rule; two ADR bodies spell the same thing with colons, and no document - defines a queue grammar at all — while Phase 08a's dependency table inherits a "queue - policy" from this phase and its own Notifications section says that phase defines "its - queue and its retry policy", a tension the record resolves. Queue names and job ids - are separate concepts and the record distinguishes them. -- **The package pins and the licence verdict** for Self-Hosted redistribution. Nothing - is pinned today. - -What this phase ships once that record is Accepted: - -- The runner in its own `LearnStack.Infrastructure.*` assembly, registered at the - composition root, with its storage created on the DDL path ADR-0047 names. -- The tenant-context restoration hook: one writer, its Origin, the system-actor and - causal-actor split, the `Guid.Empty` and `TenantId.PlatformSentinel` refusals, an - `Activity` started from the stamped `traceparent`, and a `finally` that restores the - previous accessor value so the next job on the worker does not inherit it. -- An enqueue-time guard over `tenant_id`, `organization_id?`, a `traceparent`-shaped - `correlation_id` and the causal actor. Job payloads missing any one of them **fail at - enqueue time**, not at activation: the failure is loud and belongs to the caller who - can fix it. The catalogued rule reads "missing `tenant_id` **or** `correlation_id`", - so a payload missing exactly one of them fails too, and the guard checks provenance - rather than mere presence — the platform stamps these values from the resolved - context. -- A behavioural rule that a job runs under its restored tenant. The catalogued - structural rule asserts statement order and is green whether restoration works or not. -- **No job definition and no dashboard route** (§ Explicitly not in this phase). - -### Identity integration — the `learnstack` realm - -The LearnStack identity **domain** (`User`, `Membership`, `Role`, `Permission`, -`Invitation`) lands in [Phase 03](phase-03-identity-admin.md). This phase delivers the -authentication plumbing for the tenant-facing `learnstack` realm, and adds nothing to -the rules its carriers own: -[Identity and Auth § Token Flow](../architecture/13-identity-and-auth.md#token-flow) -owns the OAuth role split, -[Security Standards § Authentication](../standards/11-security.md#authentication) owns -token custody and lifetimes, -[Frontend Architecture Standards § Auth](../standards/07-frontend-architecture.md#auth) -owns the session mechanism, and -[ADR-0036 § Staging across packets](../decisions/0036-tenant-resolution-trusted-inputs.md#staging-across-packets) -stages the wiring into this phase by name. Where this phase disagreed with one of them, -it was the phase that was wrong. - -LearnStack does not implement password hashing, password-reset rendering, MFA enrolment, -or refresh-token rotation. Those live in Keycloak; the split is described in -[Identity and Auth](../architecture/13-identity-and-auth.md). - -- **The authentication wiring ADR-0036 stages here**, and its insertion order: - `UseAuthentication` above tenant resolution so a validated claim exists when the - resolver builds its attempt, `UseAuthorization` below the tenant assertions. Two - insertions, not one block, with an ordering rule and a planted-order companion - registered in the catalogue. The claim signal is populated at the one site the - resolver's comment reserves, from a validated `learnstack`-realm principal only. -- **One JWT authority for `/api/v1/*`**, the `learnstack` realm, with the issuer, the - audience, the algorithm allow-list, the clock skew, `azp`, and the rejection of ID - tokens all pinned. `Api_Registers_Only_The_Tenant_Realm_Authority` is catalogued to - this phase and its own note says the structural half passes while issuer validation is - disabled in configuration — the integration half is the load-bearing one. A - `learnstack-hub` token on a tenant-facing endpoint is refused here, not in - demand-gated Phase 02c. -- **The claim shape and the actor's identity**, under **G10**. The pipeline carries a - `UserId` from this phase on, and the resolver already dereferences one when a tenant - claim arrives with a subject, so the value is load-bearing rather than cosmetic. Phase - 03 owns the durable `sub` → `UserId` mapping; this phase owns where the claim comes - from and must not mint a fresh identifier per login. -- **Which matrix rows go live**, under **G11**. `demo-english` is a tenant-wide host and - `demo-yoga` maps to its default organization, so a tenant-only token on the yoga host - is a row that consults `ITenantMembershipReader` — registered as - `DenyAllTenantMembershipReader` until Phase 03. Whichever way G11 resolves, the - outcome is asserted rather than discovered: a successful Keycloak callback on its own - conceals it. -- **The host/JWT tenant cross-check.** A request whose host-derived tenant disagrees - with its JWT tenant returns 404 — not 403, which would confirm the resource exists — - through the **same** recorder and the **same** operation key Packet 9 shipped, with - `metadata.assertionSource = jwt-claim`, per - [ADR-0036 § Recording a rejected assertion](../decisions/0036-tenant-resolution-trusted-inputs.md#recording-a-rejected-assertion). - Not a second detector. The shipped types cannot carry that metadata yet — the - rejection record has no source, actor or correlation field, the recorder hard-codes a - null actor, and the resolver's refusal path only logs — so those are this phase's - edits. The organization dimension follows G11. The cross-check is a fault detector, - not an authorization control, and not the first isolation layer: Row Level Security - and the query filters precede it. -- **What an anonymous request to a routed endpoint answers**, under **G20**. The - catalogued `Backend_RequiresJwt_OnAllAuthenticatedRoutes` is booked to this phase and - says every endpoint outside the public allow-list answers 401 without a bearer token; - [ADR-0036's matrix](../decisions/0036-tenant-resolution-trusted-inputs.md#the-reconciliation-matrix) - row 2 says a non-`[PublicSurface]` request on a tenant host with no credential answers - 404, byte-identical to an unknown host's. Both cannot hold for the same request, and - the default `UseAuthorization` wiring answers the one the matrix forbids. The same - gate carries the refusal **code** split the shipped assertion middleware assigns to - this phase by name — `tenant_mismatch` for an authenticated caller, `not_found` for an - anonymous one, written by the middleware rather than left to the status-code pages. -- **Absence is not disagreement.** A token with no `tenant_id` claim resolves under the - host-only ceiling by design. What this phase must not do is let that be silent: with - the realm as it stands every token is claimless, so a lost mapper looks exactly like - an anonymous visitor. The claimless-token case on a tenant host has no matrix row at - all, and G11 gives it one. -- **The authenticated tier's bound**, under **G14**. Authentication goes live while - `AuthorizationBehavior` is still `return next()`, so without a bound any tenant user - reaches every routed request type until Phase 03. The token-keyed budgets that - [Security Standards § Rate Limiting](../standards/11-security.md#rate-limiting), - Standards 04 and the shipped limiter's own remarks assign to this phase go live with - authentication — they are also the bound ADR-0036 names for its per-occurrence - mismatch row, so activating that path activates this dependency. -- **Seed users**, under **G12**: tenant users only. Operators are the `learnstack-hub` - population and ADR-0004 Amendment 1 makes the separation a hard invariant — the - `learnstack` realm declares no platform-admin role and should not gain one. The - current dev export has no organization claim. **G11** decides whether this phase - mints one or deliberately refuses the authenticated organization-host case; - "across both organizations" is not yet an accepted promise. -- **Keycloak realm roles.** The realm ships three `tenant-*` roles with full scope on - both clients, so they appear in every token, while roles live in LearnStack and not in - Keycloak. Either they leave the realm or they are declared inert with a rule proving - no LearnStack assembly reads a role claim. A documentation link is not a mitigation - for a leak the realm actively causes. - -#### Correction: the realm emits no `tenant_id` claim at all - -This is an unimplemented prerequisite of this phase's authenticated cross-check. -`infra/keycloak/realms/learnstack.json` stores `tenant_id` as a **user attribute** and -declares **zero protocol mappers**. Keycloak does not put user attributes into tokens -unless a mapper says so. The API also has no JwtBearer registration or -`UseAuthentication` today: it does not validate those tokens or populate the -resolver's reserved claim signal. Current public requests use the delivered -host-only admission, query filters and Row Level Security. Authenticated behavior -must not go live until G10–G12 settle the token and resolution contract. - -Three changes, and the third is the one that makes the first two take effect: - -- An **`oidc-usermodel-attribute-mapper`** on a client scope shared by the API and the - BFF's client, projecting the attribute into the access token and the ID token, typed - as `String`, with an explicit audience mapper beside it. A mapper on the API's client - alone shapes nothing in a token minted for another client, which is the client the BFF - redeems the code with. -- The seeded value changed from the slug `"tenant-a"` to the seed tenant's **UUID**. The - claim is consumed as a `TenantId` — a Vogen value object over `Guid` from - [Phase 02a Packet 6](phase-02a-kernel-tenancy.md) — so a slug cannot be parsed. The - attribute is declared **admin-only** in the realm's user-profile configuration: it - alone raises a request to the host-and-claim authority ceiling, so a - self-service-writable attribute is a privilege-escalation path. -- A **reconciliation mechanism**, under **G12**. Keycloak consumes the realm import - once, at first start, and re-import overwrites nothing that already exists. A change - made only in the import reaches no existing workstation, and a Keycloak database wipe - is not the upgrade path — `make seed` today only polls each realm's discovery endpoint - and never writes to Keycloak. Without this step the token-shape test below is green in - CI on a fresh container while every warm workstation issues claimless tokens. - -The test asserts the shape rather than the configuration file: a token issued by the dev -realm for a seed user carries a `tenant_id` claim that parses to that seed tenant's -`TenantId`, and the realm export's seeded value equals `SeedData`'s literal. A realm -export that loses the mapper fails it. - -#### The BFF session - -The session is the first thing in the repository that holds a user credential, and its -properties are required rather than inherited from an adapter's defaults. **G13** -settles it; what the phase ships either way: - -- **OIDC Authorization Code flow with PKCE between the browser, the BFF and Keycloak.** - The BFF is the code-exchange client; the API is a resource server that validates a - bearer token and is not a party to the flow. -- **Custody.** Security Standards puts refresh tokens in `HttpOnly`, `Secure`, - `SameSite=Lax` cookies and that document owns the rule; what this phase adds is that - only server code reads them, and that no response body, RSC payload, session JSON or - log line carries one. -- **Lifetimes and refresh.** One authority for the access-token TTL — four documents - currently give four numbers, and this phase links the authority rather than adding a - fifth. Concurrent requests arriving with a near-expiry token produce exactly one token - request and one logical replacement session version, including any cookie chunks; - a terminal `invalid_grant` clears the session and the - visitor gets the public page anonymously rather than an error. -- **Cookie scoping and CSRF.** Host-only cookies with no `Domain`, so two tenant hosts - do not share a session, plus an `Origin` check and a session-bound token on every - mutating route. `SameSite=Lax` does not separate hosts under one registrable domain, - which is exactly the SaaS subdomain shape, and no CSRF rule exists in the catalogue - today. -- **Login topology**, under **G12**: login is served on the visitor's tenant host, - requiring one registered redirect URI per seed host. Phase 02d retains - `demo-english.learnstack.local` and `demo-yoga.learnstack.local` under the native - HTTPS launcher; hosts entries and certificate trust remain manual prerequisites. - `P02b-0` re-verifies [G32](phase-02d-walking-skeleton.md#the-decision-register) - and the ADR-0053/0054/0055 ingress, visitor/peer and single-bootstrap boundaries. - G12 still settles the BFF client, callback and post-logout URLs; it preserves - `Secure`. The login transaction's `state`, `nonce` and `code_verifier` live in a - host-only transaction cookie, and return URLs are validated. -- **Logout**, which - [Identity and Auth § Logout](../architecture/13-identity-and-auth.md#logout) describes - and Phase 03 expects: the session cleared, the end-session endpoint called, and - back-navigation not restoring an authenticated view. -- **Something that consumes the session.** One authenticated `/api/v1/*` read and one - guarded page, both in the OpenAPI document and the regenerated SDK. Without them "a - login completes" cannot be demonstrated, and - `Backend_RequiresJwt_OnAllAuthenticatedRoutes` sweeps an empty route set. -- **Auth.js and `auth()` placed in `apps/web`**, the `(studio)` / `(portal)` redirect, - the server SDK's bearer attachment, and server-only environment keys. The - `add-frontend-route` and `add-feature-gated-ui` skills contain future auth - illustrations rather than shipped helpers; P02b-7 replaces them with the real - session API when it lands. - -### Useful provisioning flow - -[ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) -accepts completed provisioning as the producer: `TenantCreatedIntegrationEventV1` -on `learnstack.tenancy.tenant`, partitioned by `TenantId`, with no extra payload -fields and null envelope organization. P02b-1 emits it only after tenant/default -organization/back-reference completion and persists pending rows. - -Under ADR-0046, P02b-3 supplies independent Customization subscriptions for the -`card@1` content type and `plain@1` taxonomy. Each create-only effect owns one root, -generation update and MUST -audit on its inbox transaction, preserves authored/lifecycle/deletion decisions, -and resolves incomplete pairs through retry. P02b-3 owns semantic key/version -Seeder verification, preserved warm IDs and fresh seed/delivery convergence. -Typed settings stay uncached; definition generations are freshly probed. This -phase promises no eager settings invalidation or asynchronous Audit mirror. - -### Audit coverage wiring - -The audit pipeline lit up in -[Phase 02a Packet 9](phase-02a-kernel-tenancy.md#delivery-record-packet-9) under -[ADR-0033](../decisions/0033-audit-durability-model.md). This phase adds the entry -points it does not reach, and both of Packet 9's hand-offs land here. - -- **The delivery path owns its transaction and audit frame.** - [ADR-0040](../decisions/0040-ambient-unit-of-work.md#consumers-do-not-have-a-request-and-still-need-all-of-this) - assigns `Begin → SetTenantContext → handler → Commit` to this phase. P02b-3 - prepares the app-role transaction, restores validated event context, claims the - inbox and enters the common audit owner before handler construction. Handler - identity is classified even for a direct business write; an unregistered handler - is refused. This closes the old accessor-only transport's missing audit frame. - **G6's common-owner contract is Accepted under ADR-0057**; P02b-3 implements - it in production delivery under ADR-0046. Its proof is a MUST-classified direct-write - consumer, - not only a consumer that sends a command. -- **The audit frame's owner on a non-pipeline entry point.** What is *already* decided - is not reopened here: - [ADR-0033 Amendment 2 § 2](../decisions/0033-audit-durability-model.md) and - [ADR-0044 § 4](../decisions/0044-audit-write-path.md) both say only the owning frame - writes, signals the boundary, reconciles and clears, and a joiner does none of it. - ADR-0057 accepts common entry coordination for **G6**. `AuditLogBehavior` takes - its owner - flag from an audit-frame counter rather than from unit-of-work ownership, and - [Audit Subsystem](../architecture/31-audit-subsystem.md) records that split as - deliberate for the HTTP path — at step 3 no transaction is open to answer the - question. P02b-3 explicitly opens the outer audit frame around subscriber execution; - nested commands join it and cannot reconcile or clear before delivery completion. - The shared transaction owner flushes MUST rows before commit, then the outer audit - owner alone reconciles and clears. P02b-1's controlled fixture and P02b-3's actual - consumer and direct-write proofs enforce ADR-0044/0033's common ownership. -- **The discriminating case.** The pair this phase used to name — a consumer's - MUST-class command recording `success` on the delivery's transaction, and a - rolled-back delivery recording it standalone as `failed` — passes under **both** - ownership designs. ADR-0057's cases distinguish an ordinary event-free refusal - absorbed by a committing delivery from a produced-work refusal that poisons it, - a faulted `COMMIT` producing exactly one - `indeterminate` row, and `Clear()` running exactly once per delivery. -- **Dead-letter transitions — Accepted ADR-0046.** Producer terminal state and - Tenancy-owned `platform.outbox.dead_letter` MUST security-event commit on one - short confined-role transaction. `WriteEventTerminalAsync` validates its - restricted `EventTerminalTransition` witness against the actual fenced UPDATE - and draft identity. Audit failure rolls back state and retries terminalization, - without another publication. P02b-3 Step 4 delivers the corresponding subscriber - operation and its off-path registration with the writer. -- **Routine dispatcher bypass — Accepted ADR-0046.** The confined credential, - exact grants, bounded diagnostics and atomic terminal audit explicitly exempt - routine polls/claims/acknowledgements/retries from per-invocation security audit. - Existing `EnterPlatformAdminScope` entry audit and all other bypass obligations - remain unchanged. This is no general background-job exemption. -- **The rejected-assertion row names its actor once there is one.** The recorder writes - a null actor on the authenticated tier today, because no principal exists in the - process and `IsAuthenticated` is a tier rather than an identity. ADR-0036 makes the - actor the finding on that tier, so the realm integration above populates it from the - validated token's user — the observable that also proves the assertion middleware runs - after authentication. -- **Causal actor and causation.** P02b-3 supplies the validated incoming event ID - to consumer audit intents and follow-up outbox production; causal actor remains - separate from effective SystemActor. Nested commands inherit these identifiers, - while a newly drained domain event supplies its own causation ID. The Accepted - **G6** producer/common-owner contract owns these bounded metadata keys. -- **Classification for the operations this phase introduces** — the sample flow's - command, the first authenticated read, login, logout and refresh — registered in their - owning module's catalogue source and matrix before their handlers ship, because an - operation the catalogue does not classify is refused, and the join is total in both - directions. The authenticated read carries no permission key until Phase 03. - -The `AuditEntry` aggregate is owned by the **Audit** module and shipped in Phase 02a; -rows arrive through the store's parameterised inserts, and -[Phase 03](phase-03-identity-admin.md) registers the Identity module's catalogue source -and coverage matrix against it. See -[Audit Coverage Standards](../standards/18-audit-coverage.md). - -### Compile-time secret leakage (carried out of Phase 02a Packet 3) - -Packet 3 shipped runtime redaction — the Serilog enricher and the local error tracker -both scrub the same set through the single `SensitiveTokenCatalog`. It covers logs, OTLP -and error-tracker tags. It does not cover a value already interpolated into an exception -**message**, and this phase adds three durable sinks for one: an outbox row's -`last_error`, a subscriber-side failure record, and a job's persisted failure state. -Those sinks, not a Problem Details body, are the threat this phase's diagnostic answers -— the response factory builds no free text from an exception message. - -`LS0002` is planned, not shipped; its initial Warning severity does not itself -make a build fail. A roadmap document is not its diagnostic registry. -**G16** records it the way ADR-0032 Amendment 1 recorded `LS0001`: its -`LearnStackException-<Topic>` rule name, the project trees it runs over, what it -inspects, its `AnalyzerReleases` row, its catalogue entry, and the condition that -escalates it from Warning to Error. Two things the record has to settle rather than -inherit: - -- **Its scope.** `LS0001`'s `Domain` + `Application` reference set excludes the - assemblies where this phase handles tokens and provider errors, which is where the - sinks are. -- **Its token source.** The analyzer targets a different framework from the assembly - that holds `SensitiveTokenCatalog`, whose own remark says new tokens land there and - not in consuming projects, and the catalogue's public accessor exposes only part of - the set. A drift test is what makes "matches `SensitiveTokenCatalog`" true rather than - aspirational. - -Its own tests assert the positive case, a clean case staying clean, a sensitive name -outside a `throw` staying clean, no `AD0001` crash — the failure mode ADR-0032 Amendment -1 records for `LS0001` — and that the analyzer's token set equals the catalogue's. - -P02b-2 bounds the durable failure descriptor under **G18** to closed stage, -reason and category codes, with only allowlisted SQLSTATE where applicable; -exception text/type, trace identity and payload are not persisted there. The -canonical DDL owns the byte bound. Step 1 implements the migration beside the -lease columns, including redaction of legacy descriptors without rewriting -event facts/state; Steps 2–3 implement transitions and bounded diagnostics. - -### Architecture tests - -[Architecture Tests Catalogue](../standards/21-architecture-tests-catalogue.md) is the -canonical reference for every rule identifier, and a hand-kept second copy of it here -goes stale the moment the catalogue moves. The obligation is therefore stated over the -catalogue's own **Phase** field: **every row whose Phase names 02b is Implemented and -green by this phase's exit, and none is still Registered or Awaiting backfill.** That -set includes the outbox, inbox, partition-key, claim-protocol, job-payload, JWT and -realm-authority rules, and it currently contains rows this document's previous list -omitted. - -What this phase owes the catalogue beyond implementing those rows: - -- **Producer rows delivered by P02b-1:** the announced-transaction write, - produced-work refusal, owner-only completion, outbox-only domain handlers and - identifier-only payloads. Later decision passes register and implement the - ADR-0036 middleware-ordering rule, the - routable-set bound (**G14**) and the Keycloak-role-claim rule — with the realm-role - question it answers — in `P02b-5`, where the API first reads a claim; and `LS0002` - under its rule name (**G16**) in `P02b-8`. -- **Widened assertions** where a catalogued rule is satisfied by the defect it exists to - catch. P02b-1 extends `Outbox_Row_Carries_Correlation_Context` to exact stored - identity, tenant/organization, full traceparent and partition values, including - unresolved provisioning. Its partition declaration rule combines independent - stored-source IL checks, varied identifier probes and real persisted keys; - an uninitialized instance is not a value proof. Publish ordering stays P02b-2. - `Outbox_Claim_IsHeld_Until_Dispatch_Completes` replaces the former unconditional - exactly-once assertion with live-lease contention, expiry/crash redelivery and - stale-transition refusal; Step 3 implements the actual two-worker proof. - P02b-4's accepted `BackgroundJob_Submission_Is_Transactional_And_Stamped` replaces - `Hangfire_Job_Payloads_Include_TenantId` with tenant/org/actor/trace and atomic - submission proofs under Accepted ADR-0047; it is not Implemented today. - `OutboxProcessor_NeverBlocks_OnSingleMessageFailure` gains the hanging-handler - case. Two rules the catalogue stamps **02a** also - widen here, so the Phase-field sweep above does not reach them: the transport arm of - `Tenant_Context_Guard_Fires_Only_On_An_Unmarked_Transaction`, whose second arm has no - subject until the transport announces a tenant, and - `Module_DbContexts_Enlist_In_The_Ambient_UnitOfWork`'s connection allow-list, which - the dispatcher's keyed data source and the job storage both touch — a new entry there - is a decision, taken in the pass of the packet that adds it: the dispatcher's in - `P02b-2`, the job storage's under **G9**. -- **A planted-offender companion for every structural rule this phase ships.** The - catalogue's own rule is that a rule shipping before its first subject exists carries a - companion that plants the violation it exists to catch; with one sample event and one - consumer, most of this phase's structural rules are near-vacuous without one. That is - Packet 9's repeated lesson — a rule that cannot tell *clean* from *blind* — and Packet - 10 established the convention this phase follows: a `*Probes.cs` type holding the - planted violation, and a `The_<X>_Can_Actually_Fail` case beside the rule. -- **Rules that leave this document.** A read-model naming rule belongs to - [Database Standards § Read Models](../standards/05-database.md#read-models), which - already carries `public_<module>_<concept>`; it has no subject, no marker identifying - a table as a read model and no catalogue row, and the first phase that ships a - projection registers it with its first subject. The provider-SDK rule is the - catalogue's and is wider than the paraphrase this document carried. The - [accepted P02b-6 package](#p02b-6-decision-package-2026-10-20) introduces no - runtime SDK subject and hands its owning-phase cell to Phase 03's first runtime - identity-provider adapter, triggered by actual SDK introduction. It remains - Awaiting backfill there; direct HTTP does not qualify as SDK coverage. - -Two notes on what "green in CI" can mean. Several of this phase's rows are behavioural -rather than structural, and CI runs those in a separate job under a Docker trait filter, -so "the architecture suite is green" does not reach them. `backend integration -(Testcontainers)` is already a required check; the -[P02b-0 receipt](#p02b-0-entry-verification-2026-10-12) verifies all seven current -required contexts with strict up-to-date protection. `P02b-8` re-verifies those -live settings under the exact reported names. `scripts/assert-tests-ran.py` -already rejects a missing assembly, zero executed tests and any unexecuted test -in the required assemblies; test failures additionally fail the `dotnet test` -command. The phase retains zero skips, per assembly. - -## Deliverables - -- **ADR-0046 Accepted** — event delivery, the shared inbox contract and separate - delivery - ledger: stable subscription identity, readiness, durable acceptance, attempts, - cancellation, terminal transitions and targeted replay. Canonical inbox/ledger - DDL and consumer runtime are delivered by P02b-3; acceptance of the ADR alone - did not claim implementation. -- **ADR-0047 Accepted** — the background-job runtime, with the dated ADR-0003 Amendment - its storage decision owes. -- **The dated amendments the register names**, each Accepted before the code it governs: - ADR-0044 / ADR-0033 / ADR-0040 for the delivery and domain-event frames (G6), - ADR-0046 with ADR-0044/0033 disclosures and fifth-writer seam - for terminal audit (G7), ADR-0046 with ADR-0003/0006 disclosures for bounded - bypass/retry (G8/G4), ADR-0036 for the matrix staging - (G11), ADR-0032 for `LS0002` (G16), ADR-0038 for the payload-content rule (G18). -- **Database Standards § Inbox** — the canonical inbox DDL beside § Outbox, with its - table class, its policy taken by link and its grants; plus the erratum ADR-0023's - DB-side minting list owes. This phase states the **contract** — how long a - `(event, consumer)` pair stays replayable — and - [Phase 11](phase-11-production-hardening.md) picks the purge interval that honours it. -- `IOutbox` and the `OutboxFlushBehavior` invariant guard, delivered by P02b-1 - under Accepted ADR-0057; immediate INSERT uses the announced transaction. -- `TenantCreatedIntegrationEventV1` from completed provisioning; P02b-3 - independent Customization subscriptions install untouched `card@1` content-type - and `plain@1` taxonomy defaults with one-root effects and the P02b-3 Seeder - identity handoff. -- A durable `OutboxProcessor` implementing the specified lease: a fenced claim, a - per-delivery deadline, bounded retry, a terminal producer state, and the migration - that adds `locked_by` / `locked_until` **and** extends `learnstack_outbox_admin`'s - column-scoped `UPDATE` grant in the same change. -- The dispatcher's credential registered as a keyed data source behind a boot-checked - `Lazy<>`, with `LearnStack_OutboxAdmin_Role_OnlyUsedBy_OutboxProcessor` promoted - from Registered only after the full census and planted controls pass. -- `partition_key` persisted onto the row and rebuilt into the envelope on dispatch. - `PartitionKey` abstract on `IntegrationEventBase` and per-key serialisation in - `InProcessEventBus` shipped in Packet 5; the durable hop is this phase's. -- `inbox_messages` and `IInboxGuard` over the canonical DDL, the per-`(event, consumer)` - delivery transaction opened before handler construction, and tenant and organization - context restored in every handler scope from the envelope. -- A subscriber-side ledger and terminal path accepted by ADR-0046: a terminal - outcome per - subscription, a sanitized failure descriptor, its counter, its MUST-class audit row, - and targeted internal replay through the executor/inbox boundary. Producer - reset and operator permission/reason/fencing remain Phase 03 contracts. -- A worked sample flow — enqueue → outbox → dispatch → idempotent consumption — placed - where G19 settles, between modules that hold domain code, so the module-scoped sweeps - have a subject. -- Domain-event collection on the shipped seam and one dispatch site inside the owning - frame's transaction, ordered before producer invariant checks and MUST audit. - Domain reactions translate to immediate outbox INSERTs only. -- **The delivery path's audit frame** in the shape **G6** settles — the component that - performs the four owner-side acts on a transport-opened transaction, and the same - owner duties performed in the same order by every frame that owns an ambient - transaction (Packet 9 hand-off). -- The background-job runner, its storage on the path ADR-0047 names, its tenant-context - hook, its enqueue-time guard over four fields, its package pins — and no job - definition and no dashboard route. -- The registered, unmapped `outbox` health check and accepted producer event - metrics in - [Observability Standards](../standards/10-observability.md#required-metrics), - including bounded immutable snapshots. P02b-3 Step 4 delivers the separate - subscriber signals and registered, unmapped `delivery` health check. -- `UseAuthentication` and `UseAuthorization` at their two pinned positions, the claim - signal populated at the resolver's reserved site, one JWT authority for `/api/v1/*` - with its full validation contract written into - [Security Standards § Authentication](../standards/11-security.md#authentication), and - token-keyed rate-limit partitions going live with authentication — including the - change **G14** settles to the existing pre-auth floor: 60/min per canonical - visitor and 600/min peer acquisitions/allocations under ADR-0053/0054. These - anonymous visitor/peer quotas remain distinct from the token-keyed budget. -- The rejection record carrying a source, an actor and a correlation id; the recorder - writing `metadata.assertionSource` and populating `actor_user_id` on the authenticated - tier; and the resolver's refusal path calling the recorder rather than only logging. -- The host-vs-JWT tenant cross-check returning 404 through Packet 9's existing recorder - and operation key — the same key, no second detector. -- The Keycloak `learnstack` realm with a shared client scope carrying the `tenant_id` - mapper, the `user_id` mapper G10 settles, an explicit audience mapper, UUID-valued - seed attributes agreeing with `SeedData`, both attributes declared admin-only, - tenant-only seed users, the realm-role question resolved, and per-host redirect URIs. -- An idempotent reconciler that applies all of that to a warm Keycloak database on every - `make seed`, preserving existing accounts and the `learnstack-hub` realm. -- OIDC PKCE login through the BFF on the visitor's own tenant host, a cookie session - with host-only scoping and single-flight refresh, an `Origin` plus session-bound-token - CSRF control, RP-initiated logout, and Auth.js wired in `apps/web` with the two - skills' illustrative `auth` references replaced with the shipped helper. -- The first authenticated `/api/v1/*` read and the first guarded page, both in the - OpenAPI document and the regenerated SDK. -- A Keycloak test fixture over the committed realm JSON and an in-process JWT issuer for - the ADR-0036 token rows, both carrying the Docker trait where they need a container - and both visible to the trait sweep. -- `LS0002` shipping as a Warning under its catalogued rule name, with its ADR-0032 - amendment, its catalogue entry, its `AnalyzerReleases` row, its linked token source - and its four tests. -- **Carrier reconciliation**, in the change that lands each mechanism: - [Events and Outbox](../architecture/15-event-and-outbox.md) (§ Inbox table, § - Subscriber side, § Ordering, § Dead-letter — producer side, whose pushed-out - `available_after` terminal reading and manual-replay recovery both change; the - producer and consumer samples; and the dispatcher sketch's non-existent context, - unbounded type resolution, unfenced `RecordFailure` write and raw `ex.Message`); - [Infrastructure Stack Standards § Outbox and Inbox](../standards/20-infrastructure-stack.md#outbox-and-inbox) - and § Background Jobs; - [Error Handling Standards § Outbox](../standards/09-error-handling.md#outbox) and - [§ Background Jobs](../standards/09-error-handling.md#background-jobs); - [Database Standards](../standards/05-database.md); - [Observability Standards](../standards/10-observability.md); - [Identity and Auth](../architecture/13-identity-and-auth.md) and - [Frontend Architecture](../architecture/14-frontend-architecture.md); - [Security Standards](../standards/11-security.md) and - [Frontend Architecture Standards](../standards/07-frontend-architecture.md); - [Testing Standards](../standards/06-testing.md), which names Postgres as its only - integration container; the `add-integration-event` skill, whose consumer sample still - writes an audit row through a module `DbContext`; and the glossary, both for the - headwords this phase's mechanisms need and for its existing `IInboxGuard` entry, which - calls the table per-module. Four carriers will contradict this phase the day it lands - and are corrected with it: [Phase 03](phase-03-identity-admin.md), which still owns - the BFF session, the host-and-claim cross-check and logout, and acquires instead the - Hangfire dashboard route behind the Platform-scope permission with its ADR-0015 - amendment, the operator recovery surface, and this phase's stale in-code messages; - [Phase 11 § Data Operations](phase-11-production-hardening.md#data-operations), which - acquires the processed-outbox and aged-inbox purge under the `learnstack_platform` - `DELETE` grant with the no-principal constraint **G9** carries; - [Phase 08a](phase-08a-assessment-notifications.md), which credits - `OutboxFlushBehavior` to Phase 02a and books the queue two ways; and - `infra/apisix/README.md`, which dates the dashboard's gateway gating to Phase 08a. Two - more sentences go stale on landing: the post-commit-seam comment that names this - phase's outbox dispatch as its obligation, since a polling dispatcher needs no such - seam; and - [Security Standards § The out-of-band setters](../standards/11-security.md#the-out-of-band-setters), - whose transport row and reproduced count both change when the transport opens a - transaction. - - -## P02b-4 review corrections (2026-10-19) - -**Status: local validation and both fresh independent review rounds complete; -final-source hosted qualification remains pending.** Work stays on -`development`. These corrections apply the existing Accepted contracts and the -explicitly approved quota accounting below; no new job runtime, role, grant, -quarantine-release authority or ADR is introduced. - -### Verified corrections - -- **Capacity visibility.** Transactional work parked in `reconciling` with an - unreleased reservation now makes unmapped `jobs` health unhealthy. One boolean - joins the existing complete immutable observation statement and snapshot; gauge - callbacks issue no SQL and acquire no new labels. Parking and reservation - retention remain intact. The actual PostgreSQL proof covers pending/live work, - peer recovery, empty-registry observation and the original invocation's late - positive no-start cleanup, which restores routability without another attempt. -- **Actual admission in checkpoint proofs.** The checkpoint fixture now invokes - `AdmitBackgroundJobAttemptCommandHandler` through the real pipeline instead of - copying its INSERT/UPDATE SQL. Bounded runtime options supply explicit attempt - deadlines. Recovery/fairness scenarios declare capacity for their sibling - histories; admission still locks/counts every reservation. The first run caught - three fixture scenarios trying to exceed the original one-slot declaration. - They pass with explicit fixture capacity; the initial failure is not green - regression evidence. The independent attempt observer also accepts an explicit - tenant, with positive tenant-B and tenant-A isolation controls. -- **Distribution qualification.** The verifier uses its reviewed checkout as the - manifest authority and requires published manifest copies to match. It checks - each source archive's pinned PAX commit as well as its trusted digest. Actual - binary/notice/source co-tamper controls must fail. Dapper notice versions are - pinned alongside the existing graph checks. The documentation distinguishes - archive identity and the four original shared binaries from a reproducible - upstream build or a whole-dependency-tree integrity claim. -- **CI refusal and fork shape.** GitHub may return an empty pull projection for a - fork run. The aggregate accepts it only with the API's explicit distinct fork - repository, while preserving exact run/attempt/head/workflow, raw merge-parent - and checkout bindings. Same-origin, malformed or substituted identities still - fail. Unexpected CLI/import/API-shape faults return a closed refusal rather than - exception text. Python bytecode is excluded from repository source inventory. -- **Fixture bounds.** Zero-value controls now cover all positive-only runtime - budgets. Held-COMMIT proxies in the capacity completion/no-start scenarios have - explicit two-minute lifetimes so their configured transport outlives the - scenario's bounded holds and cleanup. -- **Live corpus.** Isolation/security/observability and downstream consumers now - describe identifier-only typed submission, authoritative job rows and opaque - Hangfire hints. Retired base-class/rule examples no longer teach a live contract. - Catalogue/audit status headers reflect delivered enforcement. Front doors link - this phase's current status instead of copying Step 4–8 histories. Phase 03 - explicitly owns the audited quarantine-reconciliation design and its required - trigger/grant migration; no such authority is activated here. - -### Dispositions without runtime changes - -| Examined concern | Verified disposition | -|---|---| -| Late renewal refusal cancels work | Existing lease/admission safety closes permission on uncertainty and prohibits reopening it from a late response. Probing before refusal would change that policy. | -| Cleanup queue overflow should clear its sticky fault | No production path exceeding the bounded 64 execution owners and 128 request slots was demonstrated. Clearing a retained-cleanup fault without a witness is unsafe. | -| Acknowledged COMMIT becomes a failed job after cleanup | The executor reads the commit gate's ACK and preserves definitive success separately from retained cleanup. Suppressing the coordinator exception would lose cleanup evidence. | -| Failed native thread startup should signal completed cleanup | Ambiguous `Thread.Start` failure deliberately retains ownership; catch entry is not a positive join witness. | -| Opaque startup refusal should keep its inner exception | Provider text is intentionally excluded. A finer closed diagnostic taxonomy is an optional operability change, not a demonstrated correctness defect. | -| Quarantined rows cannot currently be edited | Phase 03's operator surface and authorization are not delivered. The freezes preserve uncertainty; nonterminal does not promise an ordinary-role release path. | -| Consolidate historical trigger bodies | Versioned Up/Down snapshots must not read a mutable shared body. No historical migration is rewritten. | -| Duplicate reservation index | The full FK/history index and unreleased-only occupancy index have different predicates and purposes. | -| Native observation masks a Python error | GitHub's default Ubuntu run shell uses `bash -e`; a Python failure stops before the following `cat`. | -| The bounded shard control runs only one suite | Its entry point loads plan and result controls under the same finite budget; earlier native controls have separate ownership. | -| Old counts, amendments and prior CI failures should be rewritten | Dated receipts retain their original source/population. Existing ADR amendments already redirect the retired model. Accepted bodies and historical counts remain unchanged. | -| Fixed 31-second sleeps | The cited occurrences are unit-test manual-clock advances, not real sleeps. Held-callback negative windows test an explicit barrier, not readiness by delay. | -| Broad refactors, caching, extra labels or dependency-wide notices | No reproducible correctness/isolation defect was established. Detector/fixture decomposition, bounded allocation/polling optimizations and repository-wide packaging policy are not bundled into these corrections. | - -Observation-only diagnostic naming, aggregate failure-artifact convenience and -source-test reflection coupling do not change admission, durable state, audit or -qualification. They are not reasons to weaken existing fail-closed paths. - -### Evidence availability and final qualification - -Run `39188256776` completed both layouts on source `1dbde1a3`. Each was independently -reconstructed while its complete archives were available. On 2026-10-19 the -attempt-A aggregate IDs `12159885492` and `12159366005` return HTTP 404, and the API -lists no attempt-A execution archives. Attempt B remains available; all twenty -execution archives and both aggregate ZIPs were downloaded and checked against -API digests. No deletion cause is inferred, and the current API cannot reconstruct -attempt A. Earlier local verification is not a promise of indefinite remote -artifact availability. - -The PR's ready-for-review claim was withdrawn while these corrections run. Final -qualification retains ADR-0063's two full attempts of the **same workflow run**, -with unchanged plan, required checks and ceilings. Before retrying all jobs for B, -retain A's twenty execution ZIPs, two aggregate ZIPs, API metadata/digests and -independent reconstruction. Recheck remote availability after B and distinguish -verification performed at the time from artifacts still downloadable today. -PR #32 owns the final source, actual outcomes and retained evidence location. - -### Local validation and review gates - -The Release solution build passes with zero warnings/errors. Unit 2,455, HTTP -177 and Contract 4 pass with zero skips. The PostgreSQL checkpoint/admission/ -control run passes 334 of 335 cases; the new capacity fixture initially carried -an invalid lease/progress pairing. After correcting and rebuilding that test, -its complete parking/late-cleanup proof passes. Four actual native capacity -completion/no-start cases also pass, including lost acknowledgements. Thus all -339 distinct affected PostgreSQL cases have a passing applicable result; the -intermediate failed run is retained as failed evidence, not renamed as success. - -The real distribution baseline and 23 dirty/replacement controls pass. Combined -plan/aggregate controls 51, native environment 5, provisioning 18, native owner 40, -ADR parser 7 and focused frontend source inventory 19 pass. Full frontend -verification passes 1,625 cases across both packages with zero skips or todos. -Changed-document link inspection finds no new broken target; the catalogue's literal placeholder -`#name_lowercased` remains documentation syntax rather than a real anchor. - -Full Architecture verification passes all 410 cases with zero skips. Final-source -hosted qualification remains pending in PR #32; no skipped or forced-cleanup -result will be counted as a passing proof. - -**Fresh review round 1.** Two new independent reviewers examined -`1dbde1a3..df6e2761` across runtime/ownership/tests and tooling/CI/corpus. Both -approve the runtime and test corrections. One reviewer found five additional -live-corpus passages still teaching `JobParams`, payload trace metadata or -`JobActivator` authority. The isolation table, observability, pipeline guidance -and shared skill instructions now use the authoritative row and `JobExecutor`. -A scoped residual scan leaves only the explicit retired catalogue navigation and -an example owned by the separate Hub repository. The second reviewer independently -ran all 51 plan/aggregate and 23 distribution controls and reconstructed the -339-case PostgreSQL receipt union. No code defect or weakened assertion was found. - -**Fresh review round 2.** Two different independent reviewers examine -`1dbde1a3..bc5bf1c2` and the final documentation correction. Both approve with no -open actionable finding. They independently run all 51 plan/aggregate controls -and the actual distribution baseline with all 23 dirty/replacement controls; -one also runs seven ADR parser controls and verifies 36 added local links. Both -verify the remaining correlation delivery-table correction: authoritative rows, -delivery ownership and `JobExecutor` restore context, while Hangfire hints stay -opaque. They run no C# builds or hosted qualification; the local suites above -are separate evidence. All verified corrections are committed before freezing -the source for two complete hosted assignments. PR #32 owns the final hash, -actual A/B outcomes, independent reconstruction and current archive availability; -this local receipt does not claim those pending runs have passed. - - -**Qualification follow-up.** The first hosted run of `8cd789de`, -[39231264902 / attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39231264902/attempts/1), -exposes six failures in two ordinary shards. They share one test-only SQL helper: -it searches for the previous complete six-column output projection after the -capacity observation adds a seventh field. A local unchanged-source run reproduces -all five invalid-fact theory failures at that exact guard. This is a verified -coverage gap in the earlier focused test selection, not a passing qualification. - -The helper now identifies the unique terminal projection prefix and final output -suffix before replacing that projection. Every production CTE, hash arithmetic, -validity check and typed binding remains intact; the planted date/hash/history -mutants retain their assertions. The actual Release build passes without warnings -or errors, and the complete recurrence store suite passes all 110 cases with zero -skips, including all six affected cases and their mutant controls. The production -query is unchanged. Two fresh sequential focused reviews independently approve -`8cd789de..6bcc2b9a` with no actionable finding. They verify the unique cut, -unchanged production SQL, all caller/mutant assertions and both actual TRX -receipts; neither reruns .NET or claims hosted qualification. The failed hosted -run completes with 24 successful jobs, the two affected ordinary failures and -the correctly failing integration aggregate. It is retained as failed evidence. -Renewed complete A/B qualification follows the corrected source freeze; PR #32 -owns the final hash, actual outcomes and archive availability. - - -**Native fence proof follow-up.** On corrected source `12c79f38`, -[run 39233496115 / attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39233496115/attempts/1) -passes the six recurrence cases but fails one native final-fence expiry case. -The retained location identifies its strict `last_error` read. A controlled local -schedule waits for the next generation's actual bridge ACK before that read and -reproduces `Column 'last_error' is null`. The bridge intentionally clears this -transient diagnostic on successful pending-row handoff; the test was racing -that separate, valid operation after observing rollback. - -The fence case now observes the first real committed handoff and positively joins -only the bridge before releasing the held business handler. Business execution, -lease expiry, app-role row-lock fencing and control recovery remain real. Every -strict rollback/error/attempt/effect assertion remains unchanged; no nullable -alternative replaces the error assertion. Bridge repair has its separate actual -native proof. A fresh warning-as-error Release build succeeds; both final-fence -branches, that repair proof, all bridge cases and the retry-progress proof pass -32/32 with zero skips. The deliberate old-schedule failure is retained as a -falsifiability receipt. The hosted run ends with 25 successful jobs and the -correctly failing ordinary/integration pair, not qualified A/B evidence. Focused -independent review and complete final-source qualification remain pending. - -The first fresh focused reviewer finds a valid ordering gap in `f8c003a7`: the -staged child's parent FK already holds KEY SHARE, so the initial ACK's FOR UPDATE -can wait behind the held handler. The corrected test signals native body entry -before staging, asserts no child exists, observes the committed ACK and joins the -bridge, then opens the staging gate and waits for its completion. Cleanup opens -both handler gates. All original fence/rollback/effect assertions remain intact. -A fresh warning-as-error build and the same complete 32-case selection pass with -zero skips; the earlier passing schedule did not cover this ordering and is not -presented as proof against it. Focused fix verification and a new second review -precede another final-source freeze. - -The first reviewer verifies `2b626235` resolves that finding and approves. A new -second independent reviewer approves `12c79f38..2b626235` without findings, -checking both ACK/native-entry orderings, bridge/execution gate separation, -cleanup and every preserved assertion. Both inspect the actual 32-case TRX and -the deliberate null-diagnostic failure; neither reruns the suites or claims -hosted qualification. Both focused rounds and verified corrections are complete. -PR #32 owns the renewed final-source A/B results and retained evidence. No new -runtime code, source-selection rule, privilege or deadline is introduced by -these test corrections. - -### Additional verification and evidence reconciliation (2026-10-19) - -**Status: all local corrections and both independent review rounds complete; -renewed final-source qualification pending.** -This pass retains existing ADRs, durable-state authority and phase boundaries. - -#### Previously qualified source and retained evidence - -[Run 39236406151, attempt A](https://github.com/HodeTech/LearnStack/actions/runs/39236406151/attempts/1) -and [attempt B](https://github.com/HodeTech/LearnStack/actions/runs/39236406151/attempts/2) -both pass all 27 jobs on development head -`62ad318cc79b1f3f4888c03158b158336bea6010`. The checkout SHA -`3104c0fc2d812bfacda4825594263cc339363556` identifies GitHub's generated PR #32 -merge-ref commit, not a development commit. GitHub's commit API identifies its -parents as `ed60157c14d33fad926fd201b49c08e2d24eed1f` and that development head; -the retained source/aggregate checks independently verify the binding. - -Each exact union contains 5,482 backend cases, zero skips: 2,455 Unit, 410 -Architecture, 177 HTTP, four Contract and 2,436 Docker, including 31 native. -The older 2,432 Docker count belongs to an earlier source and is not substituted -for this result. Both actual assignments differ, including SharedSchema groups. -Execution jobs take at most 809/777 seconds for A/B; all aggregates remain within -five minutes. The seven strict required contexts and protection readback agree. - -All 22 A archives and their API metadata were retained before rerunning all jobs -for B. Afterwards A's IDs return 404; B remains downloadable. The complete local -bundle `learnstack-pr32-evidence-39236406151.tar.gz` has 44 ZIPs, 40,756,752 bytes -and SHA-256 -`9630ede9052e7f20b1d9db18440a8a595030c519cf52daeed8a9d1644370e0db`. -Its `verify-retained.py` entry point is packaged inside the bundle, not under -repository `scripts/`. From its extracted directory, run -`python3 verify-retained.py /path/to/qualified-checkout` at `62ad318c`. -Independent reconstruction again passes both 5,482-case unions and checks the -different co-membership. This verifies captured API responses and archives; it -does not reauthenticate unavailable responses or rerun tests. The bundle is a -shared-workspace artifact, not a public GitHub download. New source still requires -renewed complete A/B qualification; this prior receipt is not proof of these -subsequent corrections. - -#### Verified scope and dispositions - -| Examined concern | Current verification and action | -|---|---| -| Eager dispatcher parsing breaks absent configuration | Existing null/empty/whitespace controls pass: Npgsql's builder supplies defaults, the lazy source remains uncreated, and mandatory resolution refuses with the named key. No production change. | -| Duplicate statistics-history filters are tolerated | Existing code rejects more than one. Zero is valid after intentional one-time removal. No filter-policy change. | -| Blank application settings reach a raw first-query error | The lazy application source calls its named validator before building/opening the pool. No eager validation added. | -| Pool worker bound lacks an independent discriminator | Add one 17-worker pool below the total-worker ceiling, retain the accepted 16-worker control, and test retained-bound arguments zero and seventeen. | -| Domain-event drain boundary lacks a direct unit proof | Add inclusive 256 and rejecting 257 controls with FIFO, repeated-collection and rollback-only assertions. Existing PostgreSQL rollback proofs remain. | -| Explicit Retry-After is overwritten | Preserve an existing delta/date value; supply the existing default only when absent or empty. | -| Cleanup wait's boolean is ignored | `Completion` is a Task, not Task<bool>; awaiting WaitAsync already requires successful completion. No weakened or discarded boolean exists. | -| Dependency/comment drift | Remove the unused audit-adapter MediatR reference; align its catalogue/coordinator description, Next patch comment, middleware XML summary and P02b-5 authentication owner. | -| Moving CI action tags and scanner admission | Pin all 39 uses to seven reviewed upstream commits; future updates require review. Go already uses its checksum database; additionally require exact module and go.mod hashes before scanner installation. Keep aggregate upload identity exact and reject a tag or substituted commit. | -| ADR comparison silently skips an unresolved base | Require the actual PR base SHA, push predecessor or explicit manual base, and refuse an unresolved base or failed diff. Require the SARIF artifact instead of warning when absent. | -| Plan-gated content-type count is unenforced | Confirmed pre-existing gap. The maintainer approves distinct nondeleted custom keys, shared revision slots, excluded card default and last-live-revision deletion releasing capacity; the shared writer must serialize count/insert tenant-wide. Approval precedes implementation. | -| Broken ADR-0038 anchor | Standards 13 already provides the exact `adr-amendments` HTML alias. The accepted record is not edited. | -| Historical SQL copies or loose-then-tightened policies should be folded | Up/Down snapshots preserve versioned rollout and reversal. Current canonical bodies have parity proofs; no historical migration is folded or made dependent on mutable SQL. | -| Vendor installer leaves search_path set | Pinned Install.v23.sql ends with RESET search_path. No session-setting change. | -| environment.json is unbound | The API-authenticated SHA-256 covers its entire ZIP, including this observation file. No independent qualification authority is attributed to the file. | -| Control cleanup limits are below the supported topology | At most 32 workers plus eight pools times four retained executions is 64; 128 request slots allow the documented cleanup boundaries. The proposed 160-owner premise exceeds the accepted topology. | -| Catalogue guards should source-parse integration methods | The architecture guard explicitly owns its compiled assembly and a repository-wide orphan check. All nine job integration owners are real discovered tests. Source parsing would reintroduce the documented conditional-compilation blind spot; no absent current owner was found. | -| Test reflection, real-time negative windows and canary naming | No bypass of a production boundary was demonstrated. Narrow two test names to their actual copy/closed-shape assertions; retain real gate/cleanup negative windows and native proofs. | -| Display locale, enum fallback and fifth public route | English is the accepted display fallback; the two-value enum is checked in domain/storage; served OpenAPI and its extra-route mutant already reject surface drift. No speculative refactor. | -| Audit diagnostics, slug helpers, tracker complexity and startup round trips | No incorrect durable outcome, isolation leak or unbounded admitted input was reproduced. Existing closed diagnostics remain; batching/helper extraction requires evidence beyond code similarity. | -| Terminal timestamp/transaction liveness symmetry | Existing event witnesses bind the fenced row and same live transaction under ADR-0046. Job witnesses have their separate ADR-0047 contract; copying their wider shape is not an established event defect. | -| Unused assert-tests-ran helper and FailureDescriptor constant | The first remains a source-inventory subject and its cited dated receipt is historical. The second documents the storage descriptor ceiling. Neither silently bypasses the current CI owner. | -| Broader refactors, generated-file headers and recurring protection recorder | No current contract failure established. Do not hand-edit generated output, add a recurring automation or expand this correction into unrelated extraction work. | - -Phase 03 retains first production definitions, audited operator recovery and any -new terminal caller census. Phase 04 retains real media capacity/limit consumers; -Phase 06 owns the Studio audit-config writer and public error experience. Phase -11 retains mapped readiness, supervised deployment/dump policy, retention/purge, -connection-pooling qualification and production/browser operational diagnostics. -These are existing owners, not delivered features of this correction. - -The warning-as-error Release solution build passes with zero warnings/errors. -All 2,463 Unit cases and five compiled corpus guards pass with zero skips, as -does the actual production-manifest test. The 51 combined shard controls, seven -ADR lifecycle controls and seven new supply-chain controls pass. The real scanner -installation verifies both pinned sums and its resulting Go module metadata; -actionlint accepts the pinned workflow. The quota proposal remains non-runtime -and was awaiting the maintainer's accounting choice at this source. - -**Additional review round 1.** Two fresh independent reviewers examine -`62ad318c..cd69bbc6` across backend/contract tests and CI/dependency/evidence -boundaries. The backend reviewer runs 70 focused cases, zero failures/skips, -and identifies one valid documentation mismatch: Standards 09 still calls thirty -seconds unconditional. It now describes the absent/empty default and preservation -of an explicit value. The CI reviewer independently verifies all seven upstream -commit identities, 51 shard, seven lifecycle and seven supply-chain controls, -actionlint and both retained historical 5,482-case unions. These are separate -local checks, not qualification of the new source. - -**Additional review round 2.** Two different fresh reviewers examine -`62ad318c..abd5320b`. Both approve without a correctness/security finding. -The backend reviewer runs 111 focused unit/configuration/corpus cases, zero -failures/skips; the CI reviewer again runs all 51 shard, seven lifecycle and -seven supply-chain controls and actionlint. The latter independently verifies -official action identities, both Go sums, the historical merge parents and the -bundle hash/implementation, but does not rerun its offline reconstruction. -An optional new weekly Dependabot schedule is removed after scope review; exact -SHA admission and its mutation controls remain. Parent verification also passes -177 HTTP and four Contract cases, zero skips, and complete format verification. -All 512 relative links in the changed documents resolve, including HTML aliases. -No reviewer claims full hosted qualification for this corrected source. - -**Quota acceptance.** The maintainer explicitly selects the proposed accounting -on 2026-10-19; its -[accepted rule](phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19) -precedes the shared-writer change. No new ADR or unapproved counting policy is -introduced. Runtime implementation and its two independent review rounds follow. - -**Source-inventory qualification failure.** On `617ed087`, -[run 39250697987](https://github.com/HodeTech/LearnStack/actions/runs/39250697987) -passes frontend lint and production build, then fails its real genericity census: -the two newly introduced Python CI tools lack explicit non-runtime ownership. -The failure identifies `scripts/install-leakwatch.py` before reaching the second -new entry. Both exact paths are added alongside the existing CI tools, with -positive classification controls; unknown Python files still refuse. The full -guarded frontend run then passes all 1,625 cases in both packages, zero skips or -todos. The earlier focused frontend omission is a real verification gap. The -failed run is cancelled after that failure because the approved quota also -changes its source; neither that run nor its interrupted jobs qualify A/B. - -**Quota implementation and local proof.** The shared registration writer now -acquires the tenant-wide quota lock before its concept lock, then checks distinct -nondeleted custom keys and inserts on the same ambient transaction. Revisions -share one slot, the built-in card is excluded, and the last live revision's -tombstone frees its slot. Unlimited feature/numeric grants bypass the ceiling; -zero admits no new custom key. The explicit `limit_exceeded` mapping returns 403, -preserves the limit key/allowance in field errors, records Denied audit outcome -and is permanent in the existing job failure taxonomy. No migration, new default -entitlement or deletion/restoration authority is introduced. - -Full Unit passes 2,471 cases, zero skips. The PostgreSQL quota/default/publication -selection passes 41 cases, zero skips; the final seven quota cases also pass after -the controlled mutation is restored and rebuilt. A temporary removal of the real -quota advisory lock makes the actual advisory-wait proof fail; production bytes -are restored exactly before the positive rerun. The initial PostgreSQL run's one -failure was a fixture assumption that the Null provider supplied a finite plan; -it intentionally supplies all-enabled/unlimited under ADR-0045. The corrected -tests preserve that default and exercise the real resolver against an explicit -plan projection. That failed receipt remains failed evidence. Independent quota -and source-inventory reviews precede renewed complete hosted qualification. - -**Quota review round 1.** Two fresh independent reviewers examine -`617ed087..04b4e782` across transaction/isolation/concurrency and -API/audit/job/error/corpus/source-inventory contracts. Both approve without a -verified finding. They independently run seven PostgreSQL quota cases and 181 -focused Unit cases on current Debug binaries, plus all 19 genericity cases with -their result guard. Their initial stale Release selections are not current-source -evidence. The parent rebuilds the entire Release solution with zero warnings or -errors, then runs all 2,471 Unit and 41 quota/default/publication PostgreSQL cases -in Release: all pass, zero skips. A different fresh review pair follows before -source freeze; no hosted qualification is claimed by these local receipts. - -**Quota review round 2 and source freeze.** Two different fresh reviewers examine -`617ed087..d2c414ee` and approve without verified findings. They independently -confirm all new cases are present in current Release binaries before running -seven actual PostgreSQL quota cases and 181 focused Unit cases, zero skips. -All 19 genericity cases and the result guard pass; unknown Python files still -refuse. The contract reviewer verifies all 607 relative links/fragments in the -changed documents. No test mutation, disabled guard, schema/grant change or new -lifecycle authority remains. Parent Release build/format, all 2,471 Unit, 177 -HTTP, four Contract and 41 affected PostgreSQL cases pass, zero skips; complete -frontend remains 1,625 cases across both packages. The source is frozen after -this receipt for both complete hosted assignments. PR #32 owns the exact final -head, actual A/B outcomes and retained evidence availability; none is claimed -passed here before execution. - -## P02b-4 merge and closeout (2026-10-19) - -The maintainer merged [PR #32](https://github.com/HodeTech/LearnStack/pull/32) -on 2026-10-19 at **17:08:09 Europe/Istanbul** (14:08:09 UTC). -GitHub records final development source -`1261c38268ff194a047f987c4ee8ffdb68ab1382` and squash merge -`b81006c7af7d38f1587ecb3bf93dbcca16f353e0`, whose parent is previous main -`ed60157c14d33fad926fd201b49c08e2d24eed1f`. Source and squash merge have the -identical tree `9c2ad62ca821ff7c886553518eab50c28094a29c`; the direct tree diff -is empty. Development incorporates the main merge without switching branches or -rewriting published history. This closeout changes no runtime, migration, grant -or Accepted ADR. - -**Final-source hosted qualification is complete.** Both full assignments of -[run 39253376497](https://github.com/HodeTech/LearnStack/actions/runs/39253376497) -pass all **27 jobs and 5,505 backend cases per attempt**, with zero skips: - -| Assignment | Actual attempt | Backend case union | Cleanup | -|---|---|---|---| -| A | [Attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39253376497/attempts/1) | 3,062 non-Docker + 2,443 Docker | Natural, complete | -| B | [Attempt 2](https://github.com/HodeTech/LearnStack/actions/runs/39253376497/attempts/2), Re-run all jobs | Same complete union | Natural, complete | - -The non-Docker union contains 2,471 Unit, 410 Architecture, 177 HTTP Integration -and four Contract cases. Docker contains 2,412 ordinary and 31 native cases. -Frontend, meta, secret scan, OpenAPI and public demo/Lighthouse pass in both -attempts; the complete guarded frontend suite contains 1,625 cases. -The checkout/workflow SHA is GitHub's generated PR merge-ref -`d062b67ed79f9c85d46d8faab44189e20b959729`, whose verified second parent is the -final development source above; it is distinct from the later squash merge. - -Independent reconstruction checks both complete protocol/TRX unions, artifact -API digests, producer-job ownership, source identity and actual natural cleanup. -Both attempts use the same source, plan, manifest and actual toolchain, with -verified different co-membership including SharedSchema: 218/254 Architecture -and 992/1,085 ordinary selector groups change owner. Maximum execution-job walls -are **846 seconds (A)** and **812 seconds (B)**, below 1,200 seconds. Each -aggregate finishes below 300 seconds; backend/integration pre-upload processing -is 16.441/31.655 seconds for A and 11.347/17.068 seconds for B. All seven strict, -app-bound required contexts and the entire branch-protection configuration are -unchanged in the final readback. - -| Aggregate | Artifact ID | SHA-256 | -|---|---|---| -| A backend | `12187997537` | `9b34b0a92d55ecd74555224987e3bf11dbcc9680d0e5fb7e694f3823ecac7a41` | -| A integration | `12187354369` | `4eac0bacedd3f30e99472db97eb8cd20a44c7855bdd085a8d0b4927d57063e5f` | -| B backend | `12191355246` | `18b1f18c57cabe19ad07e9aa7b7890f1e33364bd3cc9697e906fa381b8488400` | -| B integration | `12191520422` | `0482a80e92d608f06f305ff9b2bd749df36f0ee44fc0366c90104f1fbd8565ee` | - -**Evidence availability has a narrower bound.** All 22 A archives and their API -metadata/hashes were downloaded and independently verified before B began. -Final qualification readback returns HTTP 404 for all 22 A artifact IDs, while -all 22 B archives remain available. No deletion cause is inferred; the current -API cannot independently reconstruct A. The retained review bundle contains -all **44 ZIPs**, captured metadata, source/hash manifests, both receipts and the -comparison: `learnstack-pr32-evidence-39253376497.tar.gz`, 40,974,306 bytes, -SHA-256 `028de8d8d2bc6584a90e84f16755187cd2c32d600c2e80d98ad3ea19e18ce98d`. -Its packaged `verify-retained.py` reconstructs both attempts offline against -checkout `1261c382`; that entry point is inside the bundle, not repository -scripts. This verifies retained integrity/results without reauthenticating -unavailable API responses or rerunning tests. - -The separate post-merge push -[run 39266220267](https://github.com/HodeTech/LearnStack/actions/runs/39266220267) -was queued when merge verification began. It is not counted as a completed -post-merge proof; its live result remains separate from the final PR-source -qualification and identical-tree verification above. - -**P02b-4 is closed.** All nine runtime steps in the -[delivery table](#p02b-4-local-closeout-2026-10-18), all three ADR-0063 CI steps -and verified review corrections are delivered. Their independent review rounds -and negative controls remain recorded above. The final corrections also enforce -the approved distinct-key content-type quota under one tenant-wide transaction -lock, preserve explicit Retry-After values and close CI dependency/diagnostic -verification gaps. Earlier dated receipts retain their pre-merge or failed state; -this closeout does not relabel them as successful final-source evidence. -Production job and recurrence definitions remain empty. - -**Next: P02b-5 API authentication decision pass.** Re-verify G10/G11, G12's -BFF-client choice, G14 and G20 before implementation: UUID claims/actor identity, -host/JWT reconciliation (including organization and claimless-token outcomes), -client/issuer/audience validation, an explicitly bounded authenticated read -surface, validated-subject rate limits and the agreed anonymous 404/401 rules. -The pass must reconcile the existing ADR-0036, Security Standards and catalogue -carriers before code. No new gate is accepted by this closeout. - -P02b-6 owns realm mappers, admin-only UUID attributes, warm-realm reconciliation -and token/TTL proof. P02b-7 owns BFF token custody, single-flight refresh, CSRF, -logout and studio/session behavior. P02b-8 owns LS0002, retained-store erasure -inventory, remaining carrier reconciliations and the Phase 02b exit. Phase 02b -therefore remains in progress. Operator recovery/privileged execution stays -Phase 03, real media adapters/process-tree proof Phase 04, and mapped readiness, -supervision, retention and production sizing Phase 11. - -**Documentation-only closeout validation.** Five Release corpus consistency -cases and seven ADR status/parser controls pass, zero failures/skips. All 1,002 -relative links/fragments in the seven changed Markdown files resolve. Added prose -wrapping, whitespace and residual checks pass; every dated delivery/review record -and every Accepted ADR file is byte-preserved against the final PR source. The -runtime suites are not rerun locally for these status/navigation edits; their -final-source qualification is recorded above. This closeout starts no next packet. - -## P02b-5 decision package (2026-10-19) - -**Accepted — 2026-10-19.** The maintainer explicitly approved revised -[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md) and this -five-step package together. G10/G11/G12-client/G14/G20 are Accepted. All work -stays on development, with commit plus two fresh independent review rounds -for each step. P02b-0–4 remain complete and merged; P02b-5 implementation begins -with the acceptance commit before dependent runtime code. - -**Maintainer review follow-up — 2026-10-19.** The revised contract below addresses -verified review findings. The earlier decision-review opinions remain historical; -this follow-up replaces their readiness conclusion. Both fresh independent -revision review rounds are complete; the dated acceptance record below records -the subsequent maintainer approval before runtime work. - -### Problem statement and verified entry - -Deliver the API half of tenant authentication: validate a signed access token, -reconcile it with the independent host scope, attribute rejections through the -existing recorder, and expose one genuinely read-only authenticated production -operation with an independently checked host ceiling. Keep public rendering -independent of Keycloak, and keep role, -membership, realm reconciliation and session work with their named owners. - -The entry audit used `development` at `0e23cb14`, following the verified P02b-4 -merge. Three independent read-only audits checked HTTP/isolation, identity/client -boundaries and corpus/test ownership. Their facts were cross-checked against the -current tree; they executed no tests and made no runtime edits. - -A fresh read-only check also confirms the post-merge -[main CI run 39266220267](https://github.com/HodeTech/LearnStack/actions/runs/39266220267) -completed successfully at `b81006c7af7d38f1587ecb3bf93dbcca16f353e0`. -The earlier merge closeout retains its honest queued-as-of receipt. This check -starts no new workflow and is not a P02b-5 implementation test. - -| Verified premise | Consequence for this packet | -|---|---| -| No JwtBearer package, scheme, `UseAuthentication` or `UseAuthorization`; the resolver's reserved claim site supplies no claims | Configuration/DI checks and supplied factory attempts are not authenticated HTTP evidence. Use real signed tokens through the actual handler. | -| Two public controllers expose four GET/HEAD pairs; no protected production route | Add a real protected subject. Existing public census does not constrain future protected routes. | -| Application `AuthorizationBehavior` still delegates; `HostAndClaim` admits ordinary requests | Bound production routes and their transitive request dispatch before activating claims. No authoring command can be exposed during the window. | -| Membership reader denies everyone; row 10 asks about the host's organization | Row 10 stays 404. A matching Yoga organization claim takes row 9; it does not implement membership. Correct the older staging claim using dated errata. | -| Rejection record has only tenant, dimension, asserted UUID and authenticated bit; resolver failure only logs | Carry source/actor/correlation/trusted organization explicitly, call the existing recorder and retain its two operation keys. | -| Existing admission spends visitor 60/min and physical peer 600/min before classification | A later 600/min subject limit is an additional ceiling. It cannot establish independent throughput past these floors. | -| Keycloak 26.6.2 export has no custom mappers/scopes, a public web client and slug-valued tenant attributes; seed only polls readiness | P02b-5 qualifies the API contract with a controlled issuer. P02b-6 must independently deliver actual token issuance and warm reconciliation. | -| Framework authentication can return failure/NoResult without terminating an anonymous endpoint | A scoped credential-result gate must reject present invalid credentials even on public routes. | -| `BackgroundJobExecutionAdmission.ModeFor` selects physical ReadOnly only for public requests and two exact framework reads | Add the exact new authenticated query to positive read-mode selection. Do not label it public or use a query-name heuristic. | -| SDK `PUBLIC_GET_WRAPPERS` presently covers every generated GET path | Separate the exact public operations from the new authenticated contract during regeneration; preserve credential-free public transport. | -| Name-based telemetry redaction does not sanitize arbitrary exception messages | Token canaries must be absent from logs/spans/error captures, not merely response bodies or named properties. | - -### Accepted decisions - -This table summarizes owner choices. ADR-0064 is the canonical contract; the -summary does not redefine its validation details. - -| Gate / choice | Recommendation and explicit cost | -|---|---| -| G10: identity | Scalar UUID `tenant_id`, stable admin-assigned `user_id`, optional scalar `organization_id`; opaque `sub` remains external identity. Reject empty/reserved actors and malformed/duplicate claims. No memberships array or realm-role authority. | -| G11: organization | P02b-6 issues Yoga's matching organization claim; P02b-5 proves row 9 with real signed test tokens. Tenant-only row 10, tenant-host organization row 7 and platform claim row 14 still fail until Phase 03 membership. | -| G11: claimless token | Preserve the validated actor for attribution while HostOnly still limits authority to public reads. Emit one fixed Debug diagnostic without claim text; protected read is 404. No new origin, error code or actor suppression. | -| G11: platform membership audit | Refuse row 14 with 404 but no durable tenant row when there is no confirmed host tenant. This explicitly replaces only its `+ record under T_j` clause; no claimed/sentinel tenant is fabricated for audit. | -| G12: API/BFF client split | Convert `learnstack-web` to the confidential PKCE BFF client in P02b-6; API pins its `azp` and `learnstack-api` audience now. Old API-client service-account tokens do not satisfy this user profile. API needs no client secret. | -| Token/key posture | RS256, exact tenant issuer, duplicate-free JOSE allowlist (`alg`, `typ`, `kid`), payload Bearer, stable actor, 30-second skew and one-hour maximum lifetime. Suppress raw JWT vendor diagnostics at all levels and replace them with closed outcomes. Old-configuration reuse cannot reaccept an observed withdrawn key; immediate session revocation is not promised. Issuance TTL remains G13/P02b-6. | -| G14: quota | Preserve existing early visitor/peer floors for every credential; add stable issuer+subject 600/min accounting before audit. Reduced-subject whole-chain proof plus separate actual-default boundary. Cost: NAT/BFF sharing can throttle users below 600/min; independent end-to-end 600/min is not promised. | -| G14: routable read | One GET `/api/v1/account/site`: own actor/resolved scope and existing live `PublicSite` data, non-public Off query, physical ReadOnly, no scope parameters. The query itself checks HostAndClaim and matching HostScope before any reader, even when future membership permits row 14. No authoring/private content or platform route. | -| G20: precedence | Early admission/unknown-host 404 precedes JWT work. Invalid present credentials on known hosts give 401 even on public routes. AccountSite absent credentials give masked 404 on tenant, organization and platform hosts; a scoped authorization result handler prevents a default 401. Rows 8/11/12 and authenticated header mismatches give `tenant_mismatch`; rows 7/10/14 membership refusal and anonymous mismatches give `not_found`. | - -The maintainer accepted these decisions, disclosure instruments and five-step -plan as one package. No additional permission question is needed for routine -implementation within that accepted scope. A genuinely new security or -cross-module decision reopens only its affected boundary before implementation. - -### Document audit actions and acceptance instruments - -The pre-code work uses `implement-task`'s scoping/decision pass and `write-adr`. -The implementation additionally uses `add-mediatr-handler`, `add-audit-coverage`, -`add-architecture-test`, `add-integration-test`, `run-tests-locally`, -`update-glossary` and `commit-and-pr` where applicable. Each review uses -`standards-check` followed by `code-review`. - -| Carrier | Verified issue and required action | Owner | -|---|---|---| -| ADR-0064 and decisions index | New security contract starts Proposed. Move its row only after explicit approval; no inferred acceptance. | Decision pass / Step 1 | -| ADR-0036 matrix row 14 and recording prose | Conflicting audit targets are resolved by the named bounded supersession. Append its own dated disclosure; preserve Accepted body/metadata. | Acceptance | -| ADR-0036 staging table and 2026-09-02 erratum | Both omit that row 10 is membership-dependent. Add adjacent dated errata and a correction section in the same new Amendment, with evidence of falsity at entry; do not edit the earlier erratum. | Acceptance | -| ADR-0036 delegated claim shape and new attribution | Distinguish additive profile/claimless clarification from the preceding replacement and correction; no new context writer. | Acceptance | -| ADR-0040 Amendment 8 and ADR-0052 Decision/Context | Each receives its own dated disclosure of the bounded public-read mode-ordering extension to this exact authenticated query; ADR-0040 also records exact-type selection. Preserve bodies, public guarantees and the setter set. | Acceptance | -| ADR-0032 and ADR-0053/0054 | Preserve the canonical pipeline and coordinated ingress policy. ADR-0052 public host provenance/anonymous projection remain unchanged despite its named read-mode scope extension. | All steps | -| Architecture 09/13/14/28/30/33 | Reconcile memberships-array/role sketch, scalar active tenant, actor projection and middleware order; Architecture 30 also repeats blanket non-public 401 and the no-authentication status. Update that carrier with the catalogue/Step 4 activation. Preserve reissued-token selection, public transport and Phase 03 membership. | Steps 1/4/5 | -| Standards 02/04/05/09/10/11/20 | At acceptance, Standards 11 § Tenant Context names the additional exact ReadOnly query; Standards 04 distinguishes its outer masked refusal from the unchanged generic unresolved gate. Reconcile stable quotas, source-aware recorder labels and fixed Debug diagnostics, plus vendor failure events 1/3/7 and credential privacy. No SQL policy/grant change. | Acceptance / Steps 1–5 as mechanisms land | -| Standards 21 | Narrow blanket-401 row; authority rule has real behavioral owner. Register five ADR-0064 obligations and update canonical counters/statuses only with actual delivery. | Acceptance / Step 5 | -| Tenancy README, audit and permissions | Document AccountSite query/DTO, Off nonsensitive-query audit registration and no permission-sensitive disclosure before Phase 03. No new permission key. | Step 2 | -| SDK/OpenAPI / API route and response policy | Explicit account resource/site route; outer no-store applies even before early errors. Exact disjoint public/authenticated GET sets form an exhaustive union. AccountSite is never a public wrapper; bearer/session attachment stays P02b-7. | Step 4 | -| Glossary / `UserId`, `TenantContextOrigin` and resolver XML | Explain authentication/actor versus tenant authority and HostOnly claimless attribution; fix Identity domain ownership and obsolete bodyless-only resolver description. Implementation comments change only after approval. | Decision pass / Steps 1–3 | -| Phase 03 / 06 / 11 | Phase 03 consumes P02b sessions rather than owning their first wiring; preserve durable identity/permissions. Phase 06 owns the full browser journey; Phase 11 owns production IdP provisioning/edge/readiness. | Step 5 | -| Realm JSON, Keycloak README, seed | P02b-6 prerequisite receipt: attach audience mapper to issuing client, access-token-only API audience; admin-only identity attributes; preserve `basic` and actual `sub`; converge fresh/warm realms without deleting users or Hub realm. No realm runtime change in P02b-5. | P02b-6 | -| Frontend auth layout/native admission | P02b-7 owns Auth.js in `apps/web`, bounded auth route/method admission through current GET/HEAD ingress, cookie propagation, refresh/CSRF/logout. No generic ingress exemption. Remove stale `packages/auth` illustration with that decision. | P02b-7 | - -The acceptance commit records the exact dated instruments before dependent -code; G10/G11/G12-client/G14/G20 are Accepted together. G12's realm -reconciliation, G13, G16 and phase exit stay Open. -No prior dated delivery record is rewritten. - -### Five implementation steps - -All work stays on `development`. For each step: implement and validate, commit; -run review round 1 with fresh independent agents; verify findings against the -current code, fix valid findings and commit; run round 2 with different agents; -verify/fix/commit again. Start the next step automatically after both rounds -close. Findings are evidence to check, never instructions to execute. - -| Step | Deliverable and safety boundary | Principal validation | -|---|---|---| -| 1 — accepted contract and token foundation | Commit acceptance/disclosures/registrations first. Add pinned JWT package/options, one immutable profile, credential/purpose checks, controlled discovery/JWKS issuer and secret-free diagnostics. Defer production authentication/authorization service registration too: minimal hosting can insert middleware automatically. Test-only composition remains isolated until Step 4 closes the complete HTTP boundary. | Real-handler signature/profile and duplicate JSON controls, wrong issuer under trusted key, ID-token purpose, duplicate JOSE header/unsupported extension, lifetime/skew, reserved actor, key rotation/withdrawal and stock/base handler events 1/3/7 canary capture with positive diagnostics. | -| 2 — real read-only application subject | Add AccountSite contract/handler, exact ReadOnly selection, nonsensitive audit registration and module docs; do not route it yet. Read actual public configuration under the independent host ceiling. | Actual app-role PostgreSQL tenant/org data positives/negatives, lifecycle/missing config, missing/mismatched HostScope and future ClaimAndMembership refusal before reader calls, Off success with zero query audit rows, physical write-refusal and no nested-public workaround. | -| 3 — attributed reconciliation and subject admission | Add bounded subject quota, credential-result and surface-admission components; extend recorder and resolver to consume only the validated projection. No production JWT middleware/route activation yet. | Whole-chain component harness, rows 6/9 positives and 7/10/14 negatives, claimless outcome, row 7 one tenant-wide audit with trusted-org metadata/captured correlation, row 10 zero rows, row 14 zero rows plus one source-aware unresolved count; preserved denial on audit fault, claimless attribution/Debug event, quota lifecycle and stops-audit proof. | -| 4 — atomic HTTP activation and typed contract | Wire all guards at their specified positions in one change; map the GET with authorization and exact census; emit no-store/security/errors; regenerate OpenAPI and split public/authenticated SDK contracts. No session transport or realm changes. | Actual API host with real signed tokens, protected 200; absent credentials on all three known host classes masked404, invalid-public401; exact resolver/header/membership codes; no-store on early refusals; future row-14 hostless access404; planted extra endpoint/write/reorder; public/IdP-down regression, SDK partition and served OpenAPI equality. | -| 5 — production enforcement and packet closeout | Complete transitive production censuses and dirty/clean controls, cross-host/actor/key/telemetry matrices, all related carrier reconciliation and local/hosted verification. Update statuses only from actual proof; prepare the PR for maintainer review. | Complete backend/architecture/HTTP/contract/PostgreSQL suites under existing bounded CI plan, frontend guarded suites, OpenAPI compatibility, all seven required checks and retained public demo/Lighthouse proof; no skip or reduced population. | - -No partially safe authentication goes live between steps: Step 4 activates the -validated principal only together with quota protection, recorder, read-only -route and surface fence. Before that, tests exercise completed components and -real handlers in isolated composition. No temporary development bypass is added. - -### Required non-vacuous proof obligations - -- Real signed JWTs enter the real handler, not a fake authenticated principal. - The negative issuer token uses a trusted signing key; the negative ID token - also has acceptable audience/client so purpose enforcement is what fails. -- Duplicate JOSE `alg`/`typ`/`kid`, equal duplicates and every forbidden header - (including `crit`, `cty`, `jku`, `x5u`, `jwk` and certificate material) are refused. - Only configured issuer keys can verify a token; a header/key URL is never authority. -- Repeated/equal JSON properties, singleton identifier arrays, object/null/numeric - identifiers, malformed/empty/reserved UUIDs, timestamp boundaries and actor - substitution have planted controls. No invalid credential is treated as absent. -- A previously accepted unexpired token fails after its key is removed and the - new metadata snapshot is observed. Added-key success alone is insufficient. - Respect the framework's refresh minima and bound every wait. -- The actual non-public query and production route are nonempty census subjects. - Test-only endpoints do not count. A helper/nested dispatch or minimal route - cannot evade the permitted request set. A planted write fails physical ReadOnly. -- AccountSite reads the database: contrasting tenant settings, a visible - organization, an inactive organization and cross-tenant/org claim controls must - distinguish clean from widened scope. No id-addressed resource route is added; - future such routes still owe their separate visible/foreign-id controls. -- Resolver rows 8/11/12 and authenticated header mismatch return `tenant_mismatch`; - membership rows 7/10/14 and anonymous header mismatch return `not_found`. - Row 7 writes the existing slug once under the host tenant; row 10 writes none; - row 14 writes none and increments the source-aware unresolved counter once. - Audit rows remain tenant-wide (`OrganizationId=null`) with trusted organization - in metadata and the previously captured actor/correlation/source. No rejected - ambient context or fake tenant is installed for attribution. -- Claimless profiles preserve actor attribution but retain HostOnly authority: - public read 200, AccountSite404 and exactly one fixed Debug diagnostic without - a claim value. New origins/error codes/metrics are not an implicit requirement. -- AccountSite independently rejects missing/mismatched host provenance and - ClaimAndMembership before any reader, even with a future active membership. - Explicit Off registration yields no normal query audit row. Its outer response - policy returns no-store for success and early401/404/429; route and generated - public/authenticated GET ownership are exact and disjoint. -- Whole-chain reduced-budget tests isolate subject A's refusal from subject B - behind one peer; actual production-floor tests separately demonstrate that - shared IP/peer throttling remains. Token rotation and tenant switching do not - reset subject quota. Rejection stops downstream audit work. -- Invalid credentials on a public known host give 401; no credentials remain - anonymous. Both public sites render with Keycloak stopped. Unclassified health - and contract endpoints do not acquire tenant authentication dependencies. -- Raw-token/issuer/audience/metadata/provider-exception canaries are absent from - all enabled sinks; explicitly sanctioned typed UUID/correlation attribution - remains testable. Exercise stock JWT failure events 1/3 and inherited event 7; - a Warning threshold alone must fail. Positive LearnStack closed outcomes remain - observable, and unrelated application diagnostics are not disabled. -- Every new structural detector has a planted offender/clean control and a - mutation of its predicate which must fail. Complete discovery and existing - shard ownership remain enforced; any required plan reassignment is explicit. - -### Decision-pass review round 1 (2026-10-19) - -Two fresh independent reviewers applied standards-check and code-review to the -proposed contract and package. The security/runtime review used xhigh effort; -the corpus/test-ownership review used high effort. No runtime proof is claimed. - -The verified carrier omission was corrected: Architecture 30 repeats the old -blanket-401 rule and no-authentication status, so it is now explicitly paired -with the catalogue/error reconciliation and Step 4 activation. The read-mode -instrument now names the public-only ordering scope extension separately from -additive exact-type selection. Row 7's existing membership-denial audit and -row 10's no-audit disposition are explicit. Production service registration is -also held until Step 4 because minimal hosting can insert middleware implicitly. -The final security inspection found no remaining actionable finding. - -Local documentation verification passes: seven ADR parser controls, five Release -`CorpusConsistencyTests` with zero skips, 851 relative links/fragments, added -prose width and whitespace checks, exact source-clause verification and -byte-preservation of every prior dated delivery/review record. Only seven -Markdown files change; no Accepted ADR or runtime file is edited. The second -fresh independent review round remains pending. - -### Decision-pass review round 2 and readiness (2026-10-19) - -Two different fresh reviewers, both at xhigh effort, independently inspected -`0e23cb14..5bfe3c3b` and the final mutable introduction corrections. Both approve -for maintainer decision with no verified actionable finding. They checked the -actual handler/factory/recorder/reader, exact bounded source clauses, pending -catalogue names, SDK coupling, shared quota limitations and first-consumer -ownership. Pinned ASP.NET Core 10.0.12, IdentityModel 8.19.2 and Keycloak 26.6.2 -sources support the profile, refresh and implicit-hosting premises. This remains -a static decision review, not authentication or database qualification. - -The final introduction corrections assign realm mappers to P02b-6 and replace -leftover P02b-4 worker/merge-pending pointers with the actual merge closeout. -Every prior dated phase delivery/review record and existing ADR remains -byte-preserved. Final checks pass: seven ADR parser controls, five Release -corpus tests with zero skips, 852 relative links/fragments, exact source-clause, -added prose-width and diff/whitespace checks. Runtime, database, realm issuance, -browser and hosted CI tests were not rerun for this seven-Markdown-file proposal. - -**Ready for maintainer approval; not Accepted.** The five implementation steps, -G10/G11/G12-client/G14/G20 and dependent runtime remain pending. Approval covers -ADR-0064, the exact disclosure/correction instruments and this implementation -plan together; it does not approve any P02b-6/7/8 gate implicitly. - -### Maintainer review follow-up (2026-10-19) - -**Changes requested; revised proposal remains Proposed.** Findings were treated -as review data and rechecked against `c94abe1b`, the actual resolver/factory, -recorder/reader, Accepted clauses and pinned upstream sources. No runtime test -or current-production exploit is inferred from a static contract gap. The earlier -rounds' no-actionable-finding opinions concerned their reviewed draft and were -not maintainer acceptance. Their original text is preserved; this dated follow-up -supersedes their readiness conclusion instead of silently editing the receipts. - -| Finding group | Verified disposition and revision | -|---|---| -| Platform-host absence401 vs row13 | Valid contradiction. Remove the absent-token401 permission; AccountSite absence gives masked404 on tenant/org/platform hosts. Name the scoped authorization result handler so `[Authorize]` cannot silently restore the default401. Generic unresolved MediatR behavior remains separate. | -| Future row14 and HostScope | Valid latent contract failure, hidden by today's deny-all membership. The exact query now refuses before readers unless HostAndClaim, valid actor and matching host provenance hold. Test active-membership ClaimAndMembership, missing/mismatched host scope and no reader call; do not wait for Phase03. | -| Resolver/header/membership error codes | Valid ambiguity. Rows8/11/12 and authenticated header mismatch use `tenant_mismatch`; rows7/10/14 membership refusal and anonymous header mismatch use `not_found`. HTTP uses shared Problem Details; pure factory Refused stays unchanged. | -| Missing recorder paths / row7 tense | Valid. Existing resolver writes no audit, so implement the already-required row7 audit rather than claim it is delivered. Extend source/actor/correlation/trusted-org attribution. Keep defended audit tenant nonnullable; add a synchronous source-aware no-tenant refusal method. Row7 one audit, row10 zero, row14 zero plus one unresolved count. | -| JOSE duplicate/extension policy | Valid gap in the selected profile. Require exact duplicate-free alg/typ/kid header, configured-issuer keys only, and reject every other parameter. RFC7515 does not itself require this exact allowlist or reject every duplicate; it is LearnStack's stricter proposed profile, not a claim that stock JwtBearer trusts token URLs. | -| Stock handler diagnostic leaks | Valid source-level gap. Failure events1/3 carry exceptions and inherited event7 logs failure text in the same concrete category. Warning-only filtering is insufficient because event3 is Error. Suppress raw category output at all levels and emit independent closed outcomes; qualify every enabled sink with negative canaries and positive diagnostics. | -| Claimless UserId / HostOnly | Documentation ambiguity valid; a current authority leak was not established. Factory preserves actor independently of HostOnly, and the ceiling already blocks non-public requests. Retain attribution, clarify origin/XML, prove public200/protected404. A new origin, null actor, metric or `lockey_tenant_claim_absent` is unnecessary; the diagnostic is one fixed Debug event without claim values. | -| Read-mode authority | Valid missing carrier. ADR0052 authorizes the public ordering departure on which ADR0040 Amendment8 relies. Acceptance therefore adds each ADR's own bounded scope-extension disclosure and reconciles Standards11's PublicSurface-only wording for this exact query; no Accepted body is rewritten and no general read-mode exception is created. | -| Query audit classification | ADR clarity gap; the package already prescribed Off. The ADR now explicitly names builder.Off, module audit documentation and zero normal query audit rows. No ReadSensitive/MAY classification or new operation slug. | -| Response/route/SDK contract | Valid implementation handoff gaps. Require explicit account/site route, outer no-store before early errors and exact disjoint public/authenticated generated GET ownership with exhaustive union. Public transport remains credential-free. | -| Status/instrument/revocation/attribution wording | Clarify Registered catalogue status, Accepted ADR bodies vs supersession, three dated disclosures, scope=platform restriction only within this tenant scheme, TTL/key withdrawal vs immediate revocation, tenant-wide audit column vs trusted-org metadata and captured correlation/source. Add missing module/standards/architecture references. | -| Earlier IdentityModel source wording | The round2 receipt called8.19.2 pinned. It was the inspected upstream tag and JwtBearer10.0.12 dependency floor, not an existing repository pin. Preserve the receipt with this correction; implementation resolves and qualifies the actual dependency graph. | -| Per-occurrence audit vs first disagreement | No behavior contradiction found: a rejected resolver short-circuits before assertions. Clarify separate requests remain separate occurrences with no coalescing or tenant ceiling. | - -The source check also found a failure-message log beyond the two cited JWT events: -`AuthenticationHandler.AuthenticateAsync` emits inherited event7 under the concrete -handler category. Its negative/positive controls are now part of Step1 alongside -stock events1/3. Pinned upstream and RFC references live in ADR0064; no transient -review input is a committed reference. - -Revision validation passes: seven ADR parser controls, five Release corpus -tests with zero skips, 857 relative links/fragments, prose/diff checks, and -byte-comparison of all pre-existing ADRs plus both earlier P5 review receipts. -Two new independent review rounds remain pending. No acceptance, runtime, realm, -migration, grant or authorization-domain change is made by this follow-up. - -### Revised proposal review round 1 (2026-10-19) - -Two fresh independent reviewers, both at xhigh effort, inspected -`c94abe1b..5e8539c9` against the actual code, Accepted clauses and pinned vendor -sources. Both found no verified actionable finding. One implementation detail -is now explicit: initialized Vogen identifiers can still contain nil UUIDs, so -the exact query mirrors the existing host guard's nonnil/nonsentinel checks as -well as profile validation. This does not introduce a new authority or origin. - -The contract review reran all seven ADR parser controls and whitespace checks; -the security review inspected sources and diff without rerunning runtime tests. -Neither review is maintainer acceptance or proof of the future implementation. -The second fresh independent revision review round remains pending. - -### Revised proposal review round 2 and readiness (2026-10-19) - -Two different fresh independent reviewers, both at xhigh effort, inspected -`c94abe1b..9ff8c8a3` within the complete seven-file proposal. Both found no -verified actionable finding. The security review checked the actual resolver, -factory, recorder and reader against the proposed JWT, diagnostic and admission -contracts. The contract review checked the exact Accepted source clauses, -separate disclosure/correction instruments, carrier ownership and five-step -activation boundary. Pinned upstream logging and JOSE sources were rechecked. - -Final documentation checks pass: seven ADR parser controls, five Release -`CorpusConsistencyTests` with zero skips, 857 relative links/fragments, exact -source-clause and added prose-width/diff checks. All pre-existing ADR documents, -earlier dated phase records and both original P5 decision-review receipts remain -byte-preserved. Only seven Markdown files differ from the entry baseline; -runtime, database, realm issuance, browser and hosted CI suites were not rerun. - -**Ready for renewed maintainer approval; not Accepted.** These four revision -reviews qualify the revised proposal for a decision, not its implementation. -ADR-0064, G10/G11/G12-client/G14/G20 and all five implementation steps remain -pending explicit approval together. No dependent runtime has started. Acceptance -first commits the three dated ADR disclosures, row-10 corrections and named -mutable carrier/catalogue reconciliation, then follows the per-step commit and -two-round review loop without further routine approval pauses. - -### Maintainer acceptance and implementation start (2026-10-19) - -The maintainer explicitly approved the revised ADR-0064 and five-step package -and requested implementation. This accepts G10/G11/G12-client/G14/G20 together; -realm/reconciliation, session/TTL and remaining phase-exit decisions are not -accepted implicitly. The two original and two revision review rounds remain -as-of receipts; this record closes their approval hold without rewriting them. - -The first commit records acceptance, ADR-0036's own bounded audit replacement, -additive attribution clarification and row-10 errata; ADR-0040 and ADR-0052 each -receive their own exact-query read-mode scope disclosure. Standards 04/10/11 and -the five new Registered catalogue obligations carry the accepted contract. -Registration is not implementation evidence. The existing authorization -behavior, database roles/grants, realm export and production HTTP composition -remain unchanged in this acceptance commit. - -Step 1 now implements the token foundation in isolated composition. Production -scheme/authorization registration and middleware activation both remain Step 4. -Every step retains commit, two fresh independent review rounds, verified fixes -and automatic progression. No further routine implementation approval is needed. - -Acceptance checks pass: seven ADR parser controls, five Release corpus tests -with zero skips, 1,788 relative targets/fragments (one existing illustrative -placeholder), prose/whitespace checks and insertion-only preservation in all -three previously Accepted ADRs. No runtime file changes in this first commit. - -### P02b-5 Step 1 — token foundation (2026-10-19) - -**Complete after both independent review rounds.** Acceptance was -committed first at `493d7f92`. The API now contains the closed options/profile, -immutable typed identity, request-local credential outcome and isolated stock -JwtBearer registration. `Program.cs` remains unchanged: no production scheme, -authorization registration, middleware or protected route activates in this step. - -The resolved graph uses JwtBearer 10.0.12 and IdentityModel 8.19.2. The latter is -the selected dependency version at this receipt, not a separate pre-existing pin. -Raw compact/header and post-signature payload checks reject duplicates, invalid -shapes, reserved IDs, wrong purpose/client/scope and malformed escaped Unicode. -The stock handler still owns cryptography, issuer/audience and key refresh. - -The owned backchannel refuses redirects and bounds each document to five seconds -and 256 KiB, including streamed multibyte bodies. Metadata HTTP instrumentation is -suppressed; unrelated outbound HTTP diagnostics remain observable. Last-known-good -reuse is disabled. The real rotation proof lowers only the stock manager's public -on-demand interval to its one-second minimum in isolated test composition; its -automatic interval remains five minutes and production on-demand remains 30 seconds. - -The production Serilog boundary excludes the exact raw JwtBearer category at all -levels, independently of the ILogger filter. Closed LearnStack outcomes replace -raw failures. Real loopback gRPC OTLP log/trace collection and the L1 capture path -prove privacy with allowed-log/error/HTTP-span positives. Natural initial metadata -failure is stock event 1; a documented test-only interface adapter delegates to -the same real manager/retriever to qualify stock event 3. Event 7 is independently -observed. No fabricated provider exception is called a natural metadata failure. - -The initial combined integration run exposed concurrent test hosts replacing -process-global Serilog/OTel state. A dedicated nonparallel diagnostics collection, -matching the existing public-log test ownership pattern, fixes the test isolation; -production behavior and every canary assertion remain unchanged. - -Validation passes: warnings-as-errors Release solution build; 2,471 unit, -209 Docker-free integration and four contract cases, all with zero skips. The -integration total includes 18 configuration cases, eight real-handler cases with -independent negative/positive matrices and six full diagnostic cases. The complete -architecture suite passes all 410 cases with zero skips; scoped format verification -and the acceptance-carrier link/prose checks also pass. No database/realm/frontend -runtime changes or Docker-suite evidence are claimed for this isolated token slice. -Catalogue obligations remain Registered until their complete active-path owners ship. - -#### Step 1 review round 1 (2026-10-19) - -Two fresh independent xhigh reviewers inspected `493d7f92..65263623` across -security, correctness, performance, ownership, diagnostics and test falsifiability. -They independently verified one shared finding: request-local instrumentation -suppression removes metadata HTTP spans, but native HTTP/DNS metrics still export -the destination hostname. Actual retriever-to-OTLP controls reproduced it. No -token or full-URL leak was established; neither review found another confirmed -defect in this isolated slice. Focused independent reruns pass 26 profile/config -and six diagnostic cases, all with zero skips. - -**Correction to the initial receipt:** its general metadata-instrumentation -suppression statement qualifies spans only. The initial full-URL canaries did -not detect destination-only metric tags. The verified correction projects native -HTTP/DNS metrics onto fixed non-destination dimensions and adds a distinct-host -canary plus exported metric positives. This projection applies to all outbound -metrics; unrelated traces/logs and metric counts, durations and status remain. -The new regression fails on the initial runtime and passes after the projection; -its unprojected SDK control still exports the private hostname. Actual metadata -GET and DNS duration positives are checked before unrelated traffic, and the -temporary test proxy override is restored under the nonparallel collection. -The correction passes a zero-warning Release solution build, all 2,471 unit and -210 Docker-free integration cases, plus 23 affected cross-cutting/corpus cases; -all have zero skips. Format, link/prose and whitespace checks pass. The earlier -complete 410-case architecture run remains the initial implementation receipt; -no complete rerun is claimed for this metric-only correction. The second fresh -independent review round is pending. - -#### Step 1 review round 2 and closeout (2026-10-19) - -Two different fresh independent xhigh reviewers inspected the complete -`493d7f92..c6108bf9` slice, including the round-1 correction and its documented -all-outbound metric dimension tradeoff. Neither found a verified actionable -finding. Each independently ran all 33 authentication integration cases in -Release, with zero failures or skips; whitespace checks also pass. These reviews -claim no Docker, real Keycloak, frontend or production-activation qualification. - -Step 1 is complete. The next step implements AccountSite's real application -contract, independent host guard, exact physical read-only selection, explicit -Off classification and application-role PostgreSQL proofs. Production scheme, -middleware and HTTP route activation remain Step 4. - -### P02b-5 Step 2 — real read-only application subject (2026-10-19) - -**Complete after both independent review rounds.** Entry is `e67c3299`. -Tenancy declares the unmarked `GetAccountSiteQuery` and typed `AccountSite` -projection. Its independent guard requires HostAndClaim, a real non-system actor, -real matching tenant/host provenance and coherent initialized organization IDs -before configuration, settings or feature access. Future ClaimAndMembership -contexts remain refused even with a planted matching HostScope. Refusals use the -shared `not_found` error. The validator admits no query parameters. - -The public and account handlers call the same internal projection directly; -neither nests another MediatR request. Public fields, lifecycle/locale semantics, -whole-theme/null behavior and attribution remain unchanged. The account query is -explicitly Off, with no query intent or audit row. Module documentation names -the unrouted boundary and adds no permission key. - -An immutable exact-Type declaration lives in SharedKernel beside transaction -mode. Tenancy's shared site-read registration supplies the sole AccountSite -literal; API and Seeder call it. The existing TransactionBehavior freezes the -Type set and retains the unchanged framework/public fallback. This placement -preserves module dependency rules without introducing a core-to-module edge or -a general mode selector. The shared registration also supplies Seeder's public -configuration reader. Existing physical mode/announcement ownership is unchanged. - -The existing module-independent transaction architecture rule now closes the -declaration, immutable snapshot, exact type lookup and registration callers. -An initial detector falsely classified the legitimate Enumerable projection as -registration; its correction permits only the exact projection and registration -signatures/owners, with duplicate/acquisition/substitution controls inside those -owners as well as outside them. No new architecture Fact or canonical rule is -invented, and implemented catalogue counts stay unchanged. - -Validation passes: zero-warning warnings-as-errors Release solution build; -2,521 unit cases, 210 Docker-free integration cases, 119 focused PostgreSQL -cases and 89 affected architecture cases, all with zero failures or skips. -The PostgreSQL set includes 14 new actual-account cases plus existing public -reads, transaction, provisioning and unit-of-work regression cases. Actual -`learnstack_app` checks prove non-superuser/non-BYPASSRLS execution, contrasting -stored tenant data, mapped-organization lifecycle, empty/disabled configuration, -foreign provenance refusal before reads, zero query audit delta, real SQL/EF -`25006` refusals with writable positive controls and writable-outer mixed-mode -refusal. Branding remains tenant-wide; no organization theme is fabricated. - -Scoped formatting, whitespace and carrier link/prose checks pass. Complete -backend/Docker/architecture unions and hosted qualification remain Step 5; -this receipt claims the named affected populations. No production HTTP route, -authentication activation, schema or grant change is introduced by Step 2. - -#### Step 2 independent review round 1 - -Two fresh xhigh reviewers independently inspected security/transaction behavior -and module/composition/census boundaries at `e67c3299..a736edbb`. Both approve -with zero verified code findings. Each independently reran 73 focused unit cases -and the extended transaction-composition architecture case; the security reviewer -also reran all 14 actual AccountSite PostgreSQL cases. All pass with zero skips. -The source review confirmed actual app-role SQL/EF refusals and writable controls, -future hostless-context refusal, audit Off and unchanged shared projection. -A stale Standards 11 implementation pointer is reconciled before round 2. - -#### Step 2 independent review round 2 and closeout - -Two different fresh xhigh reviewers independently rechecked security/correctness -and module/composition/census boundaries at `e67c3299..e36d47ca`. Both approve -with zero actionable findings. Each independently passed 73 focused unit cases -and the extended transaction-composition architecture case; the security reviewer -also passed all 14 real AccountSite PostgreSQL cases. Zero failures or skips. -They inspected current source and controls rather than treating round 1 as proof. -Neither repeated the complete solution or hosted suites; the implementation -validation above and final Step 5 obligations retain their stated scope. - -Implementation is `a736edbb`; `e36d47ca` reconciles the mutable standard and records -round 1. Both review rounds are complete. Step 3 now implements attributed -reconciliation, no-tenant diagnostics and subject admission. Production scheme, -ordered middleware and route activation remain Step 4. - -### P02b-5 Step 3 — attributed reconciliation and subject admission (2026-10-19) - -**Complete after both independent review rounds.** Entry is `8f9ecff2`. -Only the immutable validated identity supplies HTTP claim/actor signals. Raw -principals cannot establish tenant authority. The resolver still calls the pure -factory once and restores the prior accessor; no context is installed to attribute -a refusal. Rows 8/11/12 and authenticated header disagreements use the shared -`tenant_mismatch` Problem Details shape. Membership and anonymous refusals keep -masked `not_found`; malformed assertions retain their existing 400. - -The existing recorder now carries closed source, typed actor, captured request -correlation and trusted organization. JWT refusals defend the host tenant; -organization provenance stays in metadata while durable rows remain tenant-wide. -Row 7 writes one rejection, row 10 none. Row 14 synchronously counts/diagnoses -without a tenant/asserted-value field or store I/O. Existing operation keys, -anonymous burst accounting and failure-preserving Critical/health behavior remain. -Claimless identities keep their actor under HostOnly and emit one fixed Debug -event after subject admission; the account component refuses that ceiling. - -The additional singleton limiter keys only validated issuer/subject, with the -actual 600/min fixed window and no queue. Token/actor/tenant selection cannot -reset it. Retirement inspects at most 128 entries per callback and reclaims only -full-quota partitions idle for a whole window. Snapshot leases retain no child -ownership; sync/async shutdown closes admission and joins the timer before -remaining child disposal. Request-local outcome replay does not debit twice. -The earlier visitor/peer limits still apply to all credentials. - -Credential-result admission rejects present invalid credentials even for public -reads. The account surface component requires a validated actor and independent -host-backed authority; the application query retains its own guard. These -components remain isolated from Program: production authentication services, -middleware/authorization result handling and the route activate together in -Step 4. The exact production endpoint/dispatch census closes in Steps 4–5. - -Validation passes: zero-warning warnings-as-errors Release solution build; -2,536 unit cases, all 229 Docker-free integration cases, 31 focused PostgreSQL -cases and 55 affected architecture cases, with zero failures or skips. Nineteen -new component-chain cases use real signed tokens and the stock handler through -unchanged early admission, actual host classification, credential/subject gates, -resolver and assertions. Reduced subject budgets prove independence behind the -same peer, rotation resistance and stopping recorder work; separate default and -early-floor controls retain the actual limits. The six new PostgreSQL cases -exercise resolver-to-real-store rows/omissions and unavailable-store behavior; -three recorder cases prove captured fields and tenant-wide/foreign visibility. -Every database assertion runs as verified non-superuser/non-BYPASSRLS -`learnstack_app`; only fixture cleanup uses the administrator role. - -An initial harness correction enabled the exact Debug category and buffered -response JSON before repeated normalization. A stock limiter test now observes -actual full-quota idle state rather than treating TryReplenish's supported-mode -return as proof of replenishment. The corrected complete named populations pass. -Scoped formatting and carrier/whitespace checks pass. No production scheme, -HTTP route, realm, membership reader, schema or grant is activated by this slice. -Complete backend/Docker/architecture unions and hosted proof remain Step 5. - -#### Step 3 independent review round 1 - -Two fresh xhigh reviewers independently inspected `8f9ecff2..c0909708` across -quota concurrency/lifetime and reconciliation/recorder trust boundaries. Both -approve with zero actionable findings. The quota reviewer independently passed -10 limiter and 19 component HTTP cases; the reconciliation reviewer passed -39 focused unit, 19 component HTTP and nine app-role PostgreSQL cases. Zero -failures or skips. They checked current source and positive/negative controls, -including no-tenant omission, captured attribution and full-idle-only retirement. -Production activation and exact endpoint census remain the named later steps. - -#### Step 3 independent review round 2 and closeout - -Two different fresh xhigh reviewers independently inspected -`8f9ecff2..90724a54`. Both found no Blocker/Major or additional runtime defect; -both confirmed one Minor: the new actor log properties exported Vogen wrappers -instead of underlying UUIDs. Standards 02's emission rule applies. The recorder -now exports Guid/nullable Guid values, and captured-log tests require those -primitives; durable typed attribution and policy remain unchanged. Independent -reruns passed the named 10 limiter/19 component cases and 39 focused unit/19 -component/nine app-role PostgreSQL cases respectively, with zero skips. - -A narrow coverage suggestion was verified too: shortening only the stock -factory's default window escaped the original real-600 assertion. The shared -Window constant already had a literal-60 middleware control; that broader gap -was not present. The actual-default assertion now independently requires one -minute. A temporary one-second factory mutant passed the old assertion and failed -the strengthened assertion; production source was restored before final build. -This changes no production quota policy. - -After correction, the warnings-as-errors solution build passes with zero warnings -or errors, followed by 39 affected unit and 28 integration cases (19 component, -nine PostgreSQL), zero failures/skips. Scoped formatting, whitespace and carrier -checks pass. Implementation is `c0909708`; `90724a54` records round 1. Both review -rounds and verified corrections are complete. Step 4 now owns atomic production -activation, the real route, response policy and typed contract. - -### P02b-5 Step 4 — atomic HTTP activation and contracts (2026-10-19) - -**Complete after both independent review rounds.** Entry is `6686d018`. The -production root installs the strict scheme, authorization, -credential-result gate, subject quota and independent surface admission together. -Their explicit order retains earlier visitor/peer/body precedence, classifies -hosts before authentication and reconciles claims before header assertions. -The only new action is authorized `GET /api/v1/account/site`, dispatching the -already-qualified exact Off/ReadOnly query. A scoped authorization result handler -masks missing credentials without changing infrastructure/internal challenges. -The outer response owner reasserts no-store and removes validators on account -successes and early errors, including errors before tenant resolution. - -Development config supplies only its canonical loopback realm issuer. Every other -deployment mode requires explicit HTTPS configuration; startup validates its form -without connecting to the issuer. The local launcher carries an explicit issuer -only to the API child, rejects conflicting file/ambient configuration and keeps -it out of the public web environment. No realm export, mapper or client secret -changes in this step. - -The served OpenAPI document separates AccountSite bearer security from anonymous -operations, preserves the shared public projection and describes bounded refusal -headers/shapes. The SDK is regenerated from that actual document. Exact disjoint -public/authenticated GET ownership remains exhaustive; the authenticated package -exports a typed contract without adding session or bearer transport. P02b-7 owns -that transport. Production route/helper censuses and actual-host/PostgreSQL proofs -are part of this slice. - -Validation passes on the current Release binaries: warnings-as-errors solution -build with zero warnings/errors; 2,536 unit, five contract, 294 integration -(241 Docker-free plus 53 application-role PostgreSQL) and 96 affected architecture -cases, all with zero failures/skips. The PostgreSQL set includes the 20 real -AccountSite HTTP cases and two actual-chain quota cases. The full frontend lint, -typecheck and guarded workspace run pass 1,629 cases with zero skips/todos. The -snapshot is exported from the real production Program in its ordinary contract -fixture and compared with the served document; SDK generation uses that snapshot. -Scoped formatting, whitespace and carrier link/prose checks pass. - -The complete route detector and planted controls use actual production metadata; -its helper traversal distinguishes inherited base members from acquired abstract -services without losing concrete-service traversal. The older job-manifest route -multiset now names the one newly approved AccountSite GET; extra/dashboard routes -still fail. The order proof combines real-host precedence with reordered, missing -and duplicated registrations from actual Program source. Initial fixture-only -corrections retain lazy recorder construction and stock metadata refresh behavior. -No production fallback was weakened to satisfy a test. - -Complete backend/hosted unions and final catalogue promotion remain Step 5. -This receipt claims only the named local populations; both fresh independent -Step 4 review rounds remain pending. - -#### Step 4 independent review round 1 - -Two fresh independent xhigh reviewers inspected `6686d018..0be26abc` across -runtime security/isolation and contract/census/confinement, including correctness, -performance, ownership, refactoring and standards. Neither found a Blocker/Major; -both verified one Minor: actual AccountSite GET can return the early body-bound -`413 payload_too_large`, but the served contract and generated SDK omitted it. -The runtime itself already refuses before host/authentication work. Independent -reruns passed 52 architecture/contract/actual-host/configuration cases in one -review, and 113 HTTP/census/PostgreSQL/contract/SDK cases in the other, zero skips. - -The verified correction adds that response to account and public contracts using -the shared Problem Details/no-store owner; public HEAD remains bodyless. The -response census and missing-413 controls now require it. The strengthened census -first failed against the unchanged runtime, then passed after adding the response. -The snapshot is re-exported from the actual host and SDK regenerated, with an -explicit generated 413 type assertion. This changes no admission/runtime outcome. - -After correction, the warnings-as-errors Release solution build, five contract -and 34 actual-host/PostgreSQL/quota cases pass with zero warnings/failures/skips. -Frontend typecheck, SDK lint and the complete guarded 1,629-case suite pass with -zero skips/todos. Carrier and whitespace checks pass. The second fresh independent -review round remains pending. - -#### Step 4 independent review round 2 and closeout - -Two different fresh xhigh reviewers independently inspected the complete -`6686d018..746c0cd2` slice, including the round-1 correction. Neither found a -verified actionable finding. Their checks covered security/correctness, -performance, ownership, refactoring, complete route/helper/nested-dispatch census, -actual-host error precedence, API-only issuer configuration and public/authenticated -contracts. The security reviewer independently passed 34 HTTP/PostgreSQL/quota, -12 census and five contract cases. The quality reviewer independently passed -12 actual-host, 12 census, five contract, one production-manifest and 62 guarded -SDK cases plus SDK typecheck. All have zero failures/skips/todos. No actual -Keycloak, session, native Linux or full hosted qualification is inferred. - -Implementation is `0be26abc`; `746c0cd2` records the verified 413 correction and -round 1. Both independent review rounds and their verified correction are closed. -Step 4 is complete. Step 5 now owns the remaining authority census, final carrier -reconciliation and complete local/hosted packet qualification before PR handoff. - -### P02b-5 Step 5 — production enforcement and closeout (2026-10-19) - -> **Historical Step 5 entry.** The in-progress and pending receipts below precede -> the [local implementation/review closeout](#p02b-5-step-5--local-implementation-and-review-closeout-2026-10-19) -> and subsequent correction records. They are not current packet status. - -**In progress; no PR or hosted qualification is claimed.** Steps 1–4 and both -fresh independent review rounds per step are complete at `a7c9d5a3`. - -The final authority census loads every discovered production assembly and scans -actual IL, including generated state machines. Raw principal/claim/role reads, -role authorization metadata, extra typed-identity constructors, clones, mutations -and direct feature writes are refused. The existing factory/events and direct -actor/scope/subject accessor consumers form explicit nonempty caller sets. -Compiled dirty/clean probes, weakened raw-reader predicates and mutations of the -actual identity shape, factory call, same-owner write count and backing field -exercise the same detector. This is structural enforcement, not a general -reflection/taint-analysis claim. - -Architecture 09/14/28/33, Standards 02/05/09/20 and Phase 03/06/11 now describe -the implemented API boundary and each next consumer. The seven authentication -catalogue obligations have actual local test owners and are Implemented: 260 -architecture methods, 229 Implemented rules, 133 in that assembly and 96 elsewhere. -Runtime proof remains with the actual signed-token, physical ReadOnly, quota, -recorder, served-contract and SDK controls delivered in Steps 1–4. - -**Local validation at entry.** The warnings-as-errors Release solution build -passes. All 2,536 unit, five contract and 241 Docker-free HTTP cases pass with -zero failures/skips. Twenty focused Release authority/surface/corpus cases pass; -subsequent interface-access and typed-property negative controls pass eight -focused Debug authority/corpus cases with zero build warnings/errors or skips. -The complete Release architecture and ordinary PostgreSQL populations are still -running. One earlier job terminal-query plan assertion failed in the latter. -A disposable migrated-database experiment reproduced 12,000 obsolete bitmap -index entries after the guarded synthetic seed and zero after VACUUM, with the -same runtime SQL; bitmap forcing is confined to that diagnostic experiment. -The fixture now explicitly VACUUMs/analyzes before EXPLAIN. Normal production -planning, the clean `<256` visit bound and the volatile-cutoff dirty `>=6,000` -control remain unchanged. Its isolated original rerun passed; that rerun does -not close the failed complete run. Native Linux, -full hosted execution, both Step 5 review rounds and packet closeout remain -pending. No population, assertion, grant or production SQL is waived. - -#### Step 5 independent review round 1 and verified corrections - -Two fresh independent xhigh reviewers inspected `a7c9d5a3..d4639529` across -security/authority and corpus/test falsifiability. They verified two Major -structural-enforcement gaps, with no current production authority misuse: -interface `IAuthorizeData.Roles` assignment escaped the concrete-role predicate, -and generated-record `Deconstruct` exposed subject/scope without external getter -calls. Both used compiled probes against the actual detector and real production -graph; the interface metadata also produced a real framework role requirement. - -The root reproduced each independently with new compiled negative controls: -the unchanged scanner first failed the interface control; fixing that predicate -then exposed the deconstruction control as a second failing test. Interface -role getter/setter calls and identity deconstruction are now refused by the same -production detector. Existing clean, predicate-mutation, missing-subject, -factory, immutable-shape and same-owner additional-write controls remain. -The suggested extra-constructor concern was not a verified finding: an ordinary -additional constructor on this positional record delegates to the primary -constructor and adds an already rejected caller. - -Verified Minor corrections reconcile the catalogue's stale Registered/runtime -pending header and ADR-0064 derivations in Standards 02/05/09/20. README now -separates active API authentication from future browser sign-in and documents -mandatory issuer configuration without a startup network dependency. - -The complete Release architecture run also caught the older job-manifest census -still expecting only two public controllers. Its exact inventory now adds only -AccountController/GetSite, keeps every production controller/action in the scan -and plants an extra AccountSite action into the same detector. It does not add -an operator route or dashboard exception. Nine focused Debug authority/corpus/ -manifest cases pass, zero failures/skips. The maintained terminal-plan case also -passes separately in Debug with unchanged normal-planner and dirty/clean bounds. -Seven ADR parser controls and the carrier/whitespace checks pass. - -The original broad local architecture/PostgreSQL runs and the first hosted run -retain their actual results; focused correction proof is not a claim that those -runs passed. The complete hosted run is -[39318063296](https://github.com/HodeTech/LearnStack/actions/runs/39318063296) -at `d46395299f46428bc175b82745392505b1779a86`; it is still in progress at this -receipt. Both independent review opinions and verified corrections close round -1. Round 2 uses two different fresh reviewers on the corrected slice; complete -current-source hosted qualification and packet closeout remain pending. - -#### Step 5 independent review round 2 and verified corrections - -Two different fresh independent xhigh reviewers inspected -`a7c9d5a3..1942662d`. They verified three further Major structural-enforcement -gaps, with no current runtime authority misuse: generated record formatting -exports subject through object/generic APIs; IdentityModel token/payload APIs -escape a Claims/Principal-only predicate; and a derived authorization attribute -with Roles escapes both concrete-only metadata censuses. - -The root reproduced the vendor accessor and object-formatting failures in -sequence with compiled negative controls. A real compiled derived attribute and -its named Roles metadata then failed both authority and HTTP detectors when -planted on actual AccountController/GetSite. Synthetic test-helper loading errors -were corrected before those two red results; they are not counted as proof. - -The corrected detector closes identity/feature acquisition, holders, signature, -local, field, method and generic forwarding to the existing enumerated logical -owners. It covers object/generic formatting without pretending that the target -is an identity-declared method. Raw modern/legacy IdentityModel APIs are refused. -Authorization metadata follows the actual production inheritance/interface graph; -new custom authorization-data types cannot silently add another policy. Both -censuses use the compiled derived-attribute control and fail their weakened -concrete-only predicate. Typed actor use and the real unmodified graph remain -clean. This is a bounded static census, not general reflection/taint analysis. - -Verified Minor corrections remove the stale memberships-array risk from -Architecture 13 and replace Standards 11's obsolete missing-authentication -explanation with row 7's actual deny-all membership barrier, owned by Phase 03. -No production runtime, route, role, grant, retry or quota changes accompany these -corrections. Twelve focused cases pass in Debug and Release with zero failures/ -skips; the current Release architecture build has zero warnings/errors. -Both independent reviewers then reran their original bypass probes against the -corrected binaries: object/interpolated formatting, all four vendor-token probes -and derived role metadata are refused, while baseline/restored production graphs -remain clean. Their focused reruns pass three and twelve Debug cases respectively, -zero skips, and both approve the targeted corrections. Round 2 and its verified -corrections are closed; complete current-source hosted qualification remains -pending. - -**First complete hosted receipt.** -[39318063296](https://github.com/HodeTech/LearnStack/actions/runs/39318063296) -at `d46395299f46428bc175b82745392505b1779a86` is complete and failed honestly: -architecture shard 4 has 149 passes and one failure for the old two-controller -job-manifest inventory; the backend aggregate refuses it. The other five -architecture shards pass. All twelve ordinary shards, the 31-case native lane -and integration aggregate pass, with 2,486 exact Docker/native case results and -variant A retained. Native receipts confirm natural owned completion/cleanup and -zero refusals/skips. Base, frontend, OpenAPI comparison, meta and secret scan -pass. The public-demo receipt binds the same source and confirms nine URLs, -27 reports and completed process/Compose/private-file cleanup. The old local -complete architecture run likewise records 415 passes and that one failure out -of 416, zero skips. Neither failed run is relabelled green after its correction. - -The corrected `1942662d` hosted run -[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) -is still in progress at this receipt; the new round-2 controls require a later -source qualification too. No filtered subset, retry or skipped case substitutes -for final complete ownership and all seven required checks. - -### P02b-5 Step 5 — local implementation and review closeout (2026-10-19) - -Review vehicle: [PR #33](https://github.com/HodeTech/LearnStack/pull/33), -`development` into `main`. Its live checks and PR delivery receipt own final-head -CI status; this local receipt does not claim merge. - -**Locally complete; unmerged.** All five implementation steps and both fresh -independent review rounds per step are complete. The accepted decision precedes -runtime; the final implementation/correction head is `e20b6071`. Step 5's -`d4639529`, `1942662d` and `e20b6071` implement the census and record both -rounds with their verified corrections and independent targeted rechecks. -The earlier receipts retain their actual failed/pending state. - -The final warnings-as-errors Release solution build passes with zero warnings/ -errors. Twelve current Release authority/HTTP/corpus/manifest cases and the -current Release terminal-plan case pass, zero failures/skips. The complete local -base population passed 2,536 unit, five contract and 241 Docker-free HTTP cases. -The initial complete local architecture and ordinary populations report -415/416 and 2,454/2,455 respectively; each has the one explicitly corrected -census/fixture failure above, not a skip or hidden rerun. Corrected current -subjects pass independently and the complete hosted populations retain their -own source-bound receipts. - -The first complete hosted receipt above proves all 2,486 Docker/native cases, -frontend, OpenAPI, meta, secret scan and nine-page/27-report public demo, while -honestly failing the stale job-manifest census. The corrected -[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) -at `1942662df0e4321163f99b678805bec5a69c314a` is still running at this local -receipt. Later source changes only strengthen tests and reconcile documentation; -production/API/SDK/launcher/CI runtime files are unchanged from that source. -This is not a claim of complete final-head CI: the live PR checks must qualify -the final source with all seven required contexts, exact case unions, zero skips, -owned cleanup and the unchanged finite plan/budgets. PR CI status is recorded in -the PR delivery receipt before handoff; merge remains a maintainer action. - -The packet delivers only the API half: strict bearer validation, immutable typed -identity, attributed host/claim reconciliation, stable subject admission, the -physically read-only AccountSite query/route and generated authenticated contract. -Current realm imports do not issue this profile; no browser sign-in/session or -live membership/permission service is claimed. The next packet is **P02b-6**, whose -decision pass re-verifies G12's realm/reconciler boundary and G13's issuance TTL -authority before changing Keycloak or seed users. P02b-7 then owns BFF sessions -and bearer transport; P02b-8 owns remaining enforcement/erasure/phase-exit work. -No next packet starts in this closeout. - -### Work deliberately retained by its first consumer - -- **P02b-6:** real Keycloak issuance, fresh/warm realm reconciliation, user-profile - edit protection, actual seed identity/UUID agreement and issuance TTL. -- **P02b-7:** BFF code exchange, session custody/refresh/CSRF/logout, native auth - admission, guarded page and authenticated SDK bearer transport. -- **P02b-8:** LS0002, retained-store erasure inventory and final phase-exit census. -- **Phase 03:** users/memberships/permissions, durable subject-to-actor mapping, - tenant switching through new tokens, privileged and operator routes. -- **Phase 06 / 11:** full browser OIDC journey / production identity and distributed - infrastructure qualification respectively. - -These are the already staged first consumers, not cleanup debt from P02b-5. -The authenticated site endpoint grants no protected lesson/enrollment access. - - - -## P02b-5 external review remediation (2026-10-20) - -**Implementation and local proofs delivered on development.** The five original -implementation steps and both -review rounds per step remain completed historical deliveries. This follow-up -verifies later review claims against `afa84815`, corrects independently reproduced -issues under ADR-0064, and implements the separately Accepted ADR-0065 policy. -PR #33 remains unmerged. Temporary review inputs are not delivery authorities. - -### Decision boundary - -[ADR-0065](../decisions/0065-bounded-tenant-assertion-diagnostics.md) is **Accepted — -2026-10-20**. The maintainer authorizes acceptance after verified review corrections -and subsequent implementation without another approval gate. Acceptance and dated -ADR-0036/0064 disclosures precede dependent policy code. The scoped recorder now -consults a process-local singleton target-tenant allowance: 600 attempts per -monotonic minute, no independent tenant-registry cap, shared across actors. The -named MUST admission exception, suppression signals, unbounded warning cost and -native HTTP/DNS destination-dimension loss are explicit. Acceptance alone does -not claim the new runtime or proofs are delivered. - -### Verified corrections and dispositions - -Identifiers below preserve the review's finding identity, not its severity. -Reproduction and source determine each disposition; a suggestion is not presumed -to be a runtime defect. - -| Items | Disposition and evidence owner | -|---|---| -| B-1 | Strengthen the real-handler rotation proof: only a token request causes stock manager refresh, an issuer-owned response gate and actual update callback witness the update, and the subsequent rotated-token request must be 200. No test polling of `GetConfigurationAsync` can fetch the key. Stock background refresh may first return 401; that response is not counted as successful refresh. | -| B-2 | Correct the three structural endpoint censuses to follow actual stack arguments and reject computed/variable/decoy paths and alternate endpoint composition. Blinding the literal guard produces three expected red owners; restoring gives 13 green cases. The prior job manifest already had an exact runtime route union; new authenticated runtime cases strengthen it with all 15 endpoints and observed request dispatch in Development/Production. | -| B-3, M-10 | Enforce exact identity/feature members and full constructor/caller signatures, raw Tokens API reads, approved-owner generic/object exports and generic constraints, external authorization metadata resolution, and exact read-mode argument/branch/freeze flow. Extra owner overloads and malformed declarations no longer inherit authority by name. Planted controls independently fail. | -| M-1 | Mask only absent-identity challenges on the classified AccountSite surface. Forbid retains the stock 403. The Forbid and unrelated challenge controls use separate request scopes, matching the authentication handler's actual per-request ownership. | -| M-2, M-4, M-5 | Implemented under Accepted ADR-0065. A singleton shares 600 write attempts per defended tenant across scopes; failed writes consume allowance and suppression retains one Warning plus its own closed-label counter. No independent tenant-registry cap exists. Real OTLP controls distinguish destination-free metrics from preserved ordinary traces. Audit amplification and tenant-series growth are real Accepted-contract risks. Native destination loss is also real and process-wide, already implemented before this correction; it is not described as metadata-only or dependency attribution. | -| M-3 | Bound subject partitions to 4096. Refuse new keys before allocating a limiter; preserve existing spent quota and reclaim only fully idle partitions. A high-cardinality control proves cap refusal, no allocation/eviction and safe retirement reuse. | -| M-6 | Independently test actor, tenant, organization, origin and malformed identity/context refusals. Effective organization must equal the validated claim organization or host default; a context cannot invent an organization when both are absent. | -| M-7 | Validate discovery issuer equality without replacing the stock BaseConfigurationManager contract. Discovery/JWKS retrieval stays under the configured issuer origin and realm path. Disable trying all signing keys; signed unknown/withdrawn kid and wrong-discovery controls refuse. | -| M-8 | Reconcile live authentication, rows 7/10/14, deny-all membership and current implementation comments. The actual Keycloak export still lacks the approved issuance profile; P02b-6 owns its implementation and proof. | -| M-9 | The prior implementation receipt at `5676c754` remains historical. The doc-sync head `afa84815e0e9dfc3a215e8ebb38f8840e3ec2254` passed [39325575543](https://github.com/HodeTech/LearnStack/actions/runs/39325575543), and CodeRabbit passed. These observations do not qualify subsequent correction code. PR #33 owns the current head/check receipt. The earlier dated “still running” statement is retained as its as-of observation. | -| M-11, m-33 | Resolve issuer conflicts across `.env`, `.env.local` and ambient inputs only when the API launcher opts in. Projection-only values are accepted explicitly; web startup neither consumes nor gates on the API issuer. | -| m-1, m-2 | Document required 503 Retry-After and route-specific 405 Allow; extend served-contract deletion controls and regenerate snapshot/SDK together. | -| m-3, m-4 | Reconcile the SDK root's typed authenticated contract and nine-operation/five-GET contract inventory, preserving four public wrappers. | -| m-5 | No change: the generic settings accessor also serves writable commands and is not a public-site-only seam. The public projection first passes the physical read-only/provenance configuration reader; independently forbidding writable generic reads would break its intended owner. | -| m-6 | Recheck every resolved organization lifecycle in the public configuration reader, including claim-selected row 7 scope. Positive/restored and suspended/archived/deleted real-PostgreSQL controls distinguish it from the host-only check. | -| m-7, m-8 | Freeze declarations once in singleton ExplicitReadOnlyRequestCatalog and make the sole exact-type declaration registration idempotent. Actual repeated registration and cross-scope identity controls accompany the structural flow guard. | -| m-9 | No change: invalid optional theme already intentionally projects null; the generic setting reader returns a typed validation failure. A new warning is an optional diagnostic choice, not a changed successful-response contract. | -| m-10 | Document the existing Kestrel wire/framing backstop residual in 413 descriptions: server-level refusal can precede the application body/header policy. No all-wire Problem Details/no-store guarantee is invented. | -| m-11 | PublicResponsePolicy already uses the shared account path predicate; the OpenAPI transformer now uses the same live v1 constant. No v2 exists to qualify; a new major remains an explicit surface change. | -| m-12 | Suppress only the exact vendor ILogger category while preserving unrelated provider/category thresholds and rule order. Sibling-category positive and threshold controls prevent prefix suppression or accidental threshold widening. | -| m-13 | No change: explicit default-port text is deliberately noncanonical and rejected rather than silently normalized to a different configured issuer string. An explicit refusal case documents that existing policy. | -| m-14 | Refuse duplicate path slashes in issuer configuration; canonical transport remains strict. | -| m-15, m-17 | No speculative decompression, connection-pool or lock-sharding refactor. No correctness failure or measured contention was demonstrated. Finite I/O/document and subject registry bounds remain independently tested. | -| m-16 | Remove unused credential presence state. Preserve the already tested single closed authentication outcome; do not delete a distinct useful signal merely because a report calls it duplicate. | -| m-18 | No change: typed assertion headers intentionally retain Guid.TryParse compatibility. They never select scope and their accepted spelling is not the stricter token identity grammar. | -| m-19 | No new metric: row 10 already emits the fixed resolver refusal diagnostic and deliberately writes no audit row. A new membership-dimension instrument would be an additional observability contract. | -| m-20, m-21 | Define claimless principal, AccountSite and assertion source; narrow audit-matrix per-occurrence wording to a defended host tenant and explicitly exclude row 14. | -| m-22 | No Accepted body rewrite: the relationship table already names the two read-mode scope extensions and the row-14 audit replacement separately. The broad status summary does not replace those exact instruments. | -| m-23 | Refuse no-tenant signal calls outside the fixed jwt-claim/Tenant pair before emitting a label. | -| m-24, m-25 | Refuse nil/sentinel defended audit tenants before signal/store work; standalone store backstops also reject unassigned ids. Unassigned trusted organization becomes null metadata, never a dereference. | -| m-26, m-27 | Validate every supplied typed identifier and principal coherence before no-tenant shortcut/context construction. Factory positive rows remain; malformed values cannot mint a partially trustworthy context. | -| m-28 | Extend the account path fallback across methods while preserving actual matched-action admission and the existing valid-credential 405 controls. No additional routed method is introduced. | -| m-29 | Derive the immutable projection from the cryptographically validated security token, never a second read of a potentially changed Authorization header. | -| m-30 | Positive pure-factory rows 7/10/14 already existed. Keep them; add claim-selected organization lifecycle controls rather than inventing a second live membership implementation before Phase 03. | -| m-31 | Strengthen actual unsigned/public-route invalid-profile and precise projection-clock skew controls, plus Forbid and app-role assertion. Existing actual 600/whole-chain reduced-budget, anonymous warning and no-credential/no-audit evidence remains; do not relabel a reduced-budget test as end-to-end 600 throughput. | -| m-32 | Dispose unit-owned metric providers; isolate real database cleanup/reads by fixture correlation. The diagnostic collector's AllPayloads already includes Metrics, so an alleged missing full metric canary sweep is not reproduced. | -| m-34 | Recheck normalized URL pathname and reject any normalization change before adding private public-hop headers. A substituted SDK transport control rejects dot segments, encoded traversal, fragments and foreign origins, with a real positive public request. | -| m-35, m-36 | Require kid-selected trusted keys and reject whitespace-only opaque subject/kid values; explicit signed negative controls accompany them. | -| m-37 | No duplicate handler validation: the real GetAccountSiteQueryValidator rejects HasUnexpectedQuery at canonical pipeline step 2 before any reader. Directly calling a handler outside its owner does not establish an HTTP bypass. | -| m-38 | JWKS documents cannot redirect trust to another origin/realm path. Do not ban private IdP networks: SaaS, Dedicated and Self-Hosted can legitimately configure private identity providers. An operator allowlist/DNS-rebinding policy would be a separate deployment decision. | - -### Correction validation - -Runtime corrections are committed as `8a3892d9`, following acceptance commit -`d335f2bf`. Local qualification covers the working tree committed there; formatting -changes no behavior. Release solution compilation with warnings as errors passes. -The completed local populations are: - -| Population | Passed | Failed / skipped | -|---|---:|---:| -| Full Unit | 2,581 | 0 / 0 | -| Changed authentication, endpoint, tenancy, read-mode and corpus Architecture owners | 80 | 0 / 0 | -| Full Integration `Requires!=Docker` | 257 | 0 / 0 | -| Focused real PostgreSQL AccountSite, read-only, assertion/audit and invalid-store-target owners | 58 | 0 / 0 | -| Full Contract | 5 | 0 / 0 | -| Full frontend (web + SDK) | 1,630 | 0 skips / todos | - -Frontend lint and typecheck pass. Seven ADR-parser controls pass. Changed-doc -relative files and fragments are checked independently. The structural controls -also retain the real same-subject dirty/clean evidence: blinding the endpoint -literal guard gives three failing owners; the original independent opaque-object -export repro now gives one offender while its clean control gives none. A -scoped audit-budget mutation fails both actual DI identity and 601-scope -pre-I/O accounting proofs. More than 4096 live host tenants remain independent. - -The expanded run found a missing budget registration in the deliberately minimal -reconciliation test host; its singleton is now installed and all 58 PostgreSQL -cases pass. It also reproduced an OTLP test-lifetime race: the real suppression -Warning was emitted, but the host exited before the asynchronous log batch was -observed. The test now awaits the actual correlated export within eight seconds -while its owner is alive. Counter/label/no-I/O assertions are unchanged; the full -257-case non-Docker population passes after that correction. - -An accidentally broad local Integration selection was cancelled and is excluded -from receipts; its processes and Testcontainers exited. The correct Docker -exclusion is `Requires!=Docker`. An expensive full local Architecture run was -also stopped without a complete receipt. Neither is described as a passing -population. Complete Architecture, ordinary Docker and native populations remain -mandatory in the unchanged CI shards, with exact union verification by both -aggregates. The source-bound current head/check receipt belongs to -[PR #33](https://github.com/HodeTech/LearnStack/pull/33); earlier successful runs -are historical and do not qualify the correction head. - -### Independent correction reviews - -The first fresh security/proof review (GPT-6-astra, xhigh) reproduced an opaque -object-helper/storage escape in the authority census. The fresh quality review -(GPT-6.1-sol, xhigh) found the demo launcher's missing API-authentication opt-in. -Both were verified and fixed; the independent original opaque-export probe now -fails on the same dirty subject. A subsequent fresh security and quality pair -(the same model families, xhigh) reviewed the complete corrected working tree, -including ADR-0065, and found no additional actionable defect. That pair was -read-only and did not supply execution evidence. - -The final fresh pair (GPT-6-astra xhigh for runtime/security and GPT-6.1-sol xhigh -for proofs/contracts) independently reviews frozen code commit `8a3892d9`. Both -approve their assigned scopes with no additional actionable finding. They are -read-only source/test inspections, not test-execution or full-CI receipts. -That review covers the frozen runtime source. The subsequent demo-only follow-up -below has its own review and hosted qualification. -This follow-up starts no next packet and makes no claim that PR #33 is merged. - -### Hosted correction qualification follow-up - -The first correction-head run, -[39337392103](https://github.com/HodeTech/LearnStack/actions/runs/39337392103), -checks out merge `bc79e01f` for head `ac82ca6b`; its tree equals that head's tree. -Both source/attempt-bound aggregates pass: 3,276 backend cases plus 2,491 -integration cases, **5,767 total**, with exact complete unions and no failed or -skipped cases. Independently downloading all twenty producer artifacts and -re-running both receipt/hash/result/union validators confirms all 5,767 completed -cases are Passed: 2,581 Unit, 433 Architecture, five Contract and 2,748 Integration -(including 257 non-Docker, 2,460 ordinary Docker and 31 native cases). The frontend -passes 1,630 cases. Twenty-six of 27 jobs pass; -`public demo + lighthouse` is the sole failed job, so this is not a green PR-head -receipt. - -The demo completes browser controls and its first audit, whose LCP, blocking time, -layout shift and accessibility satisfy the existing budgets. It refuses roughly -280 milliseconds after announcing the second audit, before that audit makes any -product API call. Owned cleanup passes. The retained artifacts do not identify -whether browser launch, the debugging-port file or another early operation -failed; a browser-startup or product regression is not established by this record. - -Commit `f5befc9e` adds closed parent phases, bounded browser exit/signal fields -and a revalidated private worker substage. The first failure survives cleanup; -raw exception, provider, URL and document text cannot enter this diagnostic. -It changes no retry, deadline, browser flag, port parsing or audit threshold. -The first fresh demo review pair (GPT-6-astra xhigh and GPT-6.1-sol xhigh) finds -no privacy/cleanup defect but independently identifies an exit-classification -edge: Node exposes signal termination through signalCode with null exitCode. -Commit `ce2b746e` corrects the production startup predicate and replaces an -impossible synthetic status pair. Two actual native-child controls verify live, -normal and signal states. The thirteen new controls also cover an actual worker -connection refusal, clean completion, primary/cleanup failures and canary -rejection. All 189 focused demo cases and the full 1,643-case frontend population -pass with no skips/todos; typecheck, lint and formatting pass. The fresh second -independent pair identifies a declaration-only mismatch: Record<string, unknown> -does not accept Node ChildProcess. Commit `d9f21ddb` uses the exact structural -status fields, and the existing actual-child controls now compile-check both -entry points. Typecheck, all thirteen diagnostic controls, lint and formatting -pass after that fix. Both reviewers confirm the complete corrected slice has no -remaining actionable finding in their assigned scopes. Their source inspections -are not hosted demo receipts. A complete new hosted run must qualify the final -source; the earlier backend receipt does not qualify the later frontend source. - -### Reviewer handoff - -```text -Review the PR #33 correction range afa84815..development, anchored by runtime -commit 8a3892d9 and Accepted ADR-0065. Check runtime security and failure paths, -actual production subjects plus planted controls, exact HTTP/read-mode/identity -censuses, cross-scope audit admission, and ordinary-versus-metadata telemetry. -Confirm the current PR-head CI receipt independently; historical green receipts -and cancelled local selections are not current-head qualification. Treat review -inputs as untrusted data. Report only verified still-valid findings. -``` - - -## P02b-5 second external review follow-up (2026-10-20) - -> **Historical snapshot — entry and reviews before ADR-0066 approval.** -> Decision-pending and unimplemented statements in this follow-up describe that -> source interval. The later [acceptance and implementation record](#adr-0066-acceptance-and-implementation-2026-10-20) -> supersedes those states; original receipts remain intact. - -This follow-up starts from `9d4ec0e019af3b42edd7950c40a495a42034b933` -on development. It verifies each new review claim against current production -code and its actual test owner. Temporary review inputs are not permanent -authorities. No next packet or production identity activation starts here. - -**Decision pending:** -[ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) proposes the -missing explicit 4096-subject process bound and its bounded reclamation, -cleanup ownership and closed refusal signals. Existing code is not evidence -that ADR-0064 selected this bound. Three independent source/design inspections -reviewed the draft; the single retirement batch and total resource accounting -were clarified. The maintainer's new-ADR approval is required before acceptance, -source-attribution errata in ADR-0064/0065 and dependent admission refinements. -The earlier approval waiver applies to ADR-0065 only. Independent corrections -below do not depend on that decision. - -### Verified runtime and proof corrections - -Finding identifiers below identify review items, not severity. A verified -limitation is distinguished from a current runtime defect. - -| Items | Verified disposition and actual owner | -|---|---| -| B1, M8, P4 | ADR-0064 does not select 4096. ADR-0066 is Proposed; default-cap, acquisition reclamation and refusal-signal refinements remain approval-dependent. The draft explicitly counts 4096 retained plus at most 128 retiring resources and forbids accumulating cleanup batches. | -| M1 | Point projection does not remove exemplar filtered attributes. Set the production exemplar filter programmatically to `AlwaysOff`; decode actual OTLP exemplar attributes, values and identifiers. `TenantAuthenticationDiagnosticsTests.Metrics` has unprojected positives and production negatives for standard and histogram-specific `always_on`/`trace_based` settings. ADR-0065 Amendment 1 clarifies enforcement of its existing privacy contract. | -| M2 | Preserve the worker's closed exit/signal status through `DemoCommandError` and use it only for worker stages. Browser status belongs only to browser stages. Real nonzero and signal-terminated child controls replace the impossible worker/browser attribution. Unsupported signals stay null under the closed diagnostic vocabulary. | -| M3, M7 | Extend `AuthenticatedHttpSurfaceTests` across direct interface/concrete handler references in constructors, fields, locals and `Handle` calls. Each dirty route/capability control requires its expected offender prefix. Compiler-generated self-capture has a narrow clean control. | -| M4 | Derive recorder counter vocabulary from actual constant declarations and `Meter.CreateCounter` calls. Scan compiled strings and constant fields across production assemblies, including public-constant references, a differently prefixed fourth counter, both audit slugs and case-insensitive assertion headers. Exemptions name actual assembly/type owners. | -| M5 | Plant exact base `AuthorizeAttribute.Roles` separately from derived metadata; removing the named Roles branch must lose that control. Add raw authenticate-result/ticket principal and `IAuthorizationService.AuthorizeAsync` sinks to the authority census. | -| M6 | Add signed claimless platform-host row 15 to `TenantAuthenticationReconciliationTests`, including masked refusal and exactly one fixed claimless Debug event. Component-only evidence is not relabelled HTTP evidence. | -| D1, D2 | Add missing own-amendment navigation and correct current CI ownership in the decision index. Roadmap/root README distinguish completed P02b-0 entry verification from merged P02b-1–4. | -| D3 | Already closed by the baseline docs-only commit `9d4ec0e0`; do not reapply or treat its stale pending text as a current defect. | -| 9.1 containment | Reject encoded slash/backslash/dot traversal in configured issuer and discovery/JWKS paths; compare real URI segments as well as exact origin. Preserve legitimate private IdP origins and harmless escaped path data. | -| 9.1 organization liveness | No missing lifecycle gate reproduced. Every public Education query first calls the same public configuration reader. Extend the real claim-selected organization lifecycle proof through public site and course-list queries: active succeeds, inactive refuses, restored succeeds. No second lifecycle policy or new ADR is introduced. | -| 9.1, 9.2 HTTP/contract | Preserve absent-credential AccountSite masking before method admission and signed unsupported-method 405. Assert actual `Allow`, early-error no-store, both-route application 413 and optional 413 cache header in OpenAPI. Clarify public site 400 assertion errors; reject explicit `additionalProperties: true`/schema changes. Exact CLR fields and schema property/required censuses own the representation boundary; an omitted keyword does not reject unknown fields in JSON Schema. Served OpenAPI, snapshot and generated SDK agree. Future 403 belongs to Phase 03's real permission boundary. | -| 9.2 persistence | Three direct real-reader controls reject unannounced/no-EF-transaction/mismatched-EF-transaction ownership. Successful same-role, same-context controls establish that refusal is the ownership guard, rather than missing data or an inaccessible database. | -| 9.3 census | Follow reachable pipeline helpers and reject hidden/duplicate controller mapping and static health field reads. Source/IL controls exercise the production subjects, not only arrays of expected names. | -| 9.3 logging/profile | Remove ineffective `LoggerFilterOptions.PostConfigure` under the production Serilog factory; retain the registration needed by isolated hosts. Assert the actual factory, exact vendor-category suppression at every level and observable siblings. Add unequal duplicate properties and configured-issuer/console/malformed-payload canaries. | -| 9.3 startup/cache | Actual Production `Program` must refuse missing/empty issuer before dependency startup. Separately prove a warm current known key can still validate when a requested refresh fails: disabling Last Known Good fallback does not discard the manager's current cached configuration. Cold/no-usable-key refusal and observed key withdrawal retain their controls. | -| 9.3 test determinism/composition | Freeze only visitor replenishment for the real HTTP 60-permit proof and assert the unmodified default factory's 60/minute automatic configuration separately; do not claim the HTTP case proves real timer renewal. Successful real AccountSite reads also inspect actual runtime `IAuditCatalog` Off registration, rather than relying solely on assembly-wide discovery. | -| 9.4 demo lifecycle | Establish the receipt before setup, record setup failure without overwriting foreign output, set worker preflight before toolchain access, emit only validated closed status lines from chunks and preserve the primary failure if receipt saving fails. Outer process ownership drains Chromium; an extra unbounded `browser.exit` wait is removed. Signal expectations are platform-aware with no skipped tests. | -| 9.5 SDK/frontend | Use the actual asynchronous SDK and a fetch stub in path-fence controls. Admit only the four public operation templates and reject encoded separators/traversal. Freeze maps, enforce exact wrapper pairing/root exports, remove the undefined AccountSite query alias and add a compiler deletion control for GET ownership. Empty issuer is omitted by the launcher. | - -### Production activation ownership and unchanged contracts - -The issuer must be resolvable and reachable from the API using its configured -canonical origin; startup is deliberately not a network-readiness check. -Private/split-horizon DNS is supported only if it preserves that exact issuer. -No separate metadata-origin setting or weaker JWKS containment is introduced. -[API Gateway](../architecture/30-api-gateway.md#current-issuer-topology-and-activation-limits) -records cold/warm cache behavior, manual versus automatic refresh proof limits, -coarse Information outcomes, early correlation limits and row 10's Debug-only -visibility. An event-3 adapter injection is not a natural stock-handler receipt. - -[Phase 11's activation gate](phase-11-production-hardening.md#tenant-authentication-production-activation) -owns issuer/readiness, closed authentication failure signals, row-10 operational -visibility, capacity sizing, key-rotation drills and suppression alert/runbook -qualification **before production exposure**. Audit suppression is intentional -admission and can coexist with Healthy audit-store health. Counter and 4006 -tenant/actor/correlation triage do not restore lost durable rows. Existing -Information and assertion Warning volume remains a stated cost; this follow-up -does not silently sample accepted diagnostics or invent new failure taxonomy. - -[Phase 03](phase-03-identity-admin.md) must decide and install runtime -deny-by-default admission before its first permission-sensitive endpoint, -with a denied-dispatch control and public/nonsensitive positives. Today's static -route census remains a complementary guard. No unused fallback policy is -installed in P02b-5. Real issuance remains P02b-6; BFF custody and recovery remain -P02b-7. These are explicit activation conditions, not claims of production fit. - -No speculative change is made for the following suggestions: - -- The read-only composition deliberately permits one exact declaration today; - its census rejects a second. Adding another request must change registration - and its exact-type guard together. No current declaration silently falls back - to ReadWrite. -- AccountSite has only the authorized v1 route. A v2 route requires its own - explicit contract/no-store/admission controls; no unrequested path abstraction - or response-policy rename is introduced. -- Authentication registration is a bootstrap-once graph. Repeat-registration - idempotence is not promised; silently ignoring conflicting settings would not - improve its fail-closed behavior. -- ADR-0064's exact relationship table and the own dated ADR-0040/0052 - disclosures distinguish read-only scope extensions from row 14's audit - replacement. Preserve those instruments and the Accepted body; its broad - status summary is not a new independent read-mode authorization. -- The validated unexpected-query flag follows the existing public application - contract; it carries no `HttpContext` and changes no scope. Moving it would - change validation precedence without fixing a reproduced bypass. -- Public-client TLS/configuration splitting or caching has no demonstrated - correctness failure or measured cost here. Keep private configuration strict. -- Account HTTP Debug settings are child-host configuration, not a shared test - logger-level switch. The host owns/disposes its logger and the database - collection is serialized. No cross-test mutation was reproduced; retain the - claimless-event proof without adding a second logging path. -- Actual component 600 and reduced-budget whole-chain proofs retain their - separate meanings; neither promises end-to-end 600 throughput through the - earlier visitor/peer limits. Timer retirement injection likewise does not - control the stock limiter's replenishment clock. -- Existing demo corrections stay in this PR because they qualify this packet's - required browser check. Splitting already dependent fixes into another PR - would leave this source unqualified; no thresholds or budgets are relaxed. - -### Historical evidence reconciliation - -The Step 5 **In progress** paragraph and its later local closeout are dated -snapshots, superseded by subsequent implementation/remediation records. Their -claim that later changes only affected tests/docs is scoped to the original -`1942662d..e20b6071` closeout; runtime changes in `8a3892d9` belong to the later -remediation and are not covered by that sentence. The original no-tenant-cap/ -unconditional per-occurrence text describes the pre-ADR-0065 contract; admitted -per-occurrence recording and the aggregate allowance are current. - -Independent Actions readback on 2026-10-20 confirms historical run -[39319162537](https://github.com/HodeTech/LearnStack/actions/runs/39319162537) -completed 27/27 jobs successfully at -`1942662df0e4321163f99b678805bec5a69c314a`. It was genuinely pending when the -earlier receipt was written. Baseline run -[39346971253](https://github.com/HodeTech/LearnStack/actions/runs/39346971253) -also completes 27/27 jobs at `9d4ec0e0`. Neither qualifies the new changes. - -The earlier demo's roughly 280 ms description is an unexported local timing -estimate, not a retained-artifact witness. The retained job's roughly 13.7 s -interval includes cleanup; the numbers cannot be interchanged. The supported -claim is narrower: the second audit was announced, made no product API call, -and then refused; cleanup completed. The failing operation/root cause remains -unidentified. The later successful source has its own receipt. - -The retained P02b-4 portable evidence archive was independently read again: -40,974,306 bytes, SHA-256 -`028de8d8d2bc6584a90e84f16755187cd2c32d600c2e80d98ad3ea19e18ce98d`, containing -44 ZIP artifacts. This checks retained archive integrity/inventory; it does not -rerun those historical tests or reauthenticate its saved API response. The -earlier 1,002-link figure remains a local as-of document check, not a current -repository link census. Current changed-document links require their own check. - -Historical model names and opinions record review-tool provenance and assigned -scope, not reproducible repository test artifacts. The prior correction record -anchors frozen source `8a3892d9`; its read-only inspections are explicitly -distinct from executable test/CI receipts. New independent review rounds and -validation below must name their own source and evidence. PR #33's body must -follow the final submitted head, rather than borrowing a historical green run. - -### Local correction validation - -The following focused populations pass with zero failures/skips. These are -separate selections with overlapping owners, not a summed complete-suite count: - -- 49 Architecture authority/surface/tenancy/composition cases, Release. -- 33 reconciliation/pipeline Integration cases, including signed row 15. -- 59 privacy/configuration/profile cases; three additional actual startup/warm - cache cases pass after correcting the fixture's bootstrap configuration. -- 73 real PostgreSQL HTTP/reader/lifecycle cases; three final runtime-catalogue/ - deterministic-ingress cases pass after their proof corrections. -- Five served/snapshot Contract cases; generated SDK equality and typecheck. -- Full frontend: 1,656 cases (1,591 web and 65 SDK), zero skips/todos; lint and - typecheck pass. Six setup-path controls pass again after platform normalization. - -Seven ADR-parser controls pass. ADR-0065 remains Accepted; ADR-0066 parses -Proposed. Formatting and diff whitespace checks pass. At `15c2f49d`, changed-doc -link verification checks 1,934 real relative links/fragments; the catalogue's -pre-existing inline `name_lowercased` template example is not a real target. -The following review records govern correction closure; neither focused passes -nor previous hosted receipts complete current-source hosted qualification. - -### Second follow-up independent review round 1 - -Frozen correction commit `15c2f49d` receives three fresh read-only reviews: -security/runtime, frontend/contracts/docs and production proofs. The first two -find no additional actionable issue in their assigned scopes. The proof review -finds two verified gaps: counter/header checks still pass only the API module to -their otherwise broad scanner, and `Use*` names stop source helper expansion -before its body can reveal another middleware. These are proof defects, not -observed production bypasses. Both require correction and actual dirty controls -before round 2; a review opinion alone does not establish their closure. - -The verified fixes now scan every production module for counters/headers, with -compiled controls in both API and Tenancy.Application. Custom source helpers -resolve before framework terminals; existing middleware wrappers must preserve -their actual leaf shape, and the OpenAPI wrapper must add no middleware. -Immutable direct/receiver-alias extra-authentication mutations inside both real -resolution and OpenAPI helpers fail. Clean data-free and `Use`-prefixed helpers -remain distinguishable. All 16 Tenancy convention cases and the actual HTTP -pipeline owner pass again in warnings-as-errors Release, zero failures/skips. - -Broader local validation on the frozen `15c2f49d` source passes: full Unit -2,581; full non-Docker Integration 276; full Contract five; selected authority, -surface, tenancy, public, corpus and persistence Architecture 80. All have zero -failures/skips. The complete Release solution builds with warnings as errors, -zero warnings/errors. This receipt precedes the two review corrections; their -changed owners need their own rerun. Complete Architecture/Docker/native and -public-demo qualification still belongs to current-source hosted CI. - -### Second follow-up independent review round 2 - -Three new reviewers inspect frozen fix commit `653404ad` against `9d4ec0e0`, -covering security/runtime, frontend/contracts/docs and production proofs. -Security and frontend/docs find no additional actionable issue. The proof -review confirms the round-1 corrections and finds a fluent receiver gap: -`return app.UseMiddleware<TenantResolverMiddleware>().UseAuthentication()` -silently skipped its outer call while preserving the expected inner leaf. - -The verified correction refuses fluent application receivers, including -framework builder returns and source-declared builder-returning helpers. -Parenthesized/cast receivers and builder-valued aliases cannot evade this -specific predicate. Immutable mutations of both the actual Program statement -and actual resolver return statement require the precise fluent/leaf-shape -diagnostic. The actual HTTP pipeline owner passes again in warnings-as-errors -Release, one passed, zero failures/skips. Existing health endpoint naming stays -clean: its endpoint-convention builder is not an application-builder receiver. -This remains a bounded source proof, complemented by actual HTTP/IL censuses; -it is not a universal C# analyzer. Targeted independent fix verification and -the final submitted-head CI receipt are required before handoff. - -Commit `8f2ebb92` records that verified correction. The independent round-2 -proof reviewer re-inspects the committed delta and approves closure with no -remaining actionable issue in its target scope. Both fresh review rounds and -their verified fixes/rechecks are complete for these independent corrections; -all reviews are read-only source inspections, distinct from executed tests. - -The final PR-head/Actions receipt belongs to -[PR #33](https://github.com/HodeTech/LearnStack/pull/33), whose body is updated to -the submitted head and actual run. Historical green runs cannot qualify it. -The correction source is ready for complete hosted qualification; this does -not mark the overall review finished or authorize merge. ADR-0066, B1/M8 and -its dependent subject-admission refinements remain explicitly approval-pending. -No fresh decision is accepted by elapsed time or by a green test run. - -### ADR-0066 maintainer review revision (2026-10-20) - -> **Historical proposal revision.** Proposed/pending statements below apply -> before the subsequent [maintainer acceptance](#adr-0066-acceptance-and-implementation-2026-10-20), -> not to the current implementation. - -The maintainer requests revision, not acceptance. This pass starts from -`09e1a169dd61e02633860d03ad68052d1e86dfa8` on development and verifies the -findings against the current limiter, middleware and real test owners. -[ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) stays Proposed; -no dependent runtime, Accepted-ADR erratum or acceptance is implemented here. -The earlier ADR-0065 approval waiver does not authorize this decision. - -The three high findings are valid: the draft conflates permanent cleanup fault -with ordinary capacity pressure, leaves acquiring allocation/debit ordering -ambiguous, and omits the blocking cost of acquisition/shutdown disposal. -Two independent read-only design/corpus inspections confirm these gaps; they -are not runtime tests or qualification of the proposed implementation. - -| Finding | Verified revision / disposition | -|---|---| -| 1 — Fault visibility | Propose rejection reasons `quota`, `registry_capacity`, `registry_fault`; add an unlabelled once-per-instance cleanup-fault transition counter so timer faults are visible without a request. Phase 11 owns three-branch alert/runbook qualification. | -| 2 — Allocation/debit ordering | Acquisition removes at most one eligible entry, completes its disposal and rechecks state before its own allocation/debit. Failure produces no owning debit or dispatch. Other requests can use free slots before fault publication; after publication no new allocation starts. Existing retained keys keep quota service. Lost-slot and same-key races need explicit controls. | -| 3 — Blocking cost | Acquisition inspects at most 128 entries but disposes at most one. Timer batches remain at most 128 under the same sole retirement owner. Other requests never wait for cleanup; a full registry refuses immediately. One disposal can still block the owning request and joined shutdown indefinitely. Host grace expiry is not cleanup evidence; no fatal/restart owner is added. | -| 4 — Reason transport | A closed result carries acquired/quota/capacity/fault plus detached retry metadata from limiter to middleware. Cache the first request result and emit a rejection exactly once; admission emits none. | -| 5 — Active mutable carriers | Security Standards and Identity architecture now identify 4096 as current code under a Proposed decision, not a bound selected by ADR-0064. Derivation headers and Accepted-ADR attribution errata remain acceptance work. | -| 6 — HTTP choice | Ordinary quota/capacity remain admission 429. Sticky cleanup fault proposes dependency 503, standard `dependency_unavailable` and the existing 30-second hint. Middleware must apply the common helper explicitly; outer bodyless-status handling alone does not. Compare the idempotency-store 503 precedent without changing it. | -| 7 — Fair share | Add a separate tenant/host reservation alternative. Reject it for this packet because inventory, claimless attribution and measured share policy are absent; it is not equivalent to tenant-partitioning the quota key. Phase 11 owns comparison before changing the bound/policy. | -| 8 — Proof ownership | Name the real unit and HTTP owners plus actual OTLP `TenantAuthenticationDiagnosticCollector.MetricPoints`. Include exact-default 4096/4097, single retirement, queue rotation, 4224 ownership, both failure paths, no further batches, existing-key service, joined failures, exact headers/body, no downstream work and exported closed labels. These proofs remain pending code. | -| 9–10 — Carriers and wording | Add front-door/Phase 11/glossary/reference inventory, future runbook wording, explicit test-only constructor seam, no-allocation-on-refusal terminology and timeout limits. Served/snapshot OpenAPI must describe the new 503 cause and capacity hint uncertainty when implemented. | -| 11 — Historical trailer | No defect requiring history rewrite: the trailer denotes implementation/derivation rather than every touched ADR. New revision/implementation commits include 0066; preserve old commits. | - -The shared resource bound remains 4096 retained plus at most 128 retiring. -One acquisition can own only one retiring limiter; only the timer can hold a -128-entry batch. Cleanup failure retains evidence/resources, attempts the whole -owned batch, closes new allocation/batches and propagates through joined -shutdown. Neither the new metric nor a retry hint clears this sticky state. - -The previous source's [CI run 39374628479](https://github.com/HodeTech/LearnStack/actions/runs/39374628479) -passes all 27 jobs at `09e1a169`: 5,792 backend cases with zero skips, 1,656 -frontend cases and the required demo. Independently validated artifact unions, -hashes and natural cleanup qualify that source, not this proposed policy or -its unimplemented controls. This documentation pass needs its own parser, -relative-link/fragment, format and independent review evidence below. - -Revision validation passes: seven ADR-parser controls, ADR-0066 parsed as -Proposed, 1,113 real relative links/fragments across nine changed Markdown -files with none broken, ADR prose wrapping and `git diff --check`. No runtime -tests are rerun for this documentation-only proposal. Fresh independent review -rounds remain required before resubmitting it for approval. - -#### ADR-0066 revision independent review round 1 - -Two fresh reviewers inspect frozen `ed21d9fc` against `09e1a169`: GPT-6 Astra -at xhigh effort covers concurrency/fault/HTTP ownership; GPT-6.1 Sol at high -effort covers corpus, actual test owners and premise accuracy. Both approve the -documentation revision, not the decision or runtime. One minor inventory gap -is verified: the ADR names OpenAPI's new 503 cause but must also name the 429 -capacity-hint clarification already recorded here. The revision now does both. -No runtime tests/builds are run by these read-only reviewers. A second fresh -round is required after this correction. - -#### ADR-0066 revision independent review round 2 - -Two new reviewers inspect frozen `4b4a9ac6` against `09e1a169`: GPT-6 Astra -at xhigh effort independently checks the complete protocol and GPT-6.1 Sol -at high effort checks the corpus, actual HTTP helpers and proof inventory. -Both approve the documentation revision with no actionable finding. The -first-round OpenAPI clarification is verified; all new implementation controls -remain pending. These source inspections neither accept ADR-0066 nor qualify -its unimplemented runtime or production sizing. - -The existing corpus consistency selection also runs against the current docs -using unchanged Release test binaries: five passed, zero failed/skipped. Seven -ADR-parser controls pass; ADR-0066 stays Proposed. The final changed-document -link/fragment and whitespace checks are repeated before commit. Runtime code -and Accepted ADR-0064/0065 are unchanged throughout this revision. The concrete -proposal is ready for maintainer reapproval; no elapsed wait supplies approval. - -### ADR-0066 acceptance and implementation (2026-10-20) - -The maintainer explicitly accepts the revised ADR-0066 and requests -implementation after the two fresh revision review rounds. Acceptance is the -first commit of this dependent work on development, before runtime changes. -The ADR moves to Accepted; ADR-0064 and ADR-0065 each retain their original -body/metadata and gain an adjacent source-attribution erratum plus their own -dated Amendment 2. The index and mutable authorities record the new source. - -**Implementation plan.** One correction step covers the limiter, closed result, -singleton cleanup ownership, two metrics, middleware and served/snapshot SDK -contract. Unit and real signed PostgreSQL/OTLP integration controls deliver the -accepted default, scan, race, fault, shutdown, resource-bound and label proofs. -Then commit the implementation, run two fresh independent multidimensional -review rounds, verify/fix/commit findings, and complete current-head CI evidence -and PR reconciliation. The broader P02b-5 steps are not restarted. - -At acceptance, runtime implementation and its new controls remain pending. -No schema, role, grant, RLS, bearer identity, 600/min subject quota or earlier -visitor/peer admission changes are authorized by this addition. Phase 11 owns -measured sizing, distributed admission, readiness and exercised production -alerts/runbooks; the accepted request/shutdown blocking cost remains explicit. - -#### ADR-0066 implementation and local validation - -The singleton implements the closed detached decision and one shared retirement -owner. Acquisition inspects at most 128 entries, retires at most one and waits -for actual cleanup before its own allocation/debit. Other callers retain service -under the accepted free-slot/fault rules. Timer retirement owns at most 128 extra -resources; blocked and throwing controls verify the total 4224-resource bound, -whole-batch attempts and joined shutdown. The fault owner records one sticky -transition; middleware records one closed rejection per request, including -re-execution. Quota/capacity remain 429; new-key cleanup fault is 503 with the -common explicit 30-second hint. No timeout is a cleanup witness. - -The unit owners exercise actual singleton registration/default 4096/4097, -allocation/debit refusal, bounded rotation, blocked disposal, lost-slot/same-key -and shutdown races, sticky faults and sync/async DI shutdown. Three added Docker -rows use signed tokens, real PostgreSQL audit state and the actual exported OTLP -metric decoder. They distinguish downstream-positive controls from pre-resolution -refusals and verify only the closed metric attributes. Controlled limiter -wrappers inject disposal/idle conditions; they do not certify stock minute-clock -advance or production disposal-fault frequency. - -OpenAPI's public and AccountSite 503 descriptions name cleanup fault; 429 hints -promise no available capacity. The snapshot and generated SDK match the served -contract. Planted removals fail the specific semantic predicates independently -of snapshot parity. No route, response schema, business permission or tenant -scope is added. - -Current local Release results, all with zero skips: - -- Unit: 2600 passed, including 30 focused subject-admission cases. -- Authentication regression: 147 passed, including all five focused signed - PostgreSQL/OTLP rate-limit cases (three new rows). -- Non-Docker integration selection: 276 passed. -- Contract: five passed. SDK: 65 passed; generation/typecheck pass. -- Full architecture: 433 passed at implementation head `01799550`; this complete - run precedes the shared response-policy correction below. -- Warnings-as-errors Release solution builds pass with zero warnings/errors. - -Early integration attempts exposed synthetic teardown assumptions: the web -factory did not propagate an externally owned singleton's disposal exception, -and the injected limiter needed its async cleanup hook. The controls now join -the explicit owner, accept only the exact planted failure tree and separately -exercise real sync/async service-provider shutdown. Earlier failed attempts are -not counted as passes or reported as product runtime defects. - -Implementation is committed as `01799550`, after acceptance-only `c8b9d89e`. -Revision reviews above qualify the proposal only. Final-source hosted CI, artifacts -and PR reconciliation remain pending; historical receipts from earlier source -heads do not qualify this implementation. - -#### ADR-0066 implementation independent review round 1 - -Three fresh read-only reviewers inspect frozen `01799550` against `453d5c3a`: -GPT-6 Astra at xhigh covers concurrency/security/resource ownership; GPT-6.1 Sol -at xhigh covers proofs/DI/exported metrics; GPT-6.1 Sol at high covers the corpus, -OpenAPI/SDK and authority closure. No build, runtime probe or hosted qualification -is attributed to these inspections. Two findings are verified and corrected: - -- A classified unknown API path reaches subject admission outside the public/ - AccountSite response wrapper. Subject refusals therefore missed `no-store`. - The shared response policy now applies to every subject refusal, independently - of endpoint matching, preserving the one Problem Details writer. -- The manual timer accepted any positive cadence. Its first due time and period - now independently require the accepted 30 seconds. - -Root verification also exposes a false-green header helper: a null-conditional -chain could skip the entire assertion when `Cache-Control` was absent. Grouped -nullable values now fail for absent no-store, retry and content-type headers in -these authentication helpers. Clean, absent and false no-store controls make this -specific omission fail. Initial unknown-path cases passed through the weak helper; -with the strict helper both signed rows fail on missing `Cache-Control` before the -runtime fix. Those initial passes are not accepted as the regression proof. - -After the fix, both rows exercise unknown-path quota, capacity and cleanup-fault -refusals with exact body/status/retry/no-store, unchanged resolution/audit/read -observers and updated actual exported counts. The complete 147-case authentication -selection passes, including all five focused PostgreSQL/OTLP rate cases. Thirty -focused unit cases and 25 authentication-authority/corpus cases pass, all with zero -skips. The Release solution build has zero warnings/errors. The 433-case complete -architecture run above remains separately bound to the implementation before this -small response-policy change; final-source hosted shards must qualify the full -current population. A second fresh independent implementation review round remains -pending after the correction commit. - -#### ADR-0066 implementation independent review round 2 and local closeout - -Three new read-only reviewers independently inspect frozen `082a658c` against -`453d5c3a`: GPT-6 Astra at xhigh covers the complete runtime/HTTP protocol; -GPT-6.1 Sol at xhigh covers proofs, DI, actual export decoding and strict header -controls; GPT-6.1 Sol at high covers the corpus, contracts and source closure. -All approve with no remaining actionable finding. Their source inspections -verify the first-round corrections; no executed checks or production readiness -are attributed to them. - -Acceptance (`c8b9d89e`), implementation (`01799550`) and verified corrections -(`082a658c`) are separate commits on development. Both fresh implementation -review rounds are complete. The final changed-document sweep resolves 1903 -relative file/fragment targets with none broken; seven ADR-parser controls and -whitespace checks pass. Accepted ADR-0064/0065 remain unchanged after their -acceptance disclosures; ADR-0066 gains only its own dated implementation -Amendment 1 after acceptance. - -This closes the local ADR-0066 correction step. The -[PR #33 handoff](https://github.com/HodeTech/LearnStack/pull/33) owns subsequent -verification of the exact final-source hosted run, immutable artifact identities, -complete case unions, natural cleanup and frontend/demo proof, independently of -historical source receipts. No historical green run qualifies a later source, -and this local closeout makes no hosted-success or merge claim. P02b-6 is not -started; production sizing, distributed admission, readiness and exercised -runbooks remain Phase 11 obligations. - - -## P02b-5 systematic proof and document corrections (2026-10-20) - -**All three correction steps and review rounds are complete on development, -starting at `5daee8ad`; current-source hosted A/B qualification is owned by the -live PR handoff below.** P02b-5's five -implementation steps and ADR-0065/0066 corrections are implemented and unmerged. -This follow-up validates the current production subjects and their falsifiable -controls. Earlier review conclusions are scoped to their source and inspected -paths; they are not a guarantee against a newly identified proof gap. No merge, -new packet, production readiness or new decision is inferred here. - -### Correction plan and ownership - -1. **Backend proofs, hardening and corpus.** Close global MVC filter composition, - cross-root handler acquisition, attribute-based assertion ownership and - exact read-mode/OpenAPI proof gaps. Add isolated real-reader and recorder - controls, preserve cleanup ownership under diagnostic failure, and reconcile - current versus historical status. Commit, run two fresh independent review - rounds, verify findings and commit fixes. -2. **Demo and SDK proof.** Preserve failure origin/status ownership, bind JSON and - HTML report bytes to one receipt, qualify clean/mid-run source identity and - distinguish local transport refusal. Preserve all browser budgets, flags, - deadlines, response contracts and retry behavior. Commit, run two new - independent review rounds, verify findings and commit fixes. -3. **Measured CI timing repair.** Reconcile the frozen advisory Architecture - weights with complete hosted TRXs after a current-source deadline refusal. - Preserve every selector, the A/B algorithm, six/twelve shard counts and all - deadlines. Commit and complete two fresh independent review rounds, then - qualify both complete assignments on one final source and plan under - ADR-0063. - -Focused checks accompany each step. Full architecture, Docker/native, frontend -and managed-demo qualification must cover the final source through the existing -bounded hosted checks and exact artifact/result unions. Historical green runs -do not qualify this delta. PR #33 remains open for maintainer review. - -### Validated dispositions - -| Area | Current finding and action | -|---|---| -| Global MVC filters | Missing composition/source census, not a demonstrated runtime auth bypass. Inventory actual MVC filters and compiled extra/removed/duplicate registrations. Endpoint authorization already precedes MVC. | -| Nested HTTP handler roots | Reject a different root reached through a custom interface or generic service acquisition/non-Handle member. Preserve generated self-capture and ordinary helper positives. | -| Assertion ownership | Inspect custom-attribute constructor/named/array metadata recursively; pin exact two header names and exact recursively discovered recorder counter vocabulary. | -| Read-only selection | Protect the actual consumed mode from name-based overrides; preserve approved PublicSurface and two job pre-read fallbacks. Isolate immutable declaration/catalog shape controls. AddSingleton declarations must not silently discard an earlier different declaration; the immutable set still deduplicates exact types. | -| Served contract | Pin parameter locations/types/formats/requiredness, no request body, exact declared ProblemDetails fields and existing leaf constraints. Preserve the accepted open extension representation; additionalProperties:false would be a contract change. Dirty controls must require their intended diagnostics. | -| Credential and metadata paths | Credential 401 on classified unmatched paths also applies shared no-store. Reject ambiguous decoded dot-segment suffixes/control bytes before metadata I/O, retaining harmless escaped path positives. | -| Authentication diagnostic vocabulary | Replace arbitrary stage/reason arguments with a closed typed outcome, preserving existing emitted values. Existing real OTLP ordinary-host/IP/port/path/query and exemplar controls already cover the two authorized native meters; no speculative meter is added. | -| Startup and framework proof limits | Test missing/empty bootstrap issuer against a present ambient value. Source-owned pipeline checks are not published-host analysis. TestServer whitespace cases do not prove native Kestrel pre-normalization bytes. The event-3 adapter remains explicitly synthetic. | -| Cleanup exception ownership | An in-process metric callback failure must not skip the rest of an owned faulting batch or strand shared shutdown. Retain errors and drain remaining resources. Exercise both timer-join failure/shutdown forms. The production factory remains stock FixedWindowRateLimiter; arbitrary throwing IdleDuration implementations are outside that production profile. | -| Shutdown admission | Preserve the explicitly tested ObjectDisposedException after owner closure. Do not mislabel orderly closure as sticky RegistryFault or invent a fifth result/status policy. Host drain qualification remains Phase 11. | -| Reconciliation and audit proofs | Use the live-version classifier for assertion paths; add unresolved-header, matching-organization and exact Warning-property controls, plus direct invalid audit-budget keys. Preserve recorder invariant failures for corrupt nil/sentinel defended tenants. | -| Real configuration reader | Isolate physical read-write, missing/mismatched/sentinel HostScope and organization provenance refusals on real announced/enlisted app-role frames with same-context positives. Visibility follows the resolved organization, including claim-selected scope. | -| Existing quota/isolation controls | Issuer-versus-subject tuple separation and actor/scope stability are already covered by the actual 600 component proof. Process-global logging tests already use a serialized collection; retain that explicit mitigation and the known-working child-host configuration. | -| Future version and policy boundaries | Only v1 is authorized. No v2 route, new request or readiness policy is activated. Phase 03 owns affirmative live membership and no-host header-evidence policy before exposure; P02b-7 owns BFF recovery; Phase 11 owns capacity/readiness/alerts/drills. | -| Demo diagnostics and receipts | Confirmed gaps concern deadline/spawn/daemon ownership, input/cleanup phases, HTML byte binding and dirty/mutating source identity. Step 2 owns their corrections and real-child/corruption controls. | -| SDK/environment proof limits | The path fence already makes zero forbidden fetches and has no automatic retry. Required frontend CI already typechecks SDK tests; no missing CI gate is claimed. Constructed child environments do not prove Next never loads private dotenv; issuer is not a credential and no browser leak is established. | -| Current versus historical corpus | Preserve dated proposal/pending receipts with explicit as-of banners. ADR-0066 Amendment 2 qualifies its acceptance-time proof list; ADR-0065 Amendment 3 records delivery. ADR-0064 Amendment 3 clarifies read-mode instrument classification without rewriting Status or its accepted decision. Separate admitted rows from suppressed occurrences in the Tenancy matrix. | - -### Step 1 verification and review status - -Implementation is committed as `57f49ce0`. Warnings-as-errors -Release builds with zero warnings/errors. Complete Unit passes 2,616; all five -Contract cases pass; the 46-case architecture selection covers surface, mode, -manifest, tenancy, authentication authority and corpus owners. The PostgreSQL -selection passes all 54 AccountSite/subject-admission cases. The earlier focused -non-Docker HTTP selection passes 121, including startup with an ambient issuer. -The complete non-Docker Integration population passes all 282 cases. All -recorded tests have zero skips. - -Initial new-control failures were fixture errors, not waived runtime failures: -unclassified paths need an explicitly empty collection assertion; a failed -ReadWrite owner permanently poisons its unit, so the ReadOnly positive takes a -fresh scope. Optional per-category Debug configuration produced an invalid -Serilog scalar/section combination and was reverted; the existing serialized -logging collection remains authoritative. The corrected owners pass. - -The changed-document sweep resolves 2,216 relative file/fragment targets with -none broken; seven ADR-parser controls and whitespace checks pass. The first fresh -independent implementation review round is recorded below; complete -architecture/Docker/native and managed demo qualification still belongs to -final-source hosted CI. - -#### Step 1 independent review round 1 - -Three new read-only reviewers inspect `5daee8ad..57f49ce0`: GPT-6 Astra at -xhigh covers runtime/security/resource lifetime; GPT-6.1 Sol at xhigh covers -proof correctness and cost; another GPT-6.1 Sol at xhigh covers tenancy, real -reader controls and corpus governance. Runtime and tenancy/corpus find no -actionable issue. The proof review verifies two additional P2 coverage gaps: - -- A DI-registered `IFilterProvider` can replace effective executable filters - through `FilterItem.Filter` without changing `MvcOptions.Filters`. Pin the - actual provider inventory and bound production provider capability/registration, - with compiled dirty/restored controls. -- A custom attribute implementing `IAllowAnonymous` is not the concrete - `AllowAnonymousAttribute`. Match inherited/implemented anonymous metadata, - preserve exactly the approved public attribute, and check actual endpoint - authorization metadata too. - -Neither finding demonstrates a production authentication bypass; no such -provider/attribute is present, and the independent AccountSite gate remains. -The verified fixes add the actual framework provider/ordering inventory and a -real dirty DI provider that changes effective filter output while the options -list remains unchanged. Compiled implementation/registration controls fail the -provider diagnostic. Direct and inherited custom anonymous attributes fail the -same authorization predicate; public actions still require the exact standard -attribute. Actual endpoint metadata is checked independently. - -Release builds with zero warnings/errors and whitespace verification passes. -Focused surface/authority architecture passes all 23 cases; actual runtime -controls pass both Development/Production cases, with zero skips. These reviews are -source inspections, not executed tests. The second fresh independent review -round inspects the committed correction below. - -#### Step 1 independent review round 2 - -Three fresh read-only reviewers inspect `5daee8ad..6380fccc`: GPT-6 Astra at -xhigh covers proof closure; GPT-6.1 Sol at xhigh covers runtime, cleanup and -effective authorization; GPT-6.1 Sol at high covers corpus governance and -tenancy proofs. Corpus and the runtime corrections have no actionable finding. -The two proof findings concern supported MVC composition channels: - -- Attached/inherited action or controller filters can change effective - `ControllerActionDescriptor.FilterDescriptors` while the global options and - provider inventories remain unchanged. Inventory effective descriptors and - exercise attached filters/factories with dirty/restored controls. -- Explicit `AuthorizationPolicy` or `IAuthorizationRequirementData` endpoint - metadata is consumed separately from `IAuthorizeData`/`IAllowAnonymous`. - Reject these additional channels on the approved endpoints and exercise a - real convention-injected policy as well as compiled metadata/conventions. - -Neither finding identifies a current production bypass. The runtime correction -pins all six effective per-action descriptors, including framework factories, -the inherited API marker, exact declared response type, scope, order, reuse and -factory arguments. Added/removed/changed descriptors fail the same assertion. -Three real attached-filter convention controls preserve global options/provider -inventories while changing the effective descriptors. Two real endpoint -conventions separately inject an explicit policy and requirement metadata; -removing only that metadata restores the authorization assertion. All seven -runtime cases pass with zero skips. Compiled direct/inherited attributes cover -both filter and requirement interfaces; type/service factories and inherited -controller metadata fail their intended diagnostics. The shared endpoint -capability census covers the ordinary authorization/metadata conventions and -their supported direct mutation APIs, with an unchanged display-name convention -as the clean control. A getter alone is not treated as a metadata write: the -existing idempotency OpenAPI transformer only reads metadata. No owner allowlist -was added. Release builds with zero warnings/errors; all 53 focused -surface/authority, public-surface, tenancy, job-manifest and corpus architecture -cases pass with zero skips. Both findings are corrected in `09dcb111`. Their -original round-2 reviewers independently inspect that committed delta and confirm -their findings closed, with no remaining actionable issue in the targeted fixes. -These are source inspections, not additional executed test runs. Step 1's two -independent rounds and verified correction cycle are complete; Step 2 proceeds -under the plan above. Final-source hosted qualification remains outstanding. - -### Step 2 implementation and verification - -**Initial implementation at `8f433a73`, before independent reviews.** The SDK's -fixed, parameterless `PublicRequestRefusalError` is -available only from its server entry. Exact typed transport refusals become the -existing local `invalid-request`; cancellation still takes precedence, provider -text/lookalikes remain transport failures, and response-body failures are not -reclassified. The configured public path fence uses that port before any fetch. -Negative calls send zero requests; the restored public call returns a real -validated success. There is no automatic retry or HTTP response-policy change. -All 72 SDK cases and the 105 public-client/middleware cases pass. - -Demo command failures retain a closed reason and command/daemon origin. Only -observed spontaneous exits supply native status; deadline, spawn, output, -cancellation and cleanup do not borrow a later stop signal. The actual worker -marks missing/malformed input before CDP connection. Process/profile cleanup -preserves the first failure and never attributes its intentional stop status. -A confirmed failed daemon spawn owns no process and does not masquerade as an -output-cleanup fault. - -The CI lifecycle captures clean owned-root Git commit/tree before restore/build, -rechecks it entering proof and before success, and refuses ambient Git redirects -or changed tracked/staged/nonignored source. Real temporary repositories exercise -dirt, unchanged-tree commits, in-checkpoint mutation, root anchoring and finite -command bounds. A copied actual launcher proves the CI check precedes restore; -local-mode source remains usable while dirty. These observations do not attest -ignored inputs or edits restored between checkpoints. Both JSON and HTML byte -digests bind the admitted report pair; corrupt, missing and substituted members -refuse. The child-environment test now describes only constructed values, without -claiming that Next never loads private dotenv files. - -The six-file demo selection passes all 224 cases. The complete guarded frontend -run passes 1,688 cases (1,616 web and 72 SDK), zero skips/todos; lint, typecheck and -production build pass. Import-order and test-only environment typing failures -were corrected without changing the runtime contract. The document sweep resolves -2,275 relative links/fragments with zero broken; seven ADR-parser controls and -whitespace checks pass. Neither independent Step 2 review round had started at -that implementation point. -Actual full-stack browser/audit and final-source backend qualification remain -with the existing hosted checks. - -#### Step 2 independent review round 1 - -Three fresh read-only reviewers inspect `09fdf8a2..8f433a73`: GPT-6 Astra at -xhigh covers process lifetime and diagnostic ownership; GPT-6.1 Sol at xhigh -covers source/report proof; GPT-6.1 Sol at high covers SDK, declarations and -corpus consistency. Source/report and SDK/corpus approve their scopes. The -process review verifies three P2 diagnostic/first-failure gaps: - -- Native cancellation from coordinator timers or its positive HTTP observer - can bypass the command owner's typed path and be recorded as `unknown`. -- An observed output refusal is stored before physical child closure, but the - command race omits that refusal. A later shorter deadline can replace it while - an owned signal-resistant child awaits bounded escalation. -- A second daemon exit replaces the activity check's stored failure while the - public failure promise still retains the first daemon's error. - -These findings concern diagnostic correctness and ownership; no budget or -authentication bypass is demonstrated. Regression controls first reproduce all -three against `8f433a73`. Trusted coordinator cancellation now classifies raw -timer/HTTP aborts using only its owned signal, retaining typed first faults and -excluding cleanup. Spawn/output refusal is published immediately and raced -separately from physical closure; the same existing bounded stop is still joined. -The daemon owner latches one error for both its public promise and active checks. -Real signal-resistant children prove output beats the later deadline and that -daemon refusal precedes physical closure; two daemon exits preserve the original -17 outcome after the later 23 outcome. The daemon publication control compares -event order without a narrow scheduling-time assertion. Native waits exercise -the two distinct startup/proof classification contexts; the HTTP abort is real. - -All six distinct regression cases pass within the complete guarded frontend run: -1,694 passed (1,622 web and 72 SDK), zero skips/todos. Lint and typecheck pass. -Review conclusions above are source inspections; they do not independently rerun -the recorded local tests. The corrected commit proceeds to a second review round -with new independent reviewers. - -#### Step 2 independent review round 2 - -Three new read-only reviewers inspect `09fdf8a2..9d08070e`: GPT-6 Astra at -xhigh covers process lifetime, diagnostics and cleanup; GPT-6.1 Sol at xhigh -covers source checkpoints and report integrity; another GPT-6.1 Sol at high -covers SDK, declarations, consumers and corpus. The source/report and SDK/corpus -reviews find no actionable issue. Source capture precedes the shared launcher's -own restoration/build work; workflow browser-tool bootstrap precedes that -checkpoint and ignored dependencies remain outside its attestation. - -The runtime review verifies one further P2: waiting for ChildProcess `close` to -publish a failing native exit can let a later deadline, or another daemon's -prompt closure, replace the earlier native failure while inherited output pipes -remain open. The correction must publish failing `exit` status immediately while -retaining successful output completion and bounded physical cleanup/stream drain. -The existing exit-before-close lifecycle control makes this a supported process -shape rather than an assumed provider behavior. Fix verification follows below. - -The four new real-child controls first show three failures and one existing -successful-output positive. The fix publishes only failing native `exit` -outcomes early; zero-exit commands still await `close` and complete captured -output. Nonzero and signal failures beat a later deadline despite paused output; -the first daemon leader's failure survives the second daemon's prompt closure. -Physical group shutdown and separate bounded stream drainage remain owned. -All four controls then pass. The complete guarded frontend population passes -1,698 (1,626 web and 72 SDK), with zero skips/todos; lint and typecheck pass. -Five final corpus controls, seven ADR-parser controls and the changed-document -sweep (2,275 relative file/fragment targets, none broken) pass. The runtime fix -receives targeted independent reinspection before correction closeout. - -Targeted reinspection of `9b6794da` finds the same ordering gap for a daemon's -unexpected zero exit: ordinary command success correctly waits for `close`, but -daemon success is itself a failure and must publish immediately too. The added -zero-then-23 control fails before the follow-up fix. A distinct all-native-exit -observation now serves daemon ownership, while ordinary successful capture still -waits for `close`. Both zero-then-23 and 17-then-23 retain the first daemon fault. -All five ownership controls pass; the complete guarded frontend population passes -1,699 (1,627 web and 72 SDK), zero skips/todos, with clean lint and typecheck. - -Both independent runtime and proof reviewers reinspect `49c2c431` and confirm -the ordering finding closed, with no remaining actionable issue in the fix. -These are source inspections, distinct from the locally executed controls. - -### Correction closeout and current-source PR qualification - -Both correction steps complete implementation, commits and two fresh independent -review rounds. Verified findings from each round are fixed and committed; the -targeted follow-up inspections close the final native-exit variant. No test -population, timeout, required check, browser flag or audit threshold is relaxed. -No new decision, schema, role, grant or deployment policy is introduced. - -The [live PR #33 handoff](https://github.com/HodeTech/LearnStack/pull/33) owns -qualification of the exact current head and checkout merge: all hosted workers -and required checks, API-bound immutable artifact identities, complete case -unions, naturally completed cleanup and the frontend/browser/report proof. -Local passing checks and earlier green runs do not qualify a later source. This -record closes correction implementation/review, makes no merge or production -readiness claim, and requires that current-source evidence before merge. -P02b-6 remains unstarted. Phase 03 membership/authorization, P02b-7 BFF recovery -and the named Phase 11 production-activation obligations retain their owners. - -### Step 3 — Measured CI timing repair - -The two implementation correction steps close at `00a7877e`. Hosted -[run 39417319998](https://github.com/HodeTech/LearnStack/actions/runs/39417319998) -does not qualify that source: attempt 1 completes 25 successful jobs but refuses -`ordinary-9` before tests on `docker_census_unreadable`; its integration aggregate -fails closed. A full second attempt, without source or policy changes, completes -that Docker job and 25 successful jobs overall, but `architecture-3` reaches -`deadline_exhausted`; its backend aggregate fails closed. No successful sibling -from one attempt substitutes for another attempt's missing result. - -The second attempt's failed Architecture artifact retains 26 of 27 completed -case IDs, all passed, with owned cleanup complete and no forced cleanup. The -remaining selector is -`Background_job_authority_census_detects_extra_activation_and_removed_live_guards`. -Three expensive selectors from the same `JobAuthorityMutationTests` class share -that bin and execute serially. The separate local selector control passes in -203.11 seconds of process wall time; this establishes neither hosted duration -nor whole-shard fit. The detector and all clean/dirty/restored mutations remain -unchanged. - -Under [ADR-0063's reviewed timing-plan revision](../decisions/0063-complete-bounded-ci-test-shards.md#versioned-plan-and-independence), -refresh only weights observed in the five complete Architecture TRXs from -attempt 2 (`architecture-0`, `1`, `2`, `4`, `5`). Their 406 passed case rows -belong to 242 exact assembly/selector groups. Sum each group's observed case -durations, round upward to milliseconds and retain a minimum of one millisecond. -The failed bin's 21 selector estimates and provenance remain unchanged; the -uncompleted selector's old 371-second estimate is not relabelled as a current -measurement. Each new source names its API ZIP digest, artifact ID, run/attempt, -owner, PR head and actual merge checkout. The closed `hosted_trx` kind describes -this evidence without mislabelling it as local or rounded console data. - -These advisory weights influence ownership only. Method/theory grouping, exact -case unions, default costs, fixed-cost unknowns, plan salt, assignment algorithm, -six Architecture/twelve ordinary workers, the twenty-minute execution ceiling and -five-minute aggregates remain unchanged. Offline A/B replay is not a runtime -guarantee. A plan change requires fresh independent review and two genuinely -different complete hosted assignments on the same final source, plan, toolchain -and case population. Earlier frontend/demo successes remain source-bound -historical receipts and cannot qualify that later head. - -The refreshed plan digest is -`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. -Replay reconstructs the original actual B assignment and validates exact old/new -A/B unions, whole-selector grouping, different co-membership and unchanged -ordinary/base/native owners. All 52 shard controls, 16 result controls and the -existing workflow topology validation pass. Review closure follows below; -offline replay alone does not satisfy the required complete hosted A/B -qualification. - -#### Step 3 independent review rounds and local closeout - -The implementation is committed at `9014ec66`. Round 1 uses two fresh read-only -reviewers: GPT-6 Astra at xhigh independently reconstructs raw provenance and -assignment arithmetic; GPT-6.1 Sol at high reviews contract, parser and corpus. -Both approve with no actionable finding. Round 2 uses two new GPT-6.1 Sol -reviewers, at xhigh for raw evidence and high for contract/corpus. Both approve -with no actionable finding. The second raw-evidence review independently checks -all five ZIP digests, archive/extracted-byte equality, result file hashes, -406 TRX rows, exact tick arithmetic and all 5,847 case IDs across old/new A/B. -These are read-only calculations and inspections, not independently rerun test -suites or hosted-fit claims. - -Testing 06 also repeats ADR-0063's exact qualification boundary: rollout and plan, -algorithm or fixture-lifetime changes require both complete layouts; normal -future pushes run one complete assignment. No new authority or decision is -introduced. All three correction steps now complete implementation, commits and -both independent review rounds. The live PR handoff must verify two fresh full -A/B attempts for this timing revision on one final source, plan, toolchain and -population, preserving current-attempt evidence and exact required checks. -Neither failed historical attempt nor the offline replay qualifies that head. - -#### Step 3 provenance guard follow-up - -Source `b3abbce6` completes both full attempts of hosted run `39424514759`: -A and B each pass all 27 jobs, 5,847 backend cases including 31 native cases, -1,699 frontend cases and 27 JSON/HTML demo pairs. Independent API/archive/result -validation verifies equal complete case populations, actual different method -co-membership, matching toolchain identities and naturally completed cleanup. -The live PR retains both attempt-specific receipts and their limits. - -A subsequent inspection confirms a Minor parser gap: the new `hosted_trx` kind -accepted a null source or run identity, despite requiring identified hosted -timing evidence. All five committed hosted sources already have both values; -neither their measured provenance nor the successful receipts are defective. -The guard now requires both identities for this kind. Its actual-owner control -fails in all three null combinations before the fix and passes afterwards; -complete hosted records and the disclosed nullable local/console shapes remain -accepted. The existing field-format and unknown-kind refusals still apply. - -The plan bytes, weights, assignment algorithm and fixture lifetime do not -change. Its digest remains -`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. -This is source-shape validation, not API attestation of an arbitrary timing -record. Implementation `dbb2e9fd` completes two fresh independent follow-up review -rounds, each with two GPT-6.1 Sol reviewers at high effort. All four approve with -no actionable finding. Round 1 independently exercises 270 kind/identity -combinations; Round 2 exercises separate 507- and 297-combination controls. Both -rounds reproduce the three missing-identity failures against the preceding -parser. These are local/source proofs, not independent hosted attestation. -All 52 combined plan/result controls, 16 separate result controls and topology -validation pass; 2,276 relative links/fragments remain valid. - -ADR-0063 requires one complete current-source assignment for this normal push; -the earlier A/B receipts qualify the unchanged plan on their named source, not -the subsequent guard commit. The live PR owns final-head qualification. - -## P02b-5 merge and closeout (2026-10-20) - -**P02b-5 is complete and merged.** The maintainer merges -[PR #33](https://github.com/HodeTech/LearnStack/pull/33) at -`2026-10-20T20:18:42Z`. The verified final PR head is -`419e456260dc2023f3e6d538a46ede8b1d7e8f20`; the squash merge is -`24705a7a81ddfb7e0f5f5349370a53a55ca9e4eb`, whose parent is -`b81006c7af7d38f1587ecb3bf93dbcca16f353e0`. The PR head, tested merge checkout -`be8417c3a289d26e9062bd40bf163d51987d3e11` and actual squash merge all have tree -`7adeacfe81a15cc5e36a77cf79006da201f01e26`; their tracked contents are identical. - -| Step | Delivered scope | Review status | -|---|---|---| -| 1 | Isolated strict token foundation, bounded metadata and private diagnostics | Both independent rounds complete | -| 2 | Host-backed AccountSite query, exact physical read-only ownership and audit Off | Both independent rounds complete | -| 3 | Attributed host/claim reconciliation and stable validated-subject admission | Both independent rounds complete | -| 4 | Atomic HTTP activation, masked refusal contracts and authenticated SDK contract | Both independent rounds complete | -| 5 | Production authority census, real negative controls and corpus reconciliation | Both independent rounds complete | - -The subsequent ADR-0065 audit-budget/telemetry and ADR-0066 retained-subject/ -cleanup refinements are delivered with their recorded independent reviews. -The [systematic corrections](#p02b-5-systematic-proof-and-document-corrections-2026-10-20) -close backend proof boundaries, SDK/demo failure ownership, paired report/source -identity and measured CI weights. All three correction steps and the final -hosted-source identity guard complete two fresh independent review rounds. -Earlier delivery records remain source-bound history, including their original -unmerged, running and failed observations. - -### Final-source qualification - -[Run 39431896517, attempt 1](https://github.com/HodeTech/LearnStack/actions/runs/39431896517/attempts/1) -passes **27/27 jobs** on the final PR head. The independently downloaded, -API-bound archives verify job/artifact identities, ZIP and exported-file hashes, -complete actual case-ID unions and both aggregate results: - -- **5,847 backend cases**, zero failures/skips: 2,616 Unit, 433 Architecture, - five Contract, 287 non-Docker Integration, 2,475 ordinary Docker and 31 native. - The backend and integration aggregates count 3,341 and 2,506 respectively. - All 20 execution owners complete with joined cleanup and no forced cleanup; - native refusal evidence is empty. -- **1,699 frontend cases** across web/SDK, zero skips/todos; typecheck, lint, - production build and the ingress/cleanup proof pass. OpenAPI, secret scan - and meta pass. -- **27 JSON/HTML report pairs** verify both byte digests and source/tree/build/ - invocation/configuration identities. All 134 API completions are HTTP 200. - Nine navigations, 24 visibility controls, two TLS refusals and the timeout - control pass. The proof takes 651.490 seconds and cleanup 12.839 seconds; - all owned processes, Compose, private files, environment and lock are removed. - Hard JS/CLS/accessibility budgets pass; eight URL groups retain nonblocking - timing warnings. Browser flags and thresholds are unchanged. - -The unchanged timing plan separately qualifies both complete assignments in -[run 39424514759, A](https://github.com/HodeTech/LearnStack/actions/runs/39424514759/attempts/1) -and [B](https://github.com/HodeTech/LearnStack/actions/runs/39424514759/attempts/2) -at `b3abbce65ba60ae4165b1eb09bd44d8644e7843d`: each passes all 27 jobs with the -same complete 5,847-case population and observed toolchain, but different actual -Architecture/ordinary/SharedSchema co-membership. Their plan digest is -`85ce77743fd83d924060ad7008899595908ec4fd466597078ae6509e022db01d`. -The later guard changes no plan bytes, weights, assignment algorithm or fixture -lifetime; ADR-0063 requires the separate complete normal-push assignment above. -Historical A/B results are not reused as final-head results. The earlier failed -run `39417319998` remains failed evidence, not a partial passing receipt. - -Read-only protection verification retains all seven required context names, -their GitHub Actions app bindings and strict checking. No protection setting, -test population, timeout, audit threshold or browser budget is relaxed by this -closeout. The separate post-merge push -[run 39490885612](https://github.com/HodeTech/LearnStack/actions/runs/39490885612) -is queued at initial merge verification; it is not counted as completed -post-merge execution. The final PR-source qualification and identical-tree -comparison above are the merge evidence. - -### Remaining work and next packet - -**Next: P02b-6 realm/TTL decision pass.** Re-verify the remaining G12 realm/ -reconciler choices and G13 access-token lifetime authority before changing -Keycloak or seed users. Deliver the shared client scope and protocol mappers, -admin-only UUID user-profile attributes, exact seed identity agreement, -idempotent fresh/warm realm reconciliation and real Keycloak token/TTL proofs. -The already Accepted BFF-client choice remains the baseline; this closeout -accepts no new gate or ADR. - -P02b-7 retains BFF code exchange, token/session custody, refresh serialization, -CSRF/logout, guarded pages and SDK bearer transport. P02b-8 retains LS0002, -the retained-store erasure inventory, remaining carrier reconciliation and the -Phase 02b exit. No browser sign-in or live membership/permission service is -claimed by the merged API boundary. Phase 03 owns membership/authorization, -Phase 06 the full browser OIDC journey, and Phase 11 production identity, -readiness, distributed capacity and operational qualification. -P02b-6–8 remain unstarted; Phase 02b remains in progress. - -**Documentation-only closeout validation.** Five Release corpus consistency -cases and seven ADR lifecycle/parser controls pass, with zero failures/skips. -All 1,440 relative links/fragments in the ten changed Markdown files resolve. -Prose wrapping, whitespace and private-reference checks pass. Accepted ADRs -and the dated P02b-5 decision/delivery/review records are byte-preserved against -the final PR head. The local run covers these status/navigation edits; the -runtime, Docker/native and browser qualification remains source-bound to the -completed hosted receipts above. This closeout starts no next packet. - -## P02b-6 decision package (2026-10-20) - -**Status: Accepted — 2026-10-21.** The maintainer approved the decision package -at `6d75e532` and the four-step implementation plan on `development`. Acceptance -closes G12's realm/reconciliation/callback choices and G13's issuance-TTL part. -P02b-7's session portion of G13 stays Open independently. This acceptance record -and the two Registered catalogue obligations precede runtime implementation; -no realm, seed identity, runtime or CI implementation is delivered by acceptance. -The decision pass originally inspected `b4945705` after the P02b-5 merge; dated -inspection and review receipts below retain their as-of proposal status. - -### Problem, scope and decision vehicle - -P02b-5 validates the strict API profile, but the committed development realm does -not issue it. P02b-6 makes actual Keycloak issuance agree with that profile on -both fresh and existing development databases. It supplies protected identity -attributes, one repeatable development reconciliation path and real token/API -proofs, while preserving existing accounts and the separate operator realm. - -G12 explicitly selects a phase-document vehicle unless reconciliation becomes -ADR-0004's runtime `IIdentityProvider`. This package keeps a bounded Node.js -Admin REST client in development tooling; no application port, runtime provider -SDK, endpoint, database role/grant or schema is introduced. G13 delegates the -issuance-lifetime answer to this record and the reconciled Security standard. -A new ADR is therefore not proposed. Any implementation requiring a different -provider/runtime boundary reopens this pass before code; approval of this -package does not authorize that change. - -**Issuance-carrier follow-up — 2026-10-21.** The no-ADR statement above records -the original package's vehicle. A dedicated issuance carrier now exists as -[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md), Proposed -pending separate maintainer acceptance. The earlier 900s phase approval remains -valid; G12's development-tooling vehicle and G13's Open session portion remain -unchanged. - -**Issuance-carrier acceptance — 2026-10-21.** The maintainer separately approved -the revised ADR-0067 after its correction reviews. It now supplies the dedicated -issuance decision authority; Security 11 retains the ongoing rule. The earlier -phase approval and Proposed-state follow-up above retain their original -chronology. G12's vehicle and G13's Open session portion are unchanged. - -The existing decisions remain authoritative: -[ADR-0004](../decisions/0004-authentication-strategy.md), -[ADR-0036](../decisions/0036-tenant-resolution-trusted-inputs.md) and -[ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md). -No Accepted ADR body or acceptance metadata is rewritten. This package adds no -supersession of their authentication, tenant authority or audit contracts. - -### Reviewed premises and necessary document actions - -| Current source | Verified premise | Required disposition | -|---|---|---| -| `infra/keycloak/realms/learnstack.json` | Public `learnstack-web`, no custom client scope/mappers, slug-valued tenant attributes and no stable actor attributes | Configure the already Accepted confidential PKCE profile and real seed UUIDs; do not loosen the API to accept the old export. | -| `scripts/seed.sh`, `scripts/wait-compose.mjs` | Seed checks both realm issuers, then invokes the application Seeder; no Admin REST reconciliation | Add the shared bounded tooling call after readiness and application seed convergence; preserve the selected Compose/env identity. | -| `scripts/demo.mjs` | Demo invokes the .NET Seeder directly, then CI stops its Keycloak | Invoke the same reconciler before that stop. A seed-script-only change cannot converge this entry point. | -| `SeedData.cs`, `DemoIdentities.cs`, Seeder `Program.cs` | Tenant/org/host identities already have typed, read-only tooling projections; no identity-user declaration | Add stable actor/seed-user declarations and a credential-free projection without a new application identity table or production Seeder reference. | -| Realm `accessTokenLifespan`, API client override, Keycloak README, Security 11 | Realm/API override are 1800s; README recommends 900s for production; API permits at most one hour | Select one development issuance value, remove conflicting client overrides and distinguish issuance from API acceptance/session lifetimes. | -| This phase's former identity completion criterion: `exp - iat` equals the configured lifetime | Pinned Keycloak reads the issuance and expiration clocks separately; a second rollover can make that difference 901 for a 900s setting | Replaced at acceptance with exact realm/no-override checks and bounded observed-issuance evidence below; independent drift controls remain required. | -| Keycloak 26.6.2 profile/import source | Profile configuration is a declarative-user-profile component; runtime Admin REST uses `users/profile`. Declaring a custom `clientScopes` list can suppress automatic built-in creation | Use the supported component/config representation; include/verify actual `basic` and its `sub` mapper, not merely a scope name in a client list. | -| Keycloak account REST and profile source | Account permission is checked before attribute-edit policy; profile PUT and user-attribute PUT can replace supplied configuration/maps | Pair self-service refusals with a successful ordinary profile edit, merge unrelated definitions/attributes and verify retained state. A generic 403 proves neither protection nor preservation. | -| Standards 06, integration skills and runner instructions | Container guidance still describes Postgres as the only current integration dependency | Add the named Keycloak fixture and Docker-trait/source controls with its first tests; preserve the real app-role PostgreSQL requirement for API/database assertions. | -| Standards 21 provider-SDK backfill row and this phase's enforcement scope | The reconciler introduces no runtime provider SDK subject | Resolve the row's owning-phase handoff explicitly at acceptance, as specified below; do not claim this script implements that structural rule. | - -The review includes the full identity architecture, realm README/exports, -P02b-5 accepted profile and handoff, G12/G13, current completion/risk clauses, -Security/Testing/Infrastructure/Documentation standards, authentication and -SDK-boundary catalogue entries, Phase 03/11 ownership, seed/demo orchestration -and their existing environment/process boundaries. Historical dated delivery -receipts retain their original words; mutable current descriptions are corrected -with their actual implementing slice. - -### Accepted G12/G13 answers - -**Alternatives.** Startup-import-only cannot update an existing realm. A realm -overwrite/database reset violates preserved-account upgrade requirements. General -declarative realm-management tools remain viable for Phase 11 production -provisioning; this small development-only operation instead owns an explicit -Admin REST field allowlist and its preservation tests without introducing a -second configuration-state tool. This is a maintenance responsibility, not a -claim that those tools cannot preserve unrelated state or are more expensive. - -For issuance, keeping the existing 1800s development value reduces refresh churn -but leaves a longer stale-scope window. The accepted 900s follows the existing -Keycloak README's production target while reducing that window for new tokens. -It is a selected development default, not a measured production capacity claim. -The API's 3600s rejection ceiling is not an issuance recommendation; BFF session -lifetimes are a different decision. - -| Gate part | Accepted answer | What acceptance does not close | -|---|---|---| -| G12: realm and reconciliation | One owned development Admin REST reconciler, reused by `make seed` and `make demo`, with the exact profile, identity/preservation and failure rules below | No production realm provisioning, runtime identity-provider port, membership service or browser session | -| G12: callbacks | Exact HTTPS Auth.js Keycloak callback on each existing seed host at port 3000; exact same-host root post-logout URI | No callback implementation, login transaction/session cookie, return-URL/CSRF policy or production domain registration | -| G13: access-token issuance lifetime | Security 11 owns the rule: the tenant development realm's configured access-token lifespan is 900s; `learnstack.json` owns its executable value and reconciliation enforces it without a conflicting client override. Actual timestamps follow the provider semantics below | BFF idle/absolute session life, refresh custody/serialization, CSRF and logout remain P02b-7; API's one-hour acceptance ceiling and 30s skew remain unchanged | - -**G13 authority follow-up — 2026-10-21.** Separately Accepted -[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) records -the issuance decision above, including inherited ID-token expiration and session -clamping. Security 11 remains the ongoing-rule owner. This adds no BFF session -lifetime or change to API acceptance. - -**Client and claim configuration.** Preserve the Accepted `learnstack-web` -confidential client with S256, `azp=learnstack-web` and `learnstack-api` resource -audience. Keep standard code flow; disable implicit flow, direct access grants -and service accounts on that client. The resource client's legacy service -account is not converted into a tenant user; its tokens still fail ADR-0064's -user profile. Disable the resource client's browser code flow and remove its -old localhost callback list; it does not act as a second login client. Preserve -its existing service credential. The API receives no client secret. - -Use one named default client scope, `learnstack-tenant-api`, attached to both -named clients. Its three scalar String user-attribute mappers emit `user_id`, -`tenant_id` and optional `organization_id` in access/ID tokens, without placing -those attributes in the user-info response. Its explicit audience mapper adds -`learnstack-api` to access tokens only. Preserve/declare actual built-in scopes, -especially `basic` and its `sub` mapper; do not replace all existing default or -optional scope assignments with a partial list. Reject another effective mapper -that can contradict the protected identity claims, rather than deleting an -unrecognized administrator customization. The API audience need not be exclusive; -standard account audiences do not grant application permission. - -Declare all three identity attributes single-valued, with admin-only view/edit, -including `organization_id`. Missing tenant/org attributes remain optional; -self-registration is not an actor-provisioning mechanism. Leave unrelated -profile attributes/groups and the existing unmanaged-attribute policy intact. -The disabled unmanaged policy is omitted/null in 26.6.2, not a `DISABLED` enum. -Legacy tenant roles and assignments remain inert authentication metadata; -P02b-5's complete role-authority census still forbids application permission from -them. No new application role, membership or implicit administrator is seeded. - -For each `SeedData` host the exact redirect is -`https://<seed-host>:3000/api/auth/callback/keycloak`; its post-logout URI is -`https://<seed-host>:3000/`. No localhost HTTP/wildcard callback, alternate host -or browser client secret is accepted for this BFF. Encode the two post-logout -values with Keycloak's supported multivalue representation. Retain manual hosts, -leaf certificate and trust setup. These registrations reserve P02b-7's callback -contract without claiming a browser login exists. - -**Identity preservation.** `SeedData` owns four stable, distinct, nonreserved -actor UUIDs and their tenant/org references. Keep the two existing English demo -usernames; add `demo-admin@tenant-b.test` and `demo-learner@tenant-b.test` for -Yoga with its existing default organization. These are development personas, -not application permission grants; their credentials use the existing -create-only development password convention. -The declaration/projection owns their exact usernames and UUIDs; the realm -export must agree with it. Do not derive actor identity from email, username or -Keycloak `sub`, or generate one on each reconciliation/login. - -- Preserve the Keycloak ID/`sub` of every existing account, including seed users. -- Create a missing named demo account with its declared development credential. - Never reset an existing password, credential, MFA factor, required action, - enabled state, email/name or role assignment to make a proof pass. -- On the two legacy English accounts only, accept the known old `tenant-a` - attribute as a named migration to their declared tenant UUID. Missing identity - values may be installed; semantically matching UUIDs are retained. Conflicting - nonempty actor/tenant/org values refuse, including an unexpected organization - on a tenant-wide English identity. No reassignment of a real UUID is guessed. -- Preserve unrelated user attributes through a read/merge/write operation. - Do not send only the three attributes: that can delete the others. -- Do not update nonmanifest accounts. Their missing actor/scope is not filled by - invention: the API continues to refuse an incomplete profile until Phase 03 - owns its durable mapping. Never modify `learnstack-hub` or master users/roles. - -**Client-secret continuity.** Add one private development source, -`KEYCLOAK_WEB_CLIENT_SECRET`, documented in `.env.example`. Fresh import and the -reconciler must agree with the selected value. Converting the old public client -installs that selected BFF secret once; any unused generated public-client -secret is not a previously consumed confidential contract. An already -confidential client's secret is verified and preserved; a mismatch fails without -rotation. A missing key in an older private environment is reported with setup -instructions, never silently filled or printed. P02b-7 receives only this BFF -credential, never the admin credential. Production secrets remain Phase 11's -provisioning responsibility. - -**TTL semantics.** Remove the named clients' `access.token.lifespan` overrides; -they inherit the realm's configured 900s value. Keycloak 26.6.2 sets `iat` and -calculates expiration from separate clock reads: crossing a second boundary can -yield `exp - iat == 901`, and a scheduling pause can widen it further. Do not -assert exact subtraction equality or substitute a fixed 901s ceiling. - -Check the exact realm value and absence of either client override independently. -For a fresh code exchange, record UTC and monotonic bounds around the request, -with its finite HTTP deadline, and require the signed expiration to lie within -that observed interval plus the configured lifespan. Any qualified fixture/ -provider clock tolerance is explicit, at most the existing 30s API clock skew; -an indeterminate clock/window fails the proof rather than widening the tolerance. -The measurement bound is test evidence, not a new production token-acceptance -rule. Separate session-clamping coverage permits shorter late-session issuance. -Exact configuration/override controls and independent wrong-expiration mutants -prevent timing tolerance from hiding a different configured lifespan. - -Changing the realm does not invalidate earlier -1800s tokens; they remain subject to the API acceptance bound. The reduced TTL -reduces the ordinary stale-scope window; 900s is the configured lifespan, not a -hard `exp - iat` guarantee. It does not implement immediate revocation, live -membership checks or refresh-token rotation. The latter's existing Phase 11 -owner is unchanged. - -### Reconciler ownership, failure and security boundaries - -The implementation is a closed tooling client under `scripts/`, using Node's -HTTP support rather than a new Keycloak SDK/application service. Both entry -points await it after successful application seed convergence and before API/web -launch or CI-owned Keycloak stop. Direct .NET Seeder remains application-data -only. The read-only identity projection never opens a data source. - -- Validate selected Compose project/service and pinned-image identity, loopback - development endpoint, exact realm discovery issuer and private source agreement - before admin authentication. Verify authenticated server version before writes. - Do not accept arbitrary realm, - URL, command, import file or destructive-reset CLI arguments. Test transport - injection stays internal and cannot widen the production CLI. -- Read the selected environment as data; inherited aliases cannot silently point - reconciliation at a different instance. Admin credentials, access tokens and - BFF secret stay in memory and the specifically owned tooling environment, - never argv, URLs, temp JSON, stdout/stderr, receipts or the API/public renderer - environment. The .NET Seeder keeps its existing credential allowlist. -- Use one local lock owner per selected target for both entry points; refuse a - second invocation rather than interleave. Hold through actual HTTP/child - cleanup. A stale lock is not removed merely because time elapsed. This is a - local tooling boundary, not a distributed lock against another checkout or - Admin Console. Concurrent external administration is unsupported: operators - run reconciliation while this development realm is otherwise quiescent. -- Read and validate the complete bounded change plan before the first write. - Detect conflicting users, scope/mappers, secret and unsupported configuration - up front. Apply only named owned fields/resources, merge unrelated data and - perform independent post-write readback. Never replay a full realm import, - drop a database, recreate a realm or delete existing accounts/scopes/roles. - - **Bounded replacement — 2026-10-22:** [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) - permits one qualified metadata preparation before a fresh full plan, after all - identity-independent prechecks. Every other Admin REST write remains ordinary - and requires that complete plan. Its implementation/proof remains pending. -- Bound each HTTP wait to 5s, ordinary decoded responses and every outbound body - to 256 KiB, and the complete reconciliation to 120s. Only the fixed authenticated - successful `GET /admin/serverinfo` read has the - [accepted 512 KiB allowance](#server-information-response-budget--proposal-2026-10-21). - Reject redirects on discovery, authentication and Admin - REST alike. No automatic token-request or mutation retry loop. - Creation conflicts permit one exact fresh-state check, not blind overwrite. - Abort/close the owned request and await cleanup before dropping the lock; - elapsed time is not evidence that a remote write failed. -- A partial/uncertain run exits nonzero. Previously completed mutations stay - durable; the next explicit run reads current state and resumes missing acts. - No cross-Keycloak/application transaction or automatic rollback is promised. - A completed third run performs zero mutating Admin REST calls. -- Errors emit a fixed stage/reason, never an upstream body/exception or arbitrary - claim/mapper/user values. Exercise credential/token/URL canaries and positive - closed diagnostics. No LearnStack audit row is added for development setup; - Keycloak retains its own administrative event mechanism. - -These choices deliberately trade broad realm-management convenience for safe -local convergence. A customized incompatible identity or confidential secret -requires explicit operator reconciliation. Existing nonmanifest users are -preserved but may lack the strict API profile. Admin credentials remain powerful -local setup credentials, never production runtime authority. A deadline can -leave a remotely committed partial update; a later run must verify it. - -### Test ownership and required controls - -Acceptance registers the following two canonical behavioural obligations in -Standards 21, with actual owners and **Registered** status until shipped. Their -sources are ADR-0004/0064, Security 11 and this accepted package, not a new -architecture decision. Counts/status assertions change with the same registry -edit; no new Implemented rule is claimed by approval. - -**Test-source follow-up — 2026-10-21.** ADR-0067's separate acceptance adds its -dedicated issuance authority to the existing issuance obligation's sources. -It introduces no new canonical obligation or test owner. The later Step 4 -delivery retains the two existing obligations' Implemented status; the original -registration paragraph above remains an acceptance-time receipt. - -| Canonical obligation | Owner/level | Required evidence | -|---|---|---| -| [`Tenant_Realm_Issuance_Matches_The_Api_Profile`](../standards/21-architecture-tests-catalogue.md#tenant_realm_issuance_matches_the_api_profile) | `TenantRealmIssuanceTests` and `TenantRealmProfileProtectionTests`, backend Integration with Docker | Import committed JSON into pinned Keycloak, exercise real code/S256 issuance, validate through real API handler/AccountSite and app-role PostgreSQL; protect profile attributes with a working account-edit positive control. | -| [`Development_Realm_Reconciliation_Preserves_Accounts`](../standards/21-architecture-tests-catalogue.md#development_realm_reconciliation_preserves_accounts) | `TenantRealmReconciliationTests`, backend Integration with Docker; Node tooling controls for bounded transport/process/CLI | Execute the actual shared reconciler against a pre-mapper warm realm; preserve users/credentials/IDs/unrelated data/Hub, converge protected mappers/attributes/TTL, and prove a third run has zero mutations. | - -Required controls include: - -- All four seed identities: real `sub`, fixed actor, expected tenant and Yoga org, - correct scalar JSON types, API audience/`azp`, RS256/purpose, exact configured - 900s lifespan and bounded fresh-issuance evidence under the TTL semantics above. - Compare export and issued values to typed `SeedData`, not duplicated test IDs. -- Exact registered callbacks on both seed hosts, missing/wrong secret, missing - challenge, plain challenge and missing/wrong verifier refusals; unregistered - redirect rejection, direct grant - still disabled, and ID tokens without API audience. The fixture consumes the - code callback without requiring the unimplemented BFF; it does not launch a - browser or bypass TLS validation to claim a browser cookie proof. -- Actual AccountSite 200 on both host classes with their real tokens, cross-tenant - and cross-organization refusal, claimless protected refusal, Hub-issuer refusal, - and the unchanged absent-token/public-IdP-down path. API/database reads stay - `learnstack_app`; Keycloak uses its own separate fixture database. -- Through the built-in account-console code/S256 flow for the same seed user, - prove an ordinary profile edit succeeds. Then try each protected attribute and - read it independently as admin: no user write or deletion succeeds. Admin-only - profile/account attribute visibility and registration attempts need their own - controls; deliberate token claims are not profile visibility. A - user-editable variant must make the protection proof fail. -- Removed/misattached identity/audience/basic mappers, duplicate/conflicting - identity mappers, wrong scalar types/UUIDs, writable profile attributes, ID-token - audience, client override and TTL drift all have planted dirty/clean controls. -- Warm legacy migration plus additional unrelated users/attributes/profile groups, - changed passwords, required actions, client scopes/roles, confidential secret - and Hub account state; exact snapshots remain preserved. Also cover an - incompatible managed identity, duplicate lookup, partial-write interruption, - failed readback, uncertain HTTP result, a race and zero-write completed rerun. -- Shared `make seed`/`make demo` wiring, target/env mismatch before writes, - secret leakage across child environments, timeout/cancellation/cleanup and - lock ownership; errors never turn into success or erase another owner's lock. - -The new fixture uses Keycloak 26.6.2 with its separate PostgreSQL database and -actual committed import. No ROPC shortcut or test-only mapper/client weakening -is made in the production realm. Every consuming class carries the Docker trait; -the source sweep must detect fixture references outside `Database/` too, with a -planted missing-trait control. Offline Node controls run in the existing meta -job; real provider cases enter ordinary Docker shards through normal discovery. -Preserve the seven required names, complete assignment and existing time ceilings. -Measure fixture/hosted costs; tune only within ADR-0063's accepted plan envelope. - -`Provider_SDK_Types_NotImportedOutsideInfrastructure` remains unimplemented: the -script introduces no runtime SDK type. Acceptance moves its owning-phase cell -from Phase 02b to Phase 03's first runtime identity-provider adapter, with actual -SDK introduction as the trigger. Phase 03 re-verifies that subject before its -first writer; a direct-HTTP implementation cannot be reported as SDK coverage. -The existing SDK exception rule remains enforced. This is the explicit handoff -required by this phase's enforcement scope, not missing P02b-6 work. - -### Four implementation steps after acceptance - -Each step ends in a clean local commit, then two fresh independent review-agent -rounds. Reviewers first run standards-check, then the security, correctness, -operation/lifecycle, testing and corpus lenses. Confirmed findings are reproduced, -fixed and committed before the next round/step. Fresh focused review verifies a -material correction after round two. Routine progress automatically proceeds; -a new architectural choice returns for maintainer approval. - -| Step | Deliverable | Validation before review/commit closure | -|---|---|---| -| 1 — executable realm and identity declaration | Register accepted gates/rules and current carriers; typed seed identity projection, complete import/profile/scopes/mapper/client configuration, private secret source and drift controls | JSON/schema/source and SeedData agreement; real fresh import/code-token smoke; unsafe mapper/profile/basic/TTL variants fail. No warm overwrite or BFF session claimed. | -| 2 — owned warm-realm reconciliation | Closed Admin REST tooling, explicit owned-field diff/merge/readback, preflight, secrets, locking and deadlines; actual fresh/warm/partial/no-op integration tests | Real pre-mapper PostgreSQL-backed Keycloak retains identities, passwords, unrelated state and Hub; conflict/timeout/uncertainty/race/canary controls; zero writes on completed third pass. | -| 3 — unified seed/demo lifecycle | Both existing entries call the same implementation after application seed; preserve exact configuration/credential/process ownership and CI's stopped-Keycloak public proof | Real fresh/warm `make seed` and repeated convergence; demo lifecycle wiring/proof, no foreign cleanup, private environments and bounded cancellation. Preserve public routes, API authentication and generated contract. | -| 4 — real identity/security qualification and closeout | Full production-token API/profile protection/mutation proofs, Docker fixture census, measured ordinary CI assignment, remaining mutable carriers and packet status | All relevant backend/frontend/meta suites; complete hosted PR qualification and unchanged required checks, public production demo regression. Account/registration positive and dirty controls prove the tests can fail. | - -Do not start the next feature packet as part of this work. P02b-7 retains Auth.js -session/callback implementation, custody/refresh/CSRF/logout and SDK bearer -transport. Phase 03 retains `User`/membership/permission/provisioning/mapping and -tenant switching; Phase 06 retains the full browser OIDC journey; Phase 11 retains -production realm provisioning, rotation and deployment identity hardening. - -### Acceptance carriers and implementation handoff - -The 2026-10-21 acceptance closes G12's realm/reconciliation/callback choices and -G13's issuance-TTL part with this anchor; G13's session portion stays Open. -The acceptance and Registered catalogue owners form the first commit before -runtime changes. Security 11 owns the issuance rule and points to the executable -value; target sketches link to that authority. Dated old observations retain -their as-of state. The implementation carriers below remain owned by their steps. - -**Issuance handoff follow-up — 2026-10-21.** Separately Accepted ADR-0067 is the -dedicated decision carrier for the issuance choice; Security 11's authority -header and the existing issuance obligation now cite it. This documentation -acceptance introduces no runtime work or change to the earlier approval, -G12's reconciler/callback boundary, or P02b-7's session ownership. - -| Carrier | Action and implementing owner | -|---|---| -| This phase, `CLAUDE.md`, roadmap README | Decision status, steps, source-bound evidence and the exact-equality TTL completion-criterion correction above; completed only after implementation/reviews/qualification. | -| `docs/standards/11-security.md`, architecture 13 | Distinguish issuance/acceptance/session TTL, scalar identity controls and current real-issuance boundary; Steps 1/4. | -| Standards 06/12/21 and integration/run-test skills | Keycloak container/trait, tooling secret/CLI boundaries, two named rules and explicit provider-SDK handoff; Steps 1/4. | -| `infra/keycloak/README.md`, Compose README and root README | Exact local client/callback/secret/migration and non-destructive warm setup; remove the database wipe as the upgrade recipe; Steps 1/3/4. | -| Realm JSON, `.env.example`, seed/demo and source/fixture controls | Apply only after acceptance; Steps 1–4. No Hub-realm edit. | -| Phase 03/11, architecture 14/30 and glossary | Explicit identity-provider handoff, consumer/production boundaries and updated terminology/status; Steps 1/4. | - -The maintainer explicitly approved the package as a whole on 2026-10-21: -900s development issuance, four stable seed identities/legacy migration, exact -callbacks, secret continuity/refusal, the bounded development-only reconciler -and the four implementation steps. The independent review and mechanical -validation receipts below qualify the reviewed proposal; they do not claim -runtime delivery or final-source hosted qualification. - -### Decision-pass inspection and review evidence - -Two independent read-only inspections used GPT-6.1 Sol at xhigh effort: one -covered the identity/profile/upstream boundary, the other covered reconciliation, -seed/demo and credential/lifecycle ownership. Their findings informed the -premise/action inventory above, including the demo bypass, real `basic` scope, -protected organization attribute and account-edit positive control. - -Isolated pinned-26.6.2 development-container feasibility probes confirmed the -profile component import, protected definitions, merged unrelated account data -and credential preservation, generated-once/retained client secrets and actual -`basic` attachment. A custom-scope-only variant lost built-in `basic`; the -corrected explicit definition restored its attachment. Form-based authorization -experiments did not complete successfully: no code-flow, token or TTL success -is claimed. Both owned containers and temporary imports were removed and their -absence independently checked. These experiments support the design, not a -committed regression suite or PostgreSQL/production qualification. - -**Review round 1.** Two new independent reviewers used GPT-6.1 Sol at xhigh -(security/correctness) and high (corpus/ownership) effort. Both approved the -current proposal for maintainer decision without a verified actionable finding. -They checked Accepted decision compatibility, G12/G13 vehicle and split, -Keycloak update/profile/scope/TTL source semantics, real protection controls, -client-secret continuity, bounded HTTP/lifecycle and the provider-SDK handoff. -This is document approval, not maintainer acceptance or implementation proof. - -**Review round 2 correction.** Fresh reviewers used GPT-6 Astra at xhigh -(boundary/security) and GPT-6.1 Sol at high (delivery/corpus) effort. The latter -approved; the boundary reviewer found the exact TTL assertion incompatible with -the pinned provider's separate clock reads. Independent source inspection -confirmed the counterexample: `iat` sampled at 1,000,999ms is 1000; expiration -sampled at 1,001,000ms plus 900s is 1901. This is a source-level control, not a -runtime reproduction. The gate, TTL contract, proof obligations and acceptance -carrier inventory now distinguish configured lifespan from measured issuance. -The old equality completion criterion is explicitly replaced at acceptance. -The original boundary reviewer and a fresh GPT-6.1 Sol xhigh reviewer independently -verified the correction and approved without another actionable finding. - -**Local document validation.** Five Release corpus-consistency cases and seven -ADR parser/lifecycle controls pass with zero failures/skips. All 757 relative -links/fragments in the five changed Markdown files resolve. Added prose wrapping, -whitespace and private-reference checks pass. Accepted ADRs and the complete -dated P02b-5 decision/delivery record remain unchanged. Runtime, real-token, -PostgreSQL, frontend and hosted qualification are not claimed by these checks. - -### Source references - -- [Keycloak import semantics](https://www.keycloak.org/server/importExport), - [Auth.js Keycloak callback/client guidance](https://authjs.dev/getting-started/providers/keycloak). -- Keycloak 26.6.2: - [default/basic scopes](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/OIDCLoginProtocolFactory.java), - [token issuance/expiration](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/TokenManager.java), - [issuance timestamp](https://github.com/keycloak/keycloak/blob/26.6.2/core/src/main/java/org/keycloak/representations/JsonWebToken.java#L140), - [clock reads](https://github.com/keycloak/keycloak/blob/26.6.2/common/src/main/java/org/keycloak/common/util/Time.java#L31), - [profile resource](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/UserProfileResource.java), - [user updates](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/UserResource.java), - [account REST](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java), - [built-in account client](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/managers/RealmManager.java). - -**Source-pointer correction — 2026-10-21.** The timestamp and clock links above -targeted the wrong raw-source lines. The actual pinned assignments are -[`JsonWebToken.java` lines 150–151](https://github.com/keycloak/keycloak/blob/26.6.2/core/src/main/java/org/keycloak/representations/JsonWebToken.java#L150-L151) -and [`Time.java` lines 33–34](https://github.com/keycloak/keycloak/blob/26.6.2/common/src/main/java/org/keycloak/common/util/Time.java#L33-L34). -The provider-semantics conclusion is unchanged; ADR-0067 carries the corrected -issuance/expiration and ID-token-expiration references. - -## P02b-6 Step 1 — executable realm and identity declaration (2026-10-21) - -**Status: complete locally; both independent review rounds and fix review pass.** -Acceptance is committed at `285db56b`; implementation stays on `development`. -This record claims no warm-realm reconciliation, BFF session or final-source CI -qualification. Both independent review rounds and their verified corrections -are complete. Step 2 starts next; final-source hosted qualification stays Step 4. - -- `SeedData.IdentityUsers` owns four fixed actor identities and their tenant/host - association. The read-only `--identity-manifest` mode projects scalar facts, - including the host's organization and the narrowly recognized legacy value, - without credentials, persistence access or membership creation. -- The tenant export defines the shared scalar-identity/access-only-audience scope, - actual pinned built-ins including `basic/sub`, protected admin-only profile - attributes, confidential code/S256 client, exact HTTPS callbacks and configured - 900s realm lifespan without named-client overrides. Hub export is unchanged. -- `.env.example` and Compose expose the selected server-only BFF secret source. - Existing confidential-secret verification and the refusal for an older private - file missing the key remain Step 2–3 work, before either entry invokes it. -- `TenantRealmExportTests` compares the committed artifact to typed SeedData and - initially rejects 24 planted mapper, profile, client, scope, identity and TTL - variants; round 1 extends this to 43 as recorded below. - The Docker fixture imports the actual JSON into pinned Keycloak with a separate - PostgreSQL database and owned HTTPS/custom-root trust, with hostname validation - retained. No host certificate store is changed. Real code/S256 issuance passes - for all four declared identities; complete API/profile protection stays Step 4. -- The existing Docker source census now covers `KeycloakFixture` and - `SharedKeycloakRealm` references outside `Database/`, with clean and missing-trait - controls. Existing catalogue counts are unchanged; both P02b-6 behavioural rules - stay Registered until their complete owners ship. - -**Current local validation.** Release solution build passes with zero warnings -and errors. Two export cases, seven corpus/Docker-census cases and seven ADR -parser controls and the existing demo-manifest case pass with zero skips. The -guarded frontend run passes all 1,699 cases across both packages with zero -skips/todos. Eleven actual Keycloak/PostgreSQL cases pass: all four signed token -profiles, live TTL and scope/client configuration, both exact callbacks, -missing/wrong secret and verifier, missing/plain challenge, unregistered redirect, -disabled password grant and correct/wrong/correct CA controls. Fresh expiration -uses the observed UTC/monotonic window with the explicit 2s fixture clock -tolerance; exact realm configuration is independently checked. Owned containers -and network are independently confirmed absent after the run. - -The fixture corrections retain normal provider behavior. Both realm imports use -the unambiguous byte-array/file mapping: the pinned Testcontainers string/string -overload interprets its target as a directory. Owned HTTPS resolves the pinned -provider's Secure loopback cookie behavior without a cookie-forwarding workaround -or changes to the production realm. Sources: -[Testcontainers 4.15.0 mapping](https://github.com/testcontainers/testcontainers-dotnet/blob/4.15.0/src/Testcontainers/Builders/ContainerBuilder%603.cs#L208-L223), -[Keycloak 26.6.2 secure context](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/utils/SecureContextResolver.java#L32-L55). - -**Review round 1.** Two fresh GPT-6.1 Sol reviewers used xhigh effort for -security/correctness and high effort for proof/lifecycle/corpus. The latter -found the new `identity-username` vocabulary kind absent from the existing G20 -completeness allowlist. The existing architecture case was independently run -and failed on that exact discrepancy. The correction includes every declared -username/actor in the completeness assertion and the decoded-literal controls. -It also removes stale PostgreSQL-only skill input descriptions and reconciles -the testing standard's population count. - -The security reviewer reproduced a separate offline export-predicate gap: -optional `sub`, `aud` and dotted identity destinations passed the previous -collision check. The committed realm is clean; no live provider vulnerability -was claimed. The correction checks decoded top-level claim roots, reserved token -setters, known implicit subject/audience writers and unknown effective mapper -types across direct, default and optional sources. Forty-three dirty variants and -an escaped-dot healthy control qualify the extended predicate. Pinned semantics: -[claim setters](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/OIDCAttributeMapperHelper.java#L295-L324), -[escaped claim paths](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/utils/JsonUtils.java#L35-L58). -**Round 1 fix validation.** Release solution/integration builds pass with zero -warnings/errors. The complete domain-genericity class plus corpus/Docker-census -controls pass 14 cases; export/manifest proofs pass three cases, including all -43 dirty variants and the escaped-dot healthy control. All have zero skips. -All 1,329 relative links/fragments in the twelve changed Markdown files resolve; -whitespace checks pass. - -**Review round 2.** Fresh GPT-6 Astra/xhigh and GPT-6.1 Sol/high reviewers -approved with four Minor corrections. The boundary reviewer independently -reproduced an offline drift gap: client-role `${client_id}` interpolation could -select an identity/reserved top-level destination. The guard now refuses a -dynamic claim root while preserving the fixed `resource_access` built-in shape. -Three dirty cases extend the total to 46; a healthy prefixed interpolation -control distinguishes the intended boundary from a blanket mapper refusal. -The current committed export was clean throughout; no live mutant consequence -is claimed. Source: -[pinned role mapper](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/AbstractUserRoleMappingMapper.java#L72-L106). - -The delivery reviewer identified stale Docker prerequisites, first-import client/ -persona inventory and live-phase status. Those descriptions now match the -delivered slice; the destructive warm-upgrade recipe is removed. A fresh -GPT-6.1 Sol/high focused review approves all corrections without another finding. -The two offline export cases pass with zero skips and a clean Release build; -all 1,344 links/fragments in thirteen changed Markdown files resolve before this -closeout addition. Whitespace checks pass. Existing eleven-case provider and -1,699-case frontend receipts above remain source-applicable; the second-round -correction changes only offline proof/docs, not provider configuration or code. - -## P02b-6 Step 2 — owned warm-realm reconciliation (2026-10-21) - -**Status: complete locally; both independent review rounds and fix review pass.** -Step 1 is closed at `95d0a0c8`. The shared development-only client, owned target/ -transport/lock boundaries and field planner are implemented locally. The first -actual complete-core provider run refused before writes at `version/body_limit`; -the accepted allowance and complete-core receipt below resolve that conflict. -The review/correction receipts below close Step 2. Entry-point activation -and final-source hosted qualification remain Steps 3–4. - -### Server-information response budget — proposal (2026-10-21) - -**Status: Accepted — 2026-10-21.** The maintainer approved the named 512 KiB -exception after the additional investigation below, recorded at `fbd9e7dd`. -The acceptance receipt below precedes dependent implementation. -This is a bounded adjustment to G12's accepted phase-package HTTP envelope, using -its existing decision vehicle. It changes no Accepted ADR, runtime identity -provider, credential, realm authority, mutation policy or application surface. - -**Observed conflict.** The original package requires an authenticated version check -before writes and caps every decoded HTTP response at 256 KiB. Pinned Keycloak's -`GET /admin/serverinfo` returns the full provider/mapper inventory along with the -version; its resource exposes no projection/filter parameter. The actual pinned -PostgreSQL-backed HTTPS fixture returns **292,707 decoded bytes** on each of two -authenticated reads, version `26.6.2`, identity encoding. The current production -client correctly refuses this response at the accepted cap. Source: -[pinned server information resource](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/info/ServerInfoAdminResource.java#L120-L169). - -**Accepted delta.** Only the fixed, authenticated, read-only -`GET /admin/serverinfo` exchange may consume at most **512 KiB decoded bytes**. -Every other response and every outbound body retains **256 KiB**. The 5s exchange -and 120s whole-pass deadlines, redirect/compression refusals, full JSON parsing, -exact version check and request/response cleanup remain unchanged. No caller, -configuration or CLI option can widen this budget or choose another endpoint. -Wrong version, malformed JSON, overflow or uncertainty still refuses before -the first mutation. The extra retained response allowance is at most 256 KiB for -one sequential read; it is not a general transport-limit increase. - -**Alternatives.** Keeping the universal cap with the current server-information -probe leaves this implementation unusable. The authenticated partial-export -alternative examined below can preserve that cap with a broader realm read. -Skipping version validation would weaken the selected target contract. -Parsing only a prefix and treating an aborted/truncated JSON response as success -would not independently validate the complete version document. A general 512 KiB -limit expands every exchange unnecessarily. A provider extension solely for a -version projection adds a custom deployment surface. The named read exception -preserves the stock provider and the other bounds. - -**Qualification.** The two measurement reads use a temporary, explicitly -measurement-only 1 MiB cap, owned HTTPS CA/hostname verification, 5s wait and no -redirects. Only byte count, exact version and encoding leave the probe. Its -temporary source is removed; this is feasibility evidence, not a committed -regression or authorization to change the client. Approval must precede the -dependent bound change. Committed controls must accept the actual document and -an exact 512 KiB document, reject a 512 KiB + 1 overflow, malformed/truncated JSON -and a wrong version before writes. Wrong method/path, unauthenticated/unsuccessful -reads and ordinary exchanges retain the 256 KiB refusal boundary independently. -The complete actual-core provider suite must pass after that implementation. - -**Proposal reviews.** Two fresh independent read-only reviewers, GPT-6 Astra at -xhigh effort and GPT-6.1 Sol at high effort, approve this proposal for maintainer -decision without a verified actionable finding. They confirm the endpoint's -authenticated inventory/no-projection source and G12's decision vehicle. The -security review also inspects 240 pinned resource/runtime source files without -finding a narrower authenticated version route. Neither reviewer reruns the -measurement or claims implementation/hosted qualification. The response-byte -allowance does not bound peak heap: retained chunks, concatenation, UTF-8 text -and parsed JSON add memory overhead. Acceptance was pending at that checkpoint. - -**Independent progress.** Sixty-five offline transport/target/lock controls pass -with zero skips in 10.162s. They cover actual HTTP deadline/body/redirect/abort -behavior, closed canary diagnostics, selected private-source agreement and local -exclusive ownership. They establish local request/response/socket cleanup before -settlement and separately bounded peer closure; neither claims remote rollback. -Actual field-planner diagnostics at this checkpoint remain separate from the -later complete-core receipt below. - -**Independent transport foundation.** The unused-by-entrypoints transport and -target/lock primitives are committed separately from the incomplete planner/core -and the proposed larger read. All their exchanges still enforce 256 KiB. A later -loopback refinement pins `localhost` lookup to IPv4 loopback while preserving the -issuer, HTTP Host and normal TLS hostname checks. Its actual HTTP control poisons -system DNS, observes the supplied lookup and socket address, and verifies the -unchanged localhost Host. The twenty transport cases pass in 10.141s with zero -skips; the unchanged forty-six target/lock controls above remain applicable. -This is an implementation checkpoint, not Step 2 review/qualification closure. - -### Additional version-source investigation (2026-10-21) - -The maintainer requested further research before accepting the proposed budget -change. At this research checkpoint the proposal remained unaccepted and code -still used the universal 256 KiB cap. These read-only experiments run against isolated -pinned PostgreSQL-backed HTTPS Keycloak, with owned CA/hostname validation and -no redirects. They do not qualify the unfinished whole reconciler. - -| Fixed version-source probe | HTTP result | Decoded bytes | Live version available | -|---|---|---:|---| -| `GET /admin/serverinfo` | 200 | 292,705 | `26.6.2` | -| Same GET with `fields=systemInfo.version` | 200 | 292,705 | `26.6.2`; no projection | -| Same GET with `briefRepresentation=true` | 200 | 292,704 | `26.6.2`; no projection | -| Same GET with `Range: bytes=0-262143` | 200, no Content-Range | 292,705 | `26.6.2`; range ignored | -| `HEAD /admin/serverinfo` | 200, no qualified version header | 0 | No | -| `POST /admin/realms/learnstack/partial-export?exportClients=false&exportGroupsAndRoles=false` | 200 | 44,655 | `26.6.2` | - -The four complete server-information documents use identity encoding and parse -successfully; their one-byte variation is consistent with dynamic scalar fields. -Earlier independent reads measured 292,707 bytes. Parsing takes 0.565–0.769ms in -this small sample. The partial export parses in 0.245ms. These are diagnostic -samples, not a latency comparison, capacity result or production percentile. -Only the oversized measurement reads use the temporary 1 MiB measurement cap; -the partial export succeeds through the unchanged 256 KiB client. - -**A genuine existing-budget alternative.** The fixed partial export is an -authenticated read: its route/export implementation has no configuration-write -or admin-event call, and it assigns `keycloakVersion` from the running JVM's -`Version.VERSION`, not imported realm metadata. Independent tenant realm/user/ -client/profile/credential and Hub snapshots remain identical after the actual -request. POST alone is not evidence of a mutation. Sources: -[route](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/RealmAdminResource.java#L1356-L1398), -[live version assignment](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/exportimport/util/ExportUtils.java#L84-L96), -[export and secret stripping](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java#L175-L183). - -False/false excludes users, client objects, role/group collections and service -accounts. It still returns realm authentication/configuration data: the measured -fixture contains 15 client scopes, 21 authentication flows, four authenticator -configurations, 14 required actions and 15 component entries. The export source -masks known secrets; this experiment has no positive credential-masking control -and does not claim the complete document is nonsensitive. Its aggregate size -depends on unrelated realm customization, which can exceed the existing cap. -Scope/mapper and client-policy growth are not wholly new dependencies: the -planner's existing scope-list read already includes all scopes and protocol -mappers, and its realm GET includes client policies. Additional export coupling -includes authentication flows/configurations, required actions, component trees, -localization, IdPs/mappers and scope-role mappings, aggregated into one bounded -document. Sources: -[scope-list projection](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/ClientScopesResource.java#L95-L100), -[scope and mapper projection](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java#L828-L841), -[shared realm/client-policy projection](https://github.com/keycloak/keycloak/blob/26.6.2/server-spi-private/src/main/java/org/keycloak/models/utils/ModelToRepresentation.java#L658-L674). -Using it would require a fixed semantic read classification in the zero-write -proofs; the current method-only test counter would misclassify that POST. - -**Other options.** `kcadm --fields` is client-side output filtering: the complete -HTTP body is copied and parsed before filtering, so it does not solve this -decoded-response limit. Source: -[pinned CLI filtering](https://github.com/keycloak/keycloak/blob/26.6.2/integration/client-cli/admin-cli/src/main/java/org/keycloak/client/admin/cli/commands/AbstractRequestCmd.java#L364-L384). -The Admin Console's resource-version value is not the live release-version -contract. Container `kc.sh --version` is supported but starts another JVM and -reports installed code, rather than an authenticated response from the running -HTTP process. Sources: -[console resource version](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java#L318-L353), -[resource-version reassignment](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/storage/database/jpa/QuarkusJpaConnectionProviderFactory.java#L119-L143), -[CLI version option](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/runtime/src/main/java/org/keycloak/quarkus/runtime/cli/command/Main.java#L57-L86), -[JVM launcher](https://github.com/keycloak/keycloak/blob/26.6.2/quarkus/dist/src/main/content/bin/kc.sh#L82-L162). -Prefix acceptance weakens complete-document validation; streaming the complete -body or compressing it does not reduce total decoded bytes. - -**Recommendation, not acceptance.** Prefer the fixed 512 KiB server-information -read because version qualification then remains independent of unrelated realm -authentication/configuration growth and avoids exporting that configuration for -a version check. The partial-export route is a viable alternative if retaining -256 KiB universally takes priority. No technical minimum requires 512 KiB: -320 KiB also fits the measured document, with approximately 34 KiB headroom; -512 KiB leaves approximately 226 KiB. This is a bounded headroom choice, not an -automatic expansion rule or a peak-memory guarantee. All other bounds and the -proposed falsifiable controls above remain unchanged. Server-information size -can itself grow with provider inventory; exceeding 512 KiB would still refuse -before writes and require a new explicit decision, not a larger automatic limit. - -All temporary source/scenarios/output and compiled diagnostic classes are -removed. Release integration builds pass with zero warnings/errors. Concrete -owned provider/database/Ryuk containers and networks are independently confirmed -absent. No configuration mutation, bound change or dependent activation is -performed by this investigation. - -### Server-information allowance acceptance (2026-10-21) - -The maintainer explicitly selects the named 512 KiB server-information exception, -after considering the viable 256 KiB partial-export alternative. Only a fixed -authenticated successful `GET /admin/serverinfo`, without query parameters or a -request body, can use it. All other responses and every outbound body remain at -256 KiB; the 5s/120s deadlines and existing failure/ownership boundaries remain. -There is no configurable limit, automatic fallback or partial-export activation. - -The acceptance commit updates this package and the current navigation carriers -before dependent code. At that checkpoint it claims no completed Step 2, -implemented exception or new provider/hosted proof. The exact-boundary, -negative-purpose and full provider -controls above remain mandatory; the approved two-review-round loop is unchanged. - -### Shared implementation and pre-review verification (2026-10-21) - -The shared core, field planner and closed launcher are implemented under -`scripts/`. Seed/demo activation remains Step 3; neither entry point invokes -this implementation yet. Step 2's two independent review rounds remain open at -this checkpoint; the local complete-provider receipt follows below. - -The launcher verifies the selected local Compose service, private-source -agreement and exact issuer before admin authentication, then verifies the live -version before planning. Its compiled Seeder identity projection receives only -the existing public tooling environment. A target-specific exclusive file lock -is held through actual owned HTTP/child cleanup; uncertain cleanup retains it. -The accepted response allowance above is implemented without a caller-selected -limit or broader transport change. - -The planner reads the complete bounded plan before applying owned field changes. -Missing named users use one fixed single-user `partialImport`, with -`ifResourceExists: FAIL`, their create-only credential and declared inert role. -It never replays a realm import or assigns a role/password to an existing user. -Independent readback covers preserved state as well as desired values; a fresh -post-apply plan must be empty. - -Actual-provider investigation and pinned-source inspection corrected these -preservation details before review: - -- A profile can project email into username. Census and exact username lookup - must agree on the declared name and provider ID before treating a user as - present or missing. The conflicting imported case refuses before any write. -- Client attributes merge on PUT. Removing the token-lifespan override requires - an explicit null tombstone, rather than omission. Other attributes are retained. -- Client PUT can derive origins, disable authorization services or change service - accounts. Requests explicitly retain the declared origin list and existing - authorization state while omitting unchanged service-account flags. Incompatible - service-account transitions/cleanup refuse before writes; scope assignments - receive exact merged-state readback. -- A needed client PUT refuses existing expiry/rotated-secret metadata that the - provider would discard. Ordinary secret creation time is preserved. Existing - credentials are not rotated to force convergence. - -The offline provider double now models these pinned merge/default/cleanup -semantics. Dirty omission/tombstone controls must fail independent readback; -successful repetitions are not a substitute for the first pass's verification. -The five Node control files pass **122 cases, zero failures/skips**, in 10.210s. -They cover exact response boundaries and negative purposes, real HTTP cleanup/ -deadlines, credential canaries, target/source/lock refusals, complete preflight, -preservation, 409 checks, partial progress and the closed production CLI. -Syntax and whitespace checks pass. No final-source hosted proof is claimed here. - -**Complete actual-core provider receipt.** All four -`TenantRealmReconciliationTests` cases pass with zero failures/skips in 1.7384min -against isolated PostgreSQL-backed HTTPS Keycloak 26.6.2. The actual shared -transport/core uses the accepted allowance without a version projection, cap -override or diagnostic code. The TRX SHA-256 is -`02ffba155dcf5662ed7a7db6e15a849cd9f631f1c63830a93f3973189cc08b77`. - -The controlled warm import preserves provider IDs, changed passwords, MFA, -disabled state, required actions, role assignments, nonmanifest accounts, -unrelated profile/client data, the API service credential/resource-server -settings and the Hub realm. A deliberately removed service-account scope stays -removed; both clients retain empty web origins. Actual code/S256 logins witness -old/new credential continuity and strict signed identity claims. Second/third -completed passes perform zero mutating Admin REST calls. - -The acknowledgement-loss control injects refusal after one real successful -response closes; it does not claim packet loss or remote rollback. Cancellation -and failed readback require explicit verified reruns. Planted identity, mapper, -secret, duplicate and username-projection conflicts refuse before any write even -with a legitimate TTL change pending. Local lock/HTTP race/deadline boundaries -are established by the separate actual-resource Node controls above. - -Account preservation compares exact full stored-account details resolved through -their provider IDs. The intentionally changed global user-profile metadata is -verified separately; including it in an account's preservation baseline would -mistake the owned profile change for a stored-account mutation. All temporary -diagnostic source is removed before the passing complete run. Formal independent -Step 2 review rounds have not yet started. Destruction events and independent -post-run inventories confirm all five owned provider/database pairs, Ryuk and -five networks are gone; foreign resources are untouched. -Fourteen Release corpus, domain-genericity and Docker-trait controls pass with -zero failures/skips in 13s; the changed-file link/fragment audit has zero broken -targets. The scoped C# whitespace verification passes. - -#### Step 2 review round 1 — identity visibility and plan feasibility - -Two fresh independent reviewers inspected the complete committed Step 2 change -through `3776947e`, its callers, accepted contract and pinned provider source. -Both identified a blocking identity-preservation defect: Admin user reads are -profile projections. A missing definition with a disabled unmanaged policy can -hide a stored conflicting actor; the planner had treated it as absent. One -reviewer also reproduced projected inventory/body limits being exceeded only -after an earlier mutation had committed. These findings supersede the initial -local proof's coverage claim for those states; its warm fixture explicitly -enabled unmanaged attributes and did not exercise hidden stored values. - -The actual PostgreSQL-backed Keycloak reproduction performed six writes and -changed the hidden actor before refusing at readback. The corrected planner -qualifies protected attribute visibility before account reads or writes. Hidden, -defaulted, selected or otherwise unqualified identity projections refuse with -`plan/identity_conflict`; it does not write profile settings to reveal conflicts. -The duplicate-actor census also refuses external user-storage projections that -can override realm metadata. Safe explicit admin-readable policies remain -supported, and reconciliation retains the existing unmanaged policy. - -**Remedy follow-up — 2026-10-22:** The preceding no-profile-write result describes -that shipped correction. Accepted [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) -now authorizes the separately bounded preparation remedy after independent -preconditions, without widening unmanaged policy or rewriting this evidence. -Its automatic path remains pending implementation and proof. - -Every static mutation body is checked in the complete read-only plan against -the existing 256 KiB UTF-8 limit. Projected collection and account counts must -fit the same readers used during independent verification and a later run. -The additional byte-feasibility check covers growing response inventories too: -a small valid write must not knowingly make the next scope/user read too large. -Full user listings repeat profile metadata, and inserted accounts can move page -boundaries. Conservative byte accounting can refuse before a count ceiling; -the ceilings do not promise every combined configuration will fit. Transport -and independent readback checks remain backstops. Boundary controls prove -supported states still converge, while excess states refuse with zero writes -even when another legitimate change is pending. - -The identity correction's source-frozen actual-provider class passes **eight -cases, zero failures/skips**, in 2.8699min. Four new cases cover hidden unmanaged -identities, managed identities hidden from administrators, and explicit identity -defaults or selectors. Each refuses before the pending TTL write; an independently -captured snapshot is unchanged, and test-owned post-outcome visibility inspection -proves the stored actor was retained. Existing fresh/warm, credential, partial -progress and zero-write rerun proofs still pass. The TRX SHA-256 is -`1e7206d44e2dc4db21f0e78ef1d02dd2f8c6bd76dd7dbd6693a9b212f200b620`. -The five Node files passed **130 cases, zero failures/skips** at that checkpoint. -After the response-feasibility refinement they pass **133 cases, zero -failures/skips**, in 10.18s, including capped user/scope responses, repeated -profile metadata and a missing metadata-template control. A final-source provider -rerun remains required for Step 2 closeout. Scoped whitespace and diff checks -pass. Independent post-run inventories show no owned provider -containers or networks; the bounded Docker event history lacks one older -destruction event, so it is not claimed as a complete event receipt. Foreign -resources remain untouched. The second fresh independent review is still due -at this checkpoint. - -#### Step 2 review round 2 — derived metadata and inherited identity sources - -Two new independent reviewers inspected `95d0a0c8..29735c78`. Both independently -ran all 133 offline controls with zero failures/skips and identified a false -preservation refusal: intended profile changes alter the derived -`userProfileMetadata` in unrelated-account listings. The earlier warm test's -first two interrupted passes had already applied the profile change before its -successful resumed pass, masking uninterrupted convergence. Actual-provider -confirmation performed eleven writes, retained every independently inspected -account field/actor/credential/role, then falsely refused at readback; the next -explicit pass had zero pending writes. Account-field comparisons remain strict; -only this derived metadata is separated from them, with global profile -configuration still checked independently. - -One reviewer additionally proved that an existing protected mapper's -`aggregate.attrs=true` survived planning and independent verification. Actual -code/S256 exchanges confirmed both defects: aggregation produced the group's -actor instead of the stored actor, while the canonical nonaggregating mapper -inherited an unexpected organization when the user's field was absent. Both -unsafe reconciliations had incorrectly succeeded with zero writes. The token -signatures were independently validated; no credential or token value entered -diagnostics. - -The correction rejects protected aggregation instead of silently repairing the -administrator's setting. A bounded full ordinary-group inventory includes -nested groups and validates parent closure, count and protected attributes. -Each censused account's membership IDs are read without `search`, `first` or -`max`, following the mapper's no-argument group stream rather than selecting a -different paginated branch. Unknown/nonordinary memberships refuse before -writes. The first actual-provider run disproved an initial fixture assumption: -the pinned cached model filters out Keycloak Organization groups even after -the feature is disabled; an enabled organization-member API read confirms the -retained association independently. The corrected fixture must qualify actual -strict token identity, rather than claim an unobserved group fallback. A -separate same-fixture query control found that `search=` is injected as absent -and lists only the parent: two stored ordinary groups produced one result. A -nonempty encoded-space search selects the pinned all-group branch before its -trim, returning both parent and child with complete ancestry. Safe unrelated -groups and memberships remain unchanged. All existing HTTP/count/pass budgets remain -in force; no group, membership or feature-setting write is introduced. - -The fixed single-user import uses the pinned `addUser(false, false)` path and -does not inherit realm default roles or groups. Independent readback requires -each new account's membership set to be empty; unrelated default-group settings -remain preserved. This qualification concerns provider claim sources, not -LearnStack organization membership or application permission. - -**Correction qualification.** The final unchanged-source actual-provider class -passes **13/13 cases, zero failures/skips**, in 4.4234 test minutes (292s including -the owned build/lifecycle wrapper). This local run uses Debug; complete final -Release/hosted qualification remains Step 4. All 23 runtime/test input hashes -match before/after the run and independently match the current source. The TRX -SHA-256 is `ead5c9ed7fb89428afc223664b5bb5a68aabd309b4d6ffe0656d3b7443f97e29`. -Live lifecycle capture binds every one of 14 Keycloak/PostgreSQL pairs, Ryuk and -14 networks to creation/destruction; no owned resource remains, and the foreign -database is retained. The cached-organization control verifies a genuine -member and protected canaries through the enabled organization API, issues a -fresh signed token from a pre-existing code/S256 session while enabled, and -checks a fresh code/S256 token after disabling. Original identity is retained; -test-owned post-result visibility restoration verifies stored organization -attributes and membership unchanged. - -The root independently reruns **142 offline cases, zero failures/skips**, in -10.149s, including the faithful empty-search/descendant control. Scoped syntax, -whitespace/diff, seven ADR parser controls and 1,347 relative links/fragments -across thirteen changed Markdown files pass. The correction is committed at -`b94f6a24`. Two new independent reviewers, GPT-6 Astra and GPT-6.1 Sol at xhigh -effort, approve the bounded correction without a verified actionable finding. -Both independently rerun all 142 offline controls and verify the 13-case TRX and -23 source hashes against the commit. They inspect the real-source group/cache -branches and preservation controls; neither reruns .NET or Docker. Both formal -review rounds, their verified fixes and fresh correction verification are closed. -Step 3's shared seed/demo wiring starts next; Step 4 retains final qualification. - - - -### Account-console self-service capability — proposal (2026-10-21) - -**Status: Accepted — 2026-10-21.** The maintainer explicitly approved the narrow -capability/mapper package after its two independent reviews and actual-provider -counterfactuals. The reviewed proposal is recorded at `2ef1e148`; subsequent -wrapping corrections do not change its policy. G12's existing phase-package -vehicle owns this bounded adjustment; it introduces no new application -authorization decision or ADR. Dependent implementation remains Step 4 work. -Steps 2–3 can close independently; Step 4's same-seed account-edit proof depends -on resolving this conflict. - -**Verified conflict.** The committed seed users have only their declared inert -realm role. The pinned importer calls `addUser(false, false)`, so it does not -assign Keycloak's default-role composite. An unchanged, PostgreSQL-backed fresh -import completes the built-in `account-console` code/S256 flow and token exchange -with HTTP 200, but authenticated Account REST GET and ordinary-profile POST both -return **401**. Independent effective-role readback finds zero `account` client -roles; `manage-account` and `view-profile` are absent. The built-in console has -zero default client scopes, so the measurement requests only `openid`; it changes -no client, mapper, profile or role. No successful account edit or profile -protection is claimed from these refusals. The temporary measurement is removed -from the committed regression source; its focused run passes three measured -cases with zero skips. TRX SHA-256: -`5ff77dff45f09941046d7e42b3cef57cc29bc5839d57aba5fb9ec457172601fb`. - -**Exact existing constraint.** The accepted Identity preservation clause says: - -> Never reset an existing password, credential, MFA factor, required action, -> enabled state, email/name or role assignment to make a proof pass. - -It also requires an ordinary account-console edit for the same seed user. The -current import cannot satisfy that positive control. A test-only role grant -would qualify a different setup and cannot substitute for delivered behavior. -The proposal changes only the role-assignment part of that constraint for the -named self-service capability below. All other preservation rules remain. - -**Accepted delta.** Declare the built-in `account` client's `manage-account` -role for exactly the four managed development personas. Fresh import and the -single-user create-only import include it. Warm reconciliation adds that exact -mapping only when the capability is missing; it never removes or replaces a -prior mapping. Before any mutation, qualify the built-in client/role identity -and its bounded composite closure: only the stock `manage-account-links` child, -with no realm role or foreign client role. Incompatible administrator -customization refuses rather than editing role definitions or composites. -Already effective capability needs no new mapping. Independent readback checks -both the capability and every original mapping; a completed rerun writes zero. - -The console also needs an account-role claim emitter. Its existing audience -resolver alone does not populate `resource_access.account.roles`; Account REST -checks that field even after its configured introspection fallback. Add one -supported stock client-role mapper directly to the built-in `account-console`, -with a fixed `account` client ID and fixed `resource_access.account.roles` claim. -It emits a String array only in access/introspection tokens, with no role prefix, -ID-token, user-info or lightweight-token emission. Do not attach the broader -`roles` scope or add a realm/all-client role emitter. Retain the console's stock -S256, audience resolver and `fullScopeAllowed=false` settings. - -Before writes, qualify the console's direct/default/optional scope role allowance -and expanded composite closure within the stock account set: `manage-account`, -`manage-account-links` and `view-groups`. The last role remains an allowed stock -scope mapping, not a new user grant. Refuse a wider/customized role allowance or -an effective conflicting emitter/role-transforming mapper, without changing it. -A compatible existing fixed-account emitter needs no duplicate. Preserve all -compatible prior client settings, callbacks, scopes and mapper IDs; independent -readback verifies the exact intended addition and unchanged baseline. - -**Bounded replacement — 2026-10-22:** [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) -permits only the three independently qualified stock-console assignment -detachments; customized graphs still refuse and compatible graphs retain priority. -This adds assignment-only DELETE authority, not deletion of global resources. -Implementation and automatic-path proof remain pending. - -No realm-wide default-role assignment, group inheritance, unrelated account-data -or grant change, Hub/master mutation, new application role or membership is -introduced. -The API continues to ignore all role claims for application authorization. -Existing disabled state, MFA, required actions, passwords and account IDs remain -unchanged; this capability does not make a disabled or action-blocked user able -to log in. The protected profile definitions and BFF callback/client boundaries -remain unchanged. The built-in account-console keeps its existing S256 and -audience machinery; the new mapper carries only its resolved account roles. - -**Cost and alternatives.** `manage-account` is Keycloak's standard owner -self-service capability, not a profile-field-only permission. It includes -credential management and, through its stock composite, linked-account -management for that user's own provider account. This explicitly increases the -four warm personas' provider capability and may add the standard account -audience/role claims to their tokens; it grants no LearnStack permission. The -console mapper belongs to a shared client: it can also restore account-console -access for nonmanifest users who already hold eligible account roles. Their -records and grants stay unchanged. The four-persona restriction bounds new role -grants, rather than every effect of the shared client configuration. -Preserving the current mappings without this addition leaves those personas -unable to use standard account self-service. Manual grants leave a nonconvergent -setup prerequisite. Granting the realm default composite can include unrelated -administrator additions; granting every account or changing role definitions -exceeds this narrow need. Replacing the required positive with a generic 401/403 -would leave attribute protection unproved. - -**Implementation and proof owner.** After acceptance, Step 4 updates the typed -identity declaration/export agreement, the planner's explicit role/client diff -and readback, create-only import, Keycloak README and catalogue assertions. Tests -cover unchanged-import refusal before the change, actual same-seed ordinary edit -after it, protected writes/deletions/visibility with independent admin readback, -fresh/warm exact capability and console mapper, original mappings retained, -shared-client behavior for an already eligible nonmanifest user without a new -grant, no unrelated account-data or Hub changes, zero-write reruns and unsafe -role/scope/mapper customization refusing before writes. The existing actual -warm-provider suite must pass against that final source. No fixture-only role -grant may provide the passing baseline. - -**Sources.** Pinned Keycloak 26.6.2 -[importer](https://github.com/keycloak/keycloak/blob/26.6.2/model/storage-private/src/main/java/org/keycloak/storage/datastore/DefaultExportImportManager.java#L978-L1035), -[default-role admission](https://github.com/keycloak/keycloak/blob/26.6.2/model/jpa/src/main/java/org/keycloak/models/jpa/JpaUserProvider.java#L103-L133), -[built-in account/console setup](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/managers/RealmManager.java#L470-L535) -and [Account REST requirements](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/services/resources/account/AccountRestService.java#L126-L156). - -**Proposal qualification.** Two independent source/corpus reviews correctly found -that the first role-only recipe omitted the console's role-claim carrier. The -revised fixed-account mapper is qualified by an isolated actual-provider -counterfactual: a fresh code/S256 exchange is HTTP 200 at each stage; the -unchanged user's Account GET/POST are 401, the role-only variant returns 403, -and the role-plus-mapper variant returns GET 200 and ordinary-edit POST 204. -Independent admin readback confirms the changed ordinary field. A combined -protected-attribute replacement returns 400; a deletion request returns 204 -while preserving both stored protected values and the absent organization -field. These are feasibility observations, not complete three-field/profile/ -registration proofs. Default and optional console scopes remain empty. A -whole-client JSON comparison includes the new mapper and is not evidence of -unchanged client settings; exact preservation remains an implementation -obligation. The temporary variant is removed and makes no production change. -The single-case TRX SHA-256 is -`b3d57aecb27543e3c97f6537c75e259fc6d554c858b6fb4844f4a99617424d09`. -The lifecycle receipt confirms the one owned Keycloak/PostgreSQL/Ryuk/network -set is removed and the foreign database retained. No fixture-only grant is a -production or protection baseline. The selected mapper uses Keycloak's supported -[fixed-client role mapper](https://github.com/keycloak/keycloak/blob/26.6.2/services/src/main/java/org/keycloak/protocol/oidc/mappers/UserClientRoleMappingMapper.java) -and typed resource-access projection. The independent protection proofs remain -Step 4 obligations after any accepted implementation. - -Two independent reviewers, GPT-6 Astra and GPT-6.1 Sol at xhigh effort, approve -the revised package for maintainer decision without a remaining actionable -design finding. Their review verifies the recorded counterfactuals, bounded -capability/mapper ownership and disclosure; it grants no implementation approval. -They do not claim present-tree parity with the experiment while independent -Step 3 entry-point changes proceed. Scoped prose wrapping and link checks pass. - - -## P02b-6 Step 3 — shared seed/demo lifecycle (2026-10-21) - -**Status: complete locally after both independent review rounds, verified fixes -and fresh correction reviews.** Work stays on `development`. Step 2 -is closed at `b94f6a24`; the account-console adjustment above is Accepted and -retains Step 4 implementation ownership. - -- `seed.sh` checks selected/ambient database agreement and the application role, - then performs read-only private realm preflight before stack/migration work. - `seed.mjs` owns the confined Compose prerequisite, selected stack startup, - PostgreSQL readiness and migration, then full readiness, a fresh Release Seeder - build, its argument-free DLL with only the app credential, and the awaited - shared realm reconciliation. -- The demo performs old-private-file preflight before preparation or commands. - It awaits the same reconciler with the exact selected project/file/mode and - signal after application seed, before CI stops Keycloak or starts API/web. -- Build/setup children receive credential-free prerequisites. Migration keeps - only its own credential and explicit selected-stack metadata; API, public web - and Seeder environments do not receive private admin/BFF credentials. Fixed - diagnostics share the missing-secret setup instruction; no existing private - file is silently filled and no old-password promise is printed. -- Parent cancellation joins the shared operation and owned command cleanup. - Local data stays retained; CI's own teardown and stopped-Keycloak public proof - remain part of the shared lifecycle. - -**Local validation.** The three focused lifecycle/source files pass 142 cases -with zero failures/skips/todos; their actual JSON report passes the repository's -validator. The complete guarded frontend run passes **1,722 cases in two -packages, zero skips/todos**. Workspace typecheck/lint and 142 separate realm Node -controls pass. Seventeen relevant Release architecture/corpus/Seeder/Docker-trait -controls pass with zero skips; the Release build reports no compiler warning or -error. Syntax, Bash parsing and scoped diff checks pass. These checks establish -local wiring and source controls, not actual Compose convergence, product -browser behavior, final-source hosted CI or a BFF session. - -#### Step 3 review round one - -Two fresh independent reviewers inspected `2ef1e148..ce05931e` through the -standards, security/lifecycle and testing/corpus lenses: `gpt-6-astra` at `xhigh` -and `gpt-6.1-sol` at `xhigh`. No verified runtime, security or proof-correctness -finding remained. The testing/corpus reviewer identified five over-width prose -locations in the realm guide, catalogue, seed skill and root README. They are -wrapped without changing the contract. The security reviewer independently ran -all 142 realm Node controls with zero failures, cancellations, skips or todos. -The actual seed/demo owner remains separate from both reviewers; no offline -receipt substitutes for its pending lifecycle qualification. - -#### Step 3 review round two and credential correction - -Two new independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at `xhigh`, inspect -`2ef1e148..9b51a0bc`. The proofs/corpus reviewer independently passes all 142 -focused frontend cases with zero skips/todos and validates the actual report. -The security reviewer independently passes all 142 realm Node controls, then -reproduces a credential-confinement defect through an actual copied `make seed`: -the unchanged Makefile prerequisites run before the new Node owner, so matching -inherited Keycloak admin/BFF secrets reach migration restore, build and EF -children. Synthetic credentials and command stubs expose only presence flags; -no Docker or .NET process is required to falsify the confinement claim. - -The correction moves `dev`, PostgreSQL wait and `migrate` into the seed process -owner with selected project/file/mode and only the migration credential. The -Docker-version prerequisite is also owned and receives no private credential. -Compose child environments retain only fixed Docker process prerequisites, so -unrelated inherited application/BFF secrets cannot reach readiness or target -inspection. The existing general migration target and its explicit database -connection argument remain unchanged; the no-argument claim concerns the -application Seeder DLL, not every descendant of `make migrate`. -The actual Makefile regression passes and its planted old-prerequisite variant -fails the same confinement predicate. Selected Docker context/socket/config, -database credentials, private-source continuity and unchanged files are checked -independently across stack, migration and readiness. No real Docker or .NET -execution is claimed from these executable stubs. The two focused changed test -files pass 134 cases; the full guarded frontend run passes 1,728 cases in two -packages with zero skips/todos. Typecheck, targeted lint, 142 realm Node controls, -ADR parser and link checks pass. Fresh correction review and a corrected-source -actual seed run remain pending. Earlier actual seed evidence is bound to -`ce05931e` and requires that new run for this corrected entry path. - -#### Step 3 actual lifecycle evidence before the credential correction - -An isolated clone on `development` at `ce05931e` runs the actual entries without -reading the root checkout's private files or foreign working directories. -`make seed` completes a fresh import with zero realm writes. An owned warm-only -change sets TTL to 1800 and detaches the managed API scope from both named -clients; the next seed performs three writes and independently restores TTL 900 -and both scopes. The third pass performs zero writes. Four-user account-state, -client-ID and Hub digests remain identical. These are bounded drift controls, -not a substitute for Step 2's pre-mapper/profile upgrade proof. - -The clean-clone CI demo completes in 650.4 seconds with Keycloak stopped before -the public API/web proof: nine browser navigations, 24 visibility controls and -27 of 27 audits, with all 27 JSON/HTML report pairs and nine screenshots. All -reports share invocation, commit `ce05931e` and tree -`f446d80096bf3a8119553182df3c1629996b85b4`. All 134 API completions are HTTP 200, -with no malformed or pending output. TLS refusal and timeout controls pass. -Cleanup completes in 10.73 seconds; independent exact-project checks find zero -containers, networks or volumes. Private files, environment and lock are removed; -the unrelated database remains running and tracked clone source remains clean. -This receipt qualifies the named source, not the subsequent credential fix or -Step 4's final PR head. Final-source production demo/hosted qualification remains -Step 4 work. - -#### Step 3 correction review and single readiness owner - -Two fresh independent correction inspections, `gpt-6-astra` and `gpt-6.1-sol` at -`xhigh`, inspect the credential fix at `29bb18df`. Both independently reproduce -an additional cancellation defect: the nested `make wait-postgres` CLI creates -its own detached Docker command owner. Outer and inner two-second escalation -can race, killing the inner owner before it kills Docker. Synthetic Docker -commands continue heartbeating after the outer seed reports cancellation and -completed cleanup. Each probe cleans only its recorded owned groups. - -The correction keeps PostgreSQL readiness directly in the seed's existing -`DemoProcesses` owner: selected `make dev`, direct PostgreSQL readiness, selected -`make migrate`, then full readiness. Stack startup receives no migration -credential; only migration receives it. Increasing a teardown timeout or a -successful happy-path run does not substitute for that ownership change. -The proof reviewer also exposes the actual-Makefile regression's default -five-second test allowance under contention: the combined run passes 147 of -148 cases, while its isolated rerun passes in 3.84 seconds. Its two bounded -subprocess runs require an explicit test allowance. - -The updated two-file focused run passes 136 cases. Actual copied seed/process/ -Makefile/readiness sources now prove cancellation and deadline cleanup with a -TERM-ignoring synthetic Docker command and a 300ms post-return heartbeat check. -The checked nested-readiness mutation fails the same survival predicate in both -cases. Only the nested fixture's cleanup is delayed to expose that competing -owner deterministically; the clean owner retains the native stop helper and -canonical readiness budget. Deadline shortening is internal to the test driver. -Fixture retirement guards never re-probe or signal a handle after observed -absence. The actual-Makefile case has a finite 45-second allowance; each cleanup -case has 30 seconds and bounded child drivers. No Docker or .NET behavior is -inferred from executable stubs. Full guarded frontend validation passes 1,730 -cases in two packages with zero skips/todos; typecheck, targeted lint, 142 Node -controls and link checks pass. Fresh correction review and actual replay on this -single-owner source remain pending. - -A separate isolated actual replay at `29bb18df` again completes fresh, warm and -third seed passes with **0 / 3 / 0 realm writes**. Independent readback restores -TTL 900 and both scopes while retaining account, client-ID and Hub digests. All -three closed logs have zero generated-secret matches. Exact-project teardown -finds zero containers, networks or volumes, removes only the owned environment -and retains the unrelated database. That replay predates the single-owner -readiness correction and does not prove its cancellation behavior. - -#### Step 3 final correction verification and local closeout - -Two further fresh independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at -`xhigh`, inspect the complete Step 3 source through `1f5cc04e`, including the -single-owner correction. Each independently passes all 31 realm-lifecycle -cases. No production lifecycle or credential-confinement finding remains. -The proof reviewer identifies one Minor in the fixture observer: saved tracked -group IDs are probed again after the native helper observed absence. The fixture -now retains that native ESRCH witness and refuses a later probe/signal through a -retired handle; both observation samples consult it. The same reviewer verifies -the correction with no remaining actionable finding. Production source is -unchanged. The corrected file independently passes all 31 cases with its actual -JSON accepted by the repository report validator; targeted lint and formatting -pass. The latest complete guarded run passes 1,730 cases with zero skips/todos. - -The final actual replay uses runtime commit `1f5cc04e` and tree -`62a27504adfeeaae32ca1dad60abcb213b5b0dff`: fresh seed writes zero in 35.66 -seconds, the owned TTL/two-scope drift repairs three in 14.82 seconds, and the -third run writes zero in 14.38 seconds. All exits are zero with no timeout or -generated-secret match. Independent readbacks retain all four account -projections and the user/client-ID/Hub digests. Exact-project cleanup completes -in 10.49 seconds with zero containers/networks/volumes; the unrelated database -remains running. Only the hash-matching owned private environment is removed; -the isolated `development` clone remains clean. The receipt SHA-256 is -`adf46a23598adc7e116210d5925cdcc283d03cdad2d76a2bde5fe2c1ade6732e`. -The subsequent fixture-observer correction changes no runtime qualification -input. Step 3 closes locally. Step 4 retains the approved account-console delta, -actual API/profile/registration qualification, final-source production demo and -complete hosted CI; this closeout claims neither a BFF session nor packet merge. - - -## P02b-6 Step 4 — real identity qualification and closeout (2026-10-21) - -**Status: implementation and independent reviews complete; the PR checks own -final-head qualification.** Work stays on `development`. Steps 1–3 are complete locally; -their source-bound receipts -above retain their limits. The maintainer approved the narrow account-console -capability and mapper adjustment above. No further decision approval is pending. - -Three implementation areas proceed together: the declared four-persona -self-service capability and non-destructive warm reconciliation; actual account -and registration protection with independent stored-state observations; and -real provider credentials through the production API boundary and PostgreSQL. -The API proof retains the existing physical read-only/application-role witness; -it supplies neither alternate claims nor a replacement token validator. - -Fresh import declares both stock account clients, their stock role/scope -baseline and only the approved account mapper/persona-grant additions. Actual -provider comparison against automatic stock bootstrap remains required before -claiming that parity. Warm reconciliation qualifies the existing builtin -configuration before any write and preserves unrelated mappings and identities. - -Offline transport/ownership/convergence controls enter the existing meta job -with pinned Node setup. Each named test file must produce a fresh, nonempty -JUnit report with actual named cases, zero failures and zero skips/todos. The -exact report gate passes its positive control and refuses planted empty-file, -failed, skipped and todo cases. Seven required check names, execution topology -and existing job ceilings remain unchanged. Actual provider cases enter the -ordinary Docker discovery; final timing, complete assignment and hosted fit -remain qualification work. - -No Step 4 runtime success, catalogue promotion, final-source demo, hosted CI or -packet completion is inferred from source implementation or offline controls. -The implementation commit, both fresh independent review rounds and verified -corrections remain required before this step closes. - -### Step 4 initial qualification - -The frozen implementation compiles in Release with `CI=true`, zero warnings -and zero errors. The exact new meta step passes 148 named Node cases. The full -guarded frontend run passes 1,730 cases in two packages with zero skips/todos; -workspace typecheck and lint pass. Unit, Docker-free HTTP and contract runs pass -2,616, 289 and five cases respectively, with zero skipped cases. - -Initial actual-provider qualification finds fixture defects and remains red: -the API run passes 11 of 12 cases, while its organization-mutation cleanup gets -400 from an attributes-only Admin user update. That final assertion masks any -earlier failure, so no organization-mismatch success is inferred. The provider's -user-profile update needs the unchanged ordinary fields with its attribute map. -The profile/issuance run passes 13 of 19 cases. Five profile cases receive HTML -from Account GET rather than JSON; explicit JSON content negotiation is required -before any success can count as an account-data observation. A live TTL mutant -also shows that omitting an attribute from a client update does not remove its -existing value; restoration requires explicit removal and independent readback. -Registration's ordinary positive and late-session expiration clamping pass. -These are implementation qualification findings, not independent review rounds. - -The broader account/upgrade run executes 24 cases: eight pass and 16 fail, with -zero skips. Failures include the missing JSON negotiation and a real planner/ -readback incompatibility: the pinned provider removes an empty mapper role-prefix -entry, while the intended configuration comparison requires that empty entry. -One warm attempt therefore fails readback after six durable writes. The stock -builtin comparison itself passes before a later status assertion fails; this -does not make its containing test green. - -The narrow correction accepts only the fixed-account mapper's documented -empty/absent role-prefix equivalence. It preserves every required option, -unknown-option refusal and raw preservation check for existing mappers. The -independent fake provider now models the pinned conversion rather than echoing -the requested configuration. Four additional controls cover normalization, -required/unknown options, create/conflict readback and existing-mapper identity; -all five Node suites pass 152 cases with zero skips. Actual-provider reruns and -the JSON/restore fixture corrections remain pending. - -All three completed provider-run resource sets have zero retained containers, -networks or volumes after normal owned teardown; the unrelated database remains -running. The complete architecture run continues against unchanged production -and architecture binaries. Body-only integration fixture corrections are built -separately, without rebuilding those dependencies; case identities and trait -declarations remain unchanged. Current-source Docker census checks remain -required after the collection-boundary extension. -Neither status-only Account HTML nor a failed restore is proof of the intended -protection or recovery. - -### Step 4 corrected local qualification - -The corrected source passes **55 actual-provider cases, zero skips**: 24 account, -export and reconciliation cases; 19 profile and issuance cases; and 12 production -API cases. Account observations explicitly request JSON and verify its ordinary -fields. User mutations preserve the unchanged ordinary identity fields, restore -the exact attribute map and verify a fresh positive token/API result. Client TTL -restoration explicitly removes the override and independently verifies its -absence before accepting the recovered 900-second token. - -The account run proves fresh builtin parity, four narrow role additions plus -one console mapper on warm upgrade, zero writes on rerun, existing effective -group/composite capability without a new direct grant, and a nonmanifest user's -403-to-JSON-200/edit-204 transition without changing that user's mappings or -data. Five incompatible account configurations refuse before a write after a -working clean twin. Its complete 24-case TRX SHA-256 is -`a2b000ff5f9646ed7e4f03e20e74054a831e71410f863331892fbb3c0b30ca39`. - -Profile mutation uses its own class fixture, separate from the readonly shared -issuance baseline. The final 19-case run executes those classes concurrently on -independent providers. It verifies all three protected attributes, ordinary -account edits and registration, user-editable counterfactuals, fifteen live -token-profile variants with clean recovery, and the late-session expiry clamp. -Its complete TRX SHA-256 is -`f470c252cbbfc908e1d4996278cf116ba2b78eb514755d729c57a6ae6f8a2aa7`. - -The real API run admits all four declared personas through the stock production -authentication path and application-role PostgreSQL owner. Tenant/organization -disagreements stop before the read and persist one defended-tenant rejection -with the expected actor/source/scope. Claimless public reads preserve their -HostOnly ceiling; actual ID/Hub tokens and the wrong CA are refused. Anonymous -reads remain independent of an unavailable identity provider. Its complete -12-case TRX SHA-256 is -`7fafa97c24ea554cb0a629b5c3c952942d1ee54b767a7a988f4b9c5a5e8eb02e`. -Exact-session teardown leaves no owned provider resources; the unrelated -database remains running. - -The complete architecture assembly passes **433 cases with zero skips**. -Production and architecture input binaries remain unchanged across the separate -integration-fixture correction build; 359 SHA-256 observations retain that -boundary. Current-source Docker/corpus checks pass seven cases, followed by two -Docker census cases after the profile class-fixture isolation change. The census -now detects direct public-read fixtures, the named API collection and partial -test classes; its planted missing-trait controls fail the same detector. -Release builds report zero warnings/errors. The corrected exact meta step passes -**152 named cases**, with all report-refusal controls retained. The previously -recorded complete frontend, unit, HTTP and contract runs remain valid for their -unchanged source inputs. Link/fragment and whitespace checks are clean. - -These are local receipts. Step 4's implementation commit, two fresh independent -review rounds, final-source production demo and complete hosted qualification -remain pending. Both P02b-6 catalogue entries remain Registered; no BFF session, -packet completion or merge is claimed. - -### Step 4 review round one and executed-case correction - -Implementation commit `ea0363e8` is inspected by two new independent reviewers: -`gpt-6-astra` at `xhigh` for security/ownership and `gpt-6.1-sol` at `xhigh` for -proof correctness, API/fixture isolation and CI/corpus. The security inspection -finds no actionable defect and independently passes all 152 Node cases. -The proof inspection reproduces one Major: Node 22.23.1's JUnit reporter emits -passing `testcase` elements for empty named `describe` suites even though its -actual executed-test count is zero. The initial gate therefore cannot establish -the claimed nonempty execution from JUnit alone. - -The correction adds a second reporter to the same Node invocation. It requires -exactly one completed root `test:summary`, positive safe-integer executed-test -count, all executed tests passed, successful completion and zero failures, -cancellations, skips and todos. The JUnit filename/shape checks remain separate. -Three offline controls execute the actual workflow command/gate in twelve child -runs. Both empty-suite counterexamples pass a checked variant removing only the -counter reporter and fail the real command; ordinary/nested real tests pass, -while empty files, failures, cancellations, skips and todos are refused. These -controls run in meta. The original reviewer independently verifies the correction -and the exact complete meta step: **152 executed tests and 152 JUnit cases pass**, -with no remaining actionable correction finding. Formal round two remains -required. - -The CI plan adds advisory weights for 37 realm method selectors (35 live-provider -methods and two offline export controls) from the three complete 55-case TRXs -above. Those receipts contain 53 live-provider cases and two offline controls. -Exact completed row durations are summed and -scaled by the existing historical ordinary ratio, 2.271245. Artifact digests -are retained; source commit is null because it is not embedded in the TRXs. -Fixture startup and discovery costs are not inferred from case durations. -Topology, selectors, default unknown-method estimate, algorithms and time -ceilings are unchanged. All 52 shard controls pass. - -Actual local adapter discovery independently finds **5,902 cases**: 2,910 base, -433 architecture, 2,528 ordinary Docker and 31 native. Both complete assignments -cover the exact population once, genuinely differ and stay within the existing -selector/filter bounds. Forty-two non-base methods retain the explicit unknown -weight default. Estimated summed case durations are not wall-time guarantees; -no hosted fit or execution success follows from this local discovery. - -### Step 4 review round two and production demo - -Two further fresh independent reviewers, `gpt-6-astra` and `gpt-6.1-sol` at -`xhigh`, inspect the complete Step 4 source through `4a3173d8`. Both approve -without an actionable finding. Each independently passes all 152 executed Node -cases, the three actual-workflow gate controls and all 52 shard controls. The -proof reviewer additionally rejects thirteen missing, duplicate, malformed or -unsuccessful summary streams against the real reporter. The security reviewer -independently verifies that only the 37 measured weights and three provenance -records change the plan. Neither reviewer substitutes a local receipt for -complete hosted qualification. Separately, five environment, eighteen -provisioning and forty native-owner offline controls pass. - -An isolated clean `development` clone at runtime commit `ea0363e8` and tree -`34f391c6d837762a94bf6b704cdc1c01f220d041` passes the actual production -`make demo DEMO_MODE=ci` in 649.497 seconds. Contextual application seed and -four-user realm reconciliation complete before Keycloak is stopped for the -public proof. Nine product pages, 24 visibility controls and all 27 audits pass; -all 27 JSON/HTML report pairs and nine visually inspected screenshots exist. -Accessibility scores are 1.00 throughout, with zero warnings, runtime errors, -failures or skips. Both HTTPS refusal controls and the actual timeout refusal -pass; all 134 API completions are HTTP 200. Cleanup completes in 10.750 seconds: -zero owned containers/networks/volumes, vacant owned ports and removed private -files/environment/lock. The unrelated database identity/state/start time remain -unchanged and tracked clone source stays clean. The receipt SHA-256 is -`e4e823a088e90cbcee37988d239741d86bc300bb66dcd4db7e92a405b075d45b`. -The subsequent commit changes CI controls, timing data and this record, not the -demo runtime; final PR-head hosted qualification remains separately required. - -### Step 4 initial hosted qualification and source ownership correction - -Workflow-dispatch run `39587211807` checks candidate `4a3173d8` against main -`24705a7a`; OpenAPI, meta and secret scanning pass. Frontend typecheck/lint/build -pass, but its test gate refuses the newly added Python counterexample helper as -unclassified repository source. The prior complete frontend receipt predates -that helper; its runtime source census depends on this additional repository -input. The hosted test result is therefore 1,657 passed and one failed, not a -complete passing frontend run. Other execution jobs retain their independent -results; no full-workflow success is claimed. - -The correction declares only `scripts/test-realm-node-gate.py` as non-runtime, -beside the other exact offline CI control owners. The existing source-classifier -test asserts that exact path; the live census also explicitly requires the new -Node reporter among runtime sources. Unknown Python files and unmodeled runtime -formats remain refused. The complete guarded frontend rerun passes **1,730 cases -in two packages, zero skips/todos**. Fresh focused review verifies this correction -before final-source qualification. - -Two new independent correction reviewers, `gpt-6.1-sol` and `gpt-6-astra` at -`high`, approve `1f0a8d06` without an actionable finding. The former independently -passes all nineteen focused genericity cases and validates their actual JSON -report with the repository guard; both pass the three actual-workflow controls. -The latter also checks exact helper ownership, refusal of five adjacent/unknown -paths, continued reporter inclusion and refusal of a runtime import of the -excluded Python source. Workspace typecheck, targeted lint, hook -formatting, whitespace and link/fragment checks pass. The correction changes -neither the product runtime nor CI membership or time ceilings. - -### Step 4 implementation closeout and PR qualification handoff - -All four approved implementation steps, their two independent review rounds and -the required fresh correction reviews are complete on `development`. - -| Step | Delivered result | Review status | -|---|---|---| -| 1 | Executable import/profile/scopes, four typed stable identities and real fresh issuance | Both rounds and verified corrections complete | -| 2 | Bounded non-destructive warm reconciliation, credential continuity and preflight/readback | Both rounds and fresh correction reviews complete | -| 3 | One seed/demo operation and cancellation/cleanup owner with real lifecycle replay | Both rounds and fresh correction reviews complete | -| 4 | Narrow account self-service, real profile/registration/API proofs, CI ownership and carrier closure | Both rounds and fresh correction reviews complete | - -The completed first hosted run -[`39587211807`](https://github.com/HodeTech/LearnStack/actions/runs/39587211807) -binds its twenty successful execution owners to source `4a3173d8`. Independent -download/readback recomputes assignment from the actual adapter discovery and -verifies **5,902 distinct passing case identities, zero skips**: 2,910 base, -433 architecture, 2,528 ordinary Docker and 31 native. The 53 live-provider -cases and two offline export controls all pass. Every selected case matches its -completed record; all owners -report actual completion and cleanup, without forced cleanup, and all Docker -owners report no retained resources. The longest execution job takes 860 -seconds, below the unchanged twenty-minute ceiling. Both required backend -aggregates pass and verify their artifact/API provenance. Meta, OpenAPI, secret -scan and the hosted production demo also pass. The known frontend source-owner -failure above keeps this **whole run failed**; no corrected-head success is -inferred from it. - -The plan digest is -`c380356092978a923d4ba98108c3a1f7f13e5160bec1522f7848a368af68092d`; -the hosted manifest digest is -`736b7f268398e429ea8b5c04cc2d619d29418dfc9dd3f37a8637639d1fdf9422`. -The actual hosted toolchain is SDK 10.0.402, VSTest -18.7.0-release-26505-111 and adapter 2.8.2, recorded rather than inferred from -local SDK 10.0.302. The declared SDK roll-forward permits this feature band. - -Both P02b-6 behavioural catalogue obligations are now **Implemented** with their -actual Integration/meta owners. Published counts are 231 Implemented, 133 in the -Architecture assembly and 98 outside; the five corpus-consistency cases verify -those counts and owners with zero skips. No new structural rule or test-method -count is invented. The seven live required contexts and strict protection are -independently read back unchanged; no repository setting is modified. - -This is the implementation/review closeout. The PR's required checks own final -head qualification, including complete unchanged-plan A/B assignments and the -production demo. A full rerun selects B; rerunning only failed jobs cannot -establish a complete alternate assignment. No partial run, old-head receipt or -local success substitutes for those checks, and this record claims no merge. -P02b-7 is next: its decision pass owns BFF/session custody, lifetimes, refresh, -CSRF/logout and SDK bearer transport. P02b-8 owns final enforcement and erasure -inventory; Phase 03 owns live membership/authorization. G13's session part stays -Open until that next packet's accepted decision pass. - -### P02b-6 PR review corrections (2026-10-21) - -Six review observations are verified against `204a1039` and corrected. Tooling -retains explicit proxy, private-CA and package-cache prerequisites; the Docker -version probe uses the existing Compose environment owner. Application -credentials remain confined. Reconciliation preserves cancellation/deadline -classification after transport rejection. Failed lock initialization closes its -handle and removes its exclusive marker before refusal. Seed stack startup and -migrations retain finite 600s and 300s command budgets respectively; the realm -HTTP/pass budgets remain 5s/120s. The integration pyramid and current realm -issuance wording now match delivered provider coverage. - -Local qualification passes 160 Node controls, the complete guarded frontend -suite (1,730 cases, zero skips/todos), web typecheck and focused lint. New fault -controls fail four times against the original implementation and pass against -the correction. Two fresh independent correction reviewers (`gpt-6-astra` and -`gpt-6.1-sol`, both at high effort) approve `204a1039..e0f9798f` without an -actionable finding; each independently passes all 67 affected Node controls. -The PR checks own new-head qualification; earlier source-bound CI receipts are -not promoted to this head. - - -### P02b-6 systematic corrections and hosted qualification (2026-10-21) - -The correction pass remains on `development`. The implementation/review receipts -above describe their recorded source, not approval of a later PR head. The live -PR checks own complete current-head qualification; this record retains the -source-bound history and the correction obligations. - -**Failed hosted evidence.** Run -[`39598693980`](https://github.com/HodeTech/LearnStack/actions/runs/39598693980) -tests head `eb707ee84f7c3cbc29c4f7ded2b86cb1b7cb5834` through merge source -`c390635d0efeb92b08b3c75485fc541b4ca83d3f` with the identical head/merge tree -`fd08acbbdc0710f0fb5de579bc1c5975ef95a3a9`. - -- Attempt 1 completes all 27 jobs and seven required contexts, with 5,902 distinct - passing cases, zero skips, exact selected/completed/TRX equality, actual cleanup - and verified job/artifact provenance. Its 55 realm cases comprise **53 live - provider cases and two offline export controls**, not 55 provider executions. -- Attempt 2 is failed evidence. Ordinary-10 exports 185 passing and two failing - cases: both `independentFailure: false` variants of - `Native_completed_cancellation_survives_restart_and_independent_failure_is_not_reclassified`. - Its owner reports `tests_failed`, `owned_completion_missing`, forced cleanup - and no Docker-absence witness. Sanitized records and retained job output omit - assertion/stack details. Neither port pressure, resource pressure nor Keycloak - co-membership is established as the cause; no speculative backend fix follows. -- Attempt 3 reruns only failed jobs. Its ordinary-10 passes 195 cases, but the - integration aggregate fails before issuing a receipt. The exact current-attempt - `ci-proof-39598693980-3-base` artifact is absent. The jobs API can project reused - successful sibling rows into the current attempt; those rows do not prove a - fresh execution. The missing receipt upload is a consequence of refusal, not - a different output path. This partial run does not qualify either full layout. - -**Verified corrections.** - -| Boundary | Correction and proof ownership | -|---|---| -| Aggregate evidence | Preserve current-attempt artifact identity and fail closed; distinguish `artifact_api_missing`, `artifact_api_not_unique` and invalid metadata. An executing partial-rerun control refuses reused sibling evidence. | -| Node execution | A single owner derives the complete test-file census and requires exact reviewed per-file executed counts plus same-invocation JUnit. Added/missing files, deleted cases, redistributed cases and empty suites are rejected. | -| Fixture census | The first correction lists 82 classes. Independent round one finds that qualified collection references and other explicit fixture types remain omitted; the follow-up below corrects this census. No measured fixture startup cost is invented. | -| Realm ownership | Only an exact successful single-user `ADDED` receipt establishes creation with the declared credential. An ambiguous 409 or a publicly registered reserved username without the admitted legacy identity refuses. Existing credentials/MFA and unrelated state remain preserved. | -| Effective login | Disabled realm/clients, consent changes and incompatible stock account callbacks refuse before writes. The two legacy declarations remain tied to the typed seed authority; tooling adds no institution-name branch. | -| Token availability | Bounded proactive administrator-token renewal reserves the complete exchange budget and never replays a failed Admin request. The whole pass still ends at 120s. | -| Real provider repair | A planted warm scope drift exposes Keycloak's required `name` on scope updates. The repair carries only retained `name`, retained `protocol` and merged attributes; a model that accepted attributes-only updates no longer masks this path. | -| Local lifecycle | Read selected private files through no-follow owner-only regular-file handles. New Makefile files use mode 0600; old files require explicit operator repair. Check the effective local Docker context before stack work. Remove the implicit BFF-secret fallback. Print fixed seed stage/reason diagnostics without child output or credentials. Migration credentials remain in the confined factory environment, not process arguments. | -| Independent security proof | Inspect actual loopback Docker bindings, exact stored identity for all four personas, ordinary profile preservation, exact ID-token subject/client/nonce/issuer, transport cancellation and trusted-CA behavior. | - -**Plan revision witness.** On the unchanged 5,902-case manifest -`736b7f268398e429ea8b5c04cc2d619d29418dfc9dd3f37a8637639d1fdf9422`, the timing -revision from source `ea0363e8b936c209a9a1bae6e9a027d6877ae596` moves 2,318 -ordinary cases in A (1,043 methods) and 2,256 in B (1,034 methods); Architecture -moves zero cases. This is the old-plan-to-new-plan difference, distinct from -A-to-B independence. No weight is reverted to conceal the failed layout. -The first, still incomplete fixture-class census changes its eligibility witness -to 2,191 cases, of which 2,046 change owner across A/B. The earlier 1,985 witness -covered a smaller subset. Architecture/ordinary A-to-B changes remain 371/2,339 on -that fixed manifest. New tests require a newly discovered manifest and new full -qualification; none of these historical counts are promoted to that source. - -**Receipt corrections and limits.** The Step 1 round-two total of 46 export -variants is historical; it became 58 after the account-console extension, and -this pass expands the existing export proof again. The early Step 2 receipt of -65 transport/target/lock controls precedes the later 20 + 46 = 66 checkpoint; -neither is a current suite count. Those two historical Step 2 review rounds did -not retain model/effort metadata in this record; it is not reconstructed by -inference. Catalogue status was Registered at the earlier Step 4 checkpoint and -became Implemented only at its later recorded promotion. - -The previous-head `39590028974` A/B capture retained and API-digest-verified 46 -raw archives locally. That is a capture-time receipt, not a claim that all 46 -remain downloadable: later attempt uploads overwrite shared artifact names. -Its 152 meta Node controls belong to that previous source; `eb707ee8` executes -160. Auxiliary artifact names now include run and attempt identity. - -A 999-user ceiling bounds inventory, not completion throughput. An independent -999-user/40ms-per-exchange model reaches the unchanged 120s deadline and refuses; -no real scale benchmark or guaranteed convergence at that ceiling is claimed. -All nonmanifest/group safety checks remain. The measured 913s hosted demo job -leaves a thin margin in its existing allowance, but is not a reproduced deadline -failure. The sixteen-minute proof allowance, four-minute cleanup/artifact -reserve, twenty-minute execution ceilings and required context names remain -unchanged. Pinned image preparation is separately bounded before fixture startup -and must fit the same whole-job budget. Sequential aggregate downloads already -complete in 16/30s against their 240s allowance; no unmeasured parallel rewrite -or timeout expansion is bundled. - -**Local verification at `d8139de3`.** The source-censused Node owner passes 234 cases -(30 core, 41 HTTP, 56 ownership, 95 planner and twelve real CLI cases), with no -skips/todos. The guarded frontend passes 1,735 cases in two packages; typecheck -and lint pass. CI controls pass nineteen aggregate, 57 shard and six Node-gate -cases. The actual CLI success/failure/SIGTERM paths execute target validation, -private-source handling, lock ownership, credential-free child commands, full -planner/readback and cleanup; only the external provider boundary is substituted. -Separate actual HTTP and live-provider proofs retain their own coverage. -The readiness fault controls use an actual child-ready marker before injected -deadline expiry and an explicit cleanup release barrier, replacing two fixed -startup/hold sleeps without changing production timeouts. - -The first expanded provider invocation executes 59 cases (53 live and six -offline): 58 pass and the newly exercised scope-update branch fails. The -attributes-only request is independently reproduced and corrected as above. -The current affected set then passes all 21 cases, including all thirteen -reconciliation cases, actual startup/bindings, transport/export and backchannel -controls. Twenty-two architecture/migration/Seeder/Docker controls also pass; -Release builds have zero warnings/errors. This is an affected-source rerun, -not a claim that the earlier 59-case invocation passed. Cached-image fixture -startup measures 19.491s; no cold-pull or fixture-cost estimate is inferred. -The existing export proof now rejects 66 variants; the earlier 46/58 totals -remain as-of receipts. - -Both fresh independent correction review rounds and full frozen-source hosted -A/B qualification remain pending at the `d8139de3` checkpoint. No passing -partial retry, old-source receipt or missing cleanup witness closes that gate. -This correction record claims no merge or P02b-7 delivery. - -**Independent correction round one.** Three fresh reviewers inspect -`eb707ee8..d8139de3`: security/runtime (`gpt-6-astra`, xhigh), CI/provenance -(`gpt-6.1-sol`, xhigh), and provider/corpus (`gpt-6.1-sol`, xhigh). They verify -two Major findings, now corrected: - -- Compose selection reads the selected source before the hardened realm reader. - A temporary FIFO blocks both actual CLI entries before cancellation can run. - The shared first read now uses one no-follow, nonblocking, owner-only regular - file handle and caps bytes read even if the file grows. Six actual-entry - controls cover FIFO, symlink and oversized sources for seed validation and - reconciliation; every refusal exits naturally with no signal or child command. -- The first census misses qualified collection references and other explicit - fixture types. Its declaration-bound replacement recognizes the repository's - explicit `IClassFixture<T>` classes and members of `ICollectionFixture<T>` - collections, excluding comments, literals and unrelated declarations. Unknown - or ambiguous fixture forms refuse. All 116 such classes are included; manually - constructed fixtures are outside this source-declaration census. This is not - a measurement of fixture starts or cost. - -On the same historical 5,902-case manifest, the corrected fixture witness covers -2,527 ordinary cases / 1,147 methods; 2,338 cases / 1,057 methods change owner -across A/B. The census correction changes no case assignment, source timing or -weight. Its plan digest is -`cbe9f7086f0304aa1d8483aba04ba8feb9b462c9468b085f2fec1fcadaa978f5`. - -The updated Node owner passes 240 cases (30/41/56/95/18), including the six -actual-entry controls. Full guarded frontend verification passes 1,735 cases; -typecheck passes. CI controls pass 59 shard, nineteen aggregate and six Node-gate -cases; source topology remains complete. The provider reviewer independently -passes seven offline transport/export/backchannel controls and both Docker -census architecture cases. The mutable root status now distinguishes earlier -completed step reviews from this correction gate. Round two and full -frozen-source hosted A/B qualification remain pending at this checkpoint. - -**Independent correction round two.** Three different fresh reviewers inspect -`eb707ee8..837d9d50`: security/runtime and CI/provenance (`gpt-6-astra`, xhigh) -and provider/corpus (`gpt-6.1-sol`, xhigh). The provider/corpus review approves; -the other two verify one Major each. Their corrections preserve the plan and -all existing execution/cleanup budgets: - -- A collection-attribute alias can hide the marker used by the source census. - Local and separate global-using aliases now explicitly refuse before the - marker fast path; an executing control covers both attribute types. The - 116-class census, plan digest and assignments remain unchanged. The shard - control suite now passes sixty cases. -- Demo's early context check precedes Compose's removal of inherited keys - assigned by the private source. It can therefore inspect a different Docker - environment from the eventual stack. A second five-second check validates - the exact selected environment before every Compose command. Two actual-entry - lifecycle controls fail before the fix and pass after it. The same comparison - exposes seed's reintroduction of inherited `HOME` into its inspection; that - probe now also uses the exact selected environment. Its additional regression - fails before the one-line fix. Docker's - [CLI configuration and context precedence](https://docs.docker.com/reference/cli/docker/) - make these inputs relevant to engine selection; no real Docker or private - environment is used by the fault controls. - -Combined verification passes 240 Node and 1,738 guarded frontend cases, with -zero skips/todos; typecheck, lint and source topology pass. The independent -provider reviewer again passes seven offline cases and two Docker-census -architecture cases, without claiming live-provider execution. Independent -focused verification of these final corrections and full frozen-source hosted -A/B qualification remain pending. No historical failed layout is relabelled. - -**Final focused correction verification.** Two further fresh independent -reviewers approve `f09b16d1`: CI/provenance (`gpt-6.1-sol`, xhigh) independently -reproduces the alias bypass on the prior source and its current refusal, then -passes 60 shard, nineteen aggregate and six Node-gate cases plus topology. -Docker-environment/lifecycle (`gpt-6-astra`, xhigh) independently passes all 38 -lifecycle cases; the real frontend report validator accepts their exact file -inventory with zero skips/todos. Both inspect the fixes without editing source. - -No measured failure justifies extending the operation, HTTP, fixture or CI -deadlines. Proposed aggregate parallelization adds no demonstrated benefit to -the retained 16/30s result; optional password/certificate policy expansion and -a second seed-wide lock do not fix an established defect in this boundary. -Already-rejected incompatible 409 readback remains rejected. Those suggestions -do not replace the verified ownership, target and creation corrections above. - -Local implementation, both full correction review rounds and focused fix -verification are complete before hosted qualification. Full current-source A/B -execution remains the next gate; the -[live PR checks](https://github.com/HodeTech/LearnStack/pull/34/checks) own its -current status. This source checkpoint claims no merge readiness, passing retry -or next-packet delivery. Source-bound hosted receipts are retained separately -from this local checkpoint. - -**Frozen-source A failure and diagnosis follow-up.** Run -[`39628288185`](https://github.com/HodeTech/LearnStack/actions/runs/39628288185), -attempt 1, tests `0c9d28768758aff8f350abbb5b09daf6a7f6e75a` through merge source -`8560880e96320ce82a7eb3b2f124dba8b71d1668`; both have tree -`b71883fd423567db55b48c5b74cdad6b3bbd647a`. All 27 jobs finish: eighteen pass, -seven execution owners fail and both dependent aggregates refuse. No B attempt -or failed-only retry follows this failed A. - -- Base discovery contains 5,907 cases: 2,915 base, 433 Architecture, 2,528 - ordinary and 31 native. The manifest digest is - `187da443e8fc5e3b179714fe7bf8f718ae4a246a7d1ad7ea9d13d8cce5073d34`; - the plan digest remains - `cbe9f7086f0304aa1d8483aba04ba8feb9b462c9468b085f2fec1fcadaa978f5`. - These discovery counts are not passing execution counts. -- The actual genericity assertion rejects a demo username in the manifest - projection. A local run reproduces it. The projection now binds a legacy - identity to its complete declared actor, tenant, username and legacy attribute - in `SeedData`, without a demo-name branch or guard exception. Eight affected - Architecture cases and all three offline export cases pass; unique-username - swaps, tenant rebinding and a fresh valid UUIDv7 actor are rejected. -- Six ordinary owners retain eighteen failed Keycloak cases with 1 ms result - durations. Their existing closed fixture-startup message is absent from - retained diagnostics. Failed ownership receipts report forced cleanup without - a Docker-absence witness; neither a provider leak nor a startup cause is - inferred from those fields. An unchanged owned Linux fixture starts in - 21.665s with its original two-minute cap, strict TLS and actual loopback - binding checks. That ARM64 container probe does not reproduce the hosted - x64 VM or its load, and does not establish the failed cause. -- Frontend, meta, OpenAPI, secret scan and the production demo pass. Frontend - executes 1,738 cases; meta executes 240 Node cases. Its sixty combined CI - controls comprise **41 shard/plan and nineteen aggregate controls**; running - the aggregate module separately repeats those nineteen, not nineteen new - controls. The demo retains nine pages, 27 report pairs, nine screenshots, - actual TLS/timeout refusals and complete owned cleanup. These successes do - not qualify the failed backend execution or the whole source. - -The bounded diagnosis follow-up preserves only the fixture's existing finite -startup stage/reason/cleanup sentence for five explicit integration classes. -It rejects unknown, ambiguous and oversized messages and never exports raw -provider text. Cleanup diagnostics do not supply a cleanup witness; test -outcomes, complete case/result guards and failure status remain unchanged. -This uses ADR-0063's existing sanitized finite-fault seam, with no new authority, -timeout, selection or admission policy. Current-head full A/B qualification -remains open until actual complete executions pass. - -**Diagnosis follow-up reviews.** Two independent reviewers complete each of two -rounds on `5fbbf093`: first genericity (`gpt-6.1-sol`, xhigh) and diagnostics -(`gpt-6-astra`, xhigh), then fresh genericity (`gpt-6-astra`, xhigh) and diagnostics -(`gpt-6.1-sol`, xhigh). All approve their scoped changes without an actionable -finding. The final diagnostics reviewer independently executes all three new -offline controls. Root verification passes all 43 launcher controls, sixty -combined shard/aggregate controls, the eight affected Architecture cases, three -offline export cases and five corpus cases, with zero skips. No local check or -review establishes the hosted startup cause; a new complete frozen-source run -remains necessary. - -**Second frozen-source A and provider classification.** Run -[`39633149831`](https://github.com/HodeTech/LearnStack/actions/runs/39633149831), -attempt 1, tests `6109268ff5b8ba19d71ed569682e763256e8f903` through merge source -`31f701a48fa9ae407b69c3ad0f6e4e43e2c8fdbc`, with identical head/merge tree -`468302f4ef3520fb80cc59467fb99d8434170b0d`. All 27 jobs finish: nineteen pass, -seven ordinary owners fail and integration refuses. Backend aggregate and all -six Architecture owners pass, confirming the corrected genericity boundary. -Frontend/meta/contract/secret/demo successes retain their own current-source -API-bound receipts; no B or partial retry is started on this failed A. - -All twenty failed Keycloak cases now retain the exact closed diagnostic -`database/provider_error/completed`: nine issuance, ten reconciliation and one -self-service case. Every failed owner archive is checked against its immutable -API ID, digest and payload identity. This proves the diagnosis channel, not the -underlying provider cause or Docker absence. A small owned Linux batch starts -six PostgreSQL containers concurrently (three exact custom-network/loopback -fixtures, three default-network controls) in 6.85–7.61s; all containers and -networks are disposed and independently absent. It does not reproduce the -hosted failure. - -The pinned Testcontainers path checks readiness inside the PostgreSQL container, -without a host Npgsql/TLS login. Normal not-ready results retry; the generic -provider code cannot establish a readiness deadline failure. The next narrow -diagnostic distinguishes Docker API status, resource-reaper initialization, -socket and filesystem failure families without using any provider message or -response body. The pinned resource-reaper exception discards its inner cause, -so its code does not invent a timeout/cancellation distinction. The -[Docker exception](https://github.com/testcontainers/Docker.DotNet/blob/1e4015a84fa48cbcfe9002ecc4e2cf14177edc2d/src/Docker.DotNet/DockerApiException.cs) -and [resource-reaper exception](https://github.com/testcontainers/testcontainers-dotnet/blob/37352559c0af87d5c7eeaced1accc2d21e3a4e69/src/Testcontainers/Containers/ResourceReaperException.cs) -are checked at the installed package repository commits. Existing startup, -HTTP and job deadlines, cleanup and failure outcomes remain unchanged. One new -offline canary control checks the classifier and its unknown-message fallback; -it is diagnostic proof, not a provider repair or hosted qualification. - -The first classifier source checkpoint passes seven offline cases and 43 owner -controls; two first-round reviewers approve its privacy and diagnostic logic. -A subsequent root Architecture run exposes the static fixture reference in the -offline control: six cases pass and the Docker-trait sweep fails. The pure -classifier now lives in `KeycloakStartupFailure`; neither the offline test nor -its helper starts or owns a fixture. The guard is unchanged, with no exemption -or misleading Docker trait. The corrected source passes all seven offline -cases with warnings as errors, all seven corpus/Docker-sweep cases and all 43 -owner controls. Final independent verification follows before a new hosted run. - -Two final second-round reviewers (`gpt-6.1-sol` and `gpt-6-astra`, high effort) -approve the complete `6109268f..dc25ebb0` correction, including the fixture-free -boundary, without a remaining actionable finding. Both independently build and -pass all four transport controls in Release with warnings as errors; the first -also passes all 43 owner controls, and the second all three focused Keycloak -Python controls. Both inspect the final seven-case offline and seven-case -Architecture receipts. The sixty combined plan/aggregate controls pass again. -This completes the narrow diagnostic review gate, not provider repair. New -complete current-source A/B qualification remains required. - -**Third frozen-source A and daemon-family diagnosis.** Run -[`39637263886`](https://github.com/HodeTech/LearnStack/actions/runs/39637263886), -attempt 1, tests `fddfc2665ae401e7c8d15bdce988be65f59b327d` through merge source -`567dce35b3b8eee5c79f808edb2338d8c7083728`, with identical head/merge tree -`f451491961a7e9cb33ca21ed4c46c5e55a27df1b`. All 27 jobs finish: seventeen pass, -nine ordinary owners fail and integration refuses. All 37 failed provider cases -retain `database/docker_server_error/completed`, establishing a Docker API HTTP -500 response, not its cause. Their nine archives have independently verified -immutable API IDs, digests and current-source payload identities. All five -auxiliary checks pass with their own source-bound receipts; these do not qualify -the failed integration result. No B or failed-only retry is started. - -The next diagnostic records last-reached PostgreSQL SDK creation/start/readiness -milestones. It privately classifies bounded, shallow HTTP 500 JSON with exactly -one string `message` into six fixed networking/task families; unknown or malformed -responses retain `docker_server_error`. It exports no daemon text, address, -port, path or exception type. Actual owned cleanup precedes classification, and -the diagnostic remains separate from cleanup witnesses and result acceptance. -The categories follow the pinned Moby -[network setup wrapper](https://github.com/moby/moby/blob/6430e49a55babd9b8f4d08e70ecb2b68900770fe/daemon/start_linux.go#L37) -and [port mapping implementation](https://github.com/moby/moby/blob/89c5e8fd66634b6128fc4c0e6f1236e2540e46e0/libnetwork/drivers/bridge/port_mapping_linux.go). -The hosted daemon version and actual response body remain unobserved. - -A source-level port-allocation hypothesis is not a provider repair: an isolated -unchanged-old/corrected-upstream allocator comparison detects mixed wildcard/ -specific-address allocation differences, but the surrounding TCP bind path can -retry collisions. It neither reproduces hosted HTTP 500 nor justifies changing -application fixture bindings. Startup deadlines, test selection, ownership and -failure outcomes remain unchanged. Root validation passes seven offline C# -cases with warnings as errors, seven corpus/Docker-sweep cases, all 43 launcher -controls and sixty combined shard/aggregate controls. Independent reviews and -actual hosted diagnosis remain required before this follow-up can claim -qualification. - -The first independent lifecycle reviewer (`gpt-6.1-sol`, xhigh) approves -`fddfc266..9bbf2a31` and independently passes all 43 launcher controls. The -privacy reviewer (`gpt-6-astra`, xhigh) reproduces a malformed-string fallback -gap: raw unpaired UTF-16 surrogates throw `ArgumentException`, unlike the -already covered escaped-surrogate form. Four before-red controls reproduce -this against the unchanged helper; the correction catches that specific -exception and adds all four controls to the existing offline case. This is a -bounded .NET string-contract correction, not a demonstrated HTTP decoder path -or the hosted Docker cause. - -One owned Linux/ARM64 startup at `9bbf2a31` uses byte-identical fixture/helper -sources and completes in 20.632s with the original 120s startup budget and -strict loopback checks. Awaited disposal and direct API checks confirm both -fixture containers, its network and the isolated runner absent. The successful -isolated startup validates the milestone subscriptions; it neither exercises -the failure classifier nor reproduces hosted load or HTTP 500. - -Two fresh second-round reviewers (`gpt-6.1-sol` privacy and `gpt-6-astra` -lifecycle, both xhigh) approve `fddfc266..fb4ab5eb` without an actionable -finding. They independently pass all seven offline C# cases with warnings as -errors and all 43 launcher controls respectively. The lifecycle review also -checks pinned event ordering, the seven-case Architecture receipt, actual -third-A source/job counts and all 37 retained closed failures, plus isolated -startup source hashes. Both preserve the distinction between a finite -diagnostic, actual resource absence and complete hosted qualification. These -two rounds complete the diagnostic correction review gate; a new frozen-source -full A remains necessary before B. - -**Fourth frozen-source A and publication repair.** Run -[`39642441764`](https://github.com/HodeTech/LearnStack/actions/runs/39642441764), -attempt 1, tests `4467492b363bdb8dd794721c58897d08a1a348c2` through merge source -`38117937fa67a4ecf680ee73e23689e3eda44bb9`, with identical head/merge tree -`b3ccb2ad280c6f6f9150e94dd70be4cc2aff92ee`. All 27 jobs finish: twenty pass, -six ordinary owners fail and integration refuses. All twelve ordinary owners -finish: six pass and six fail. Five failed owners retain eighteen provider failures at -`database_start/docker_port_listen/completed`: PostgreSQL creation succeeds, -then Docker reports a TCP listen failure. The sixth owner retains one distinct -54.013s public-admission failure at `browser 429/browser-discovery`. Each failed -archive has verified immutable API identity/digest, exact current head/merge -payload identities and the same 5,908-case discovery. These failures do not -authorize B, an old-artifact fallback or a failed-only qualification retry. - -The publisher census finds one mixed-address boundary in ordinary execution: -the application PostgreSQL fixture uses Docker's wildcard default, while both -identity publishers use `127.0.0.1`. The native proof PostgreSQL publisher -already uses loopback and runs in its separate VM. In the -[pinned old Moby path](https://github.com/moby/moby/blob/6430e49a55babd9b8f4d08e70ecb2b68900770fe/libnetwork/drivers/bridge/port_mapping_linux.go#L220), -allocation and bind are retried for dynamic ranges, but TCP listen occurs later -outside that retry loop. An isolated Linux socket experiment with unchanged old -and corrected upstream allocators forces both binds before either listen: both -mixed-address orders fail at the second listen with the old allocator; both -pass with distinct ports using the -[corrected allocator](https://github.com/moby/moby/commit/d6620915db0072817d1eccb41a765de69cb38e9c). -Same-address controls -pass on both. The non-root, network-isolated runner is removed and confirmed -absent. This establishes a mechanism, not the hosted daemon version, socket -errno or actual interleaving. - -The application publisher now uses the same loopback modifier and independent -configured/runtime inspection predicate as the identity publishers. Its live -inspection fails startup and disposes the owned container on a mismatch. -Ryuk startup/readiness precedes fixture creation, so its wildcard listener is -already listening before these fixture binds; ordinary bind-time retry remains -available. Roles, credentials, SQL commands, connection identities, test -assignments and deadlines are unchanged. A new application test requires the -actual loopback publication, and an offline control rejects wildcard/foreign -addresses, invalid mapped ports and extra publications. - -An identical isolated Linux application harness proves the change before/after: -the old publication check returns false, the corrected check true. Both runs -verify all four role postures and an actual `learnstack_app` login with neither -superuser nor bypass authority. Disposal is awaited; direct inspection confirms -the exact PostgreSQL container and runner absent after each run. These are two -real fixture startups with copied source/helper/roles-SQL hashes checked, not -a hosted repair or full regression claim. - -The distinct browser failure establishes only its closed discovery phase. The -[CDP contract](https://chromedevtools.github.io/devtools-protocol/index.html) -does not equate an advertised debugging port with an available page target. -Twenty exact-flag isolated local launches succeed immediately; no natural race -is reproduced. A constructed real-browser control suppresses the startup -window, observes an empty target list, then creates an owned page within the -original five seconds. The original single-read assertion refuses that valid -transition; the production readiness helper accepts it in 324ms. Owned browser -groups/profiles are cleaned. This proves a readiness gap, not the CI case's -raw cause; discovery also includes later WebSocket setup. - -The fixture now polls only successful, valid empty target lists. One unchanged -five-second deadline covers HTTP, body and polling; malformed, foreign, -non-page and transport failures are not retried. Owner closure, browser death -and closed diagnostic branding remain enforced. Focused validated JSON reports -pass 44 browser controls with zero skips/todos. Root verification passes all -1,756 guarded frontend cases in two packages, nine C# cases (eight offline and -the actual application publication test) with warnings as errors, seven -corpus/Docker-sweep cases, all 43 launcher controls and sixty combined -shard/aggregate controls. Scoped lint/typecheck pass. These receipts precede -the new independent correction review rounds and complete hosted qualification. - -The fourth A's five auxiliary checks independently pass on its frozen source: -frontend 1,738 cases, Node 240, launcher 43, combined shard/aggregate 60 and -Node-gate six; OpenAPI transport/fixture controls pass and SARIF has no findings. -The demo retains 27 hash-validated report pairs for nine pages, nine screenshots, -all visibility/TLS/timeout controls and complete owned cleanup. Its source-bound -Keycloak-stop/absence prerequisite is also verified. These successes qualify -their individual evidence, not the seven failed jobs or a later head. - -Two first-round reviewers approve `4467492b..1bf18b80` without an actionable -finding: security/ownership (`gpt-6-astra`, xhigh) and browser/proof correctness -(`gpt-6.1-sol`, xhigh). The first independently builds Release with warnings as -errors, passes the offline publication control and both Docker-trait guards, -and verifies the pinned inspection client's existing 100s timeout. The second -independently passes all 44 browser cases with the repository JSON validator. -Both inspect the full correction and preserve the limits on live author proofs, -constructed readiness evidence and unknown hosted daemon/browser causes. A -fresh second review round follows before the next frozen-source full execution. - -Two fresh second-round reviewers approve `4467492b..faa8c2b8` without an -actionable finding: security/publication (`gpt-6.1-sol`, xhigh) and browser/CI -proof lifecycle (`gpt-6-astra`, xhigh). The first independently builds Release -with warnings as errors, passes the offline publication case, both Docker-trait -guards and six real PostgreSQL cases covering publication, four role postures -and application-login privilege denial; exact PostgreSQL and Ryuk containers -are confirmed absent. The second independently passes all 44 browser cases -with validated JSON and checks the full correction's source/ownership boundary. -Neither promotes constructed examples to an observed hosted cause. Both review -rounds are complete; the PR's current-head checks and complete same-source A/B -receipts own hosted qualification. Seven required contexts, strict protection, -the existing shard plan and execution ceilings are unchanged. - -### Further setup and proof corrections — 2026-10-21 - -The complete A/B qualification at `abd45611` belongs to -[run `39647583156`](https://github.com/HodeTech/LearnStack/actions/runs/39647583156): -both full attempts pass all 27 jobs and all 5,910 .NET cases, with zero skips. -Independent verification checks 25 API-hash-bound archives per attempt, both -aggregate recomputations, identical source/toolchain/population/plan and changed -actual co-membership for Architecture, ordinary and shared-fixture methods. -Those receipts precede the following corrections and do not qualify a later head. - -- Compose, seed and reconciliation distinguish unsafe file properties with the - closed `preflight/private_file` reason and fixed owner/type/link/permission - guidance, including explicit `chmod 600` remediation. Files are not repaired; - paths and contents are not emitted. Oversized or malformed configuration - retains its existing configuration refusal. Existing real-CLI controls cover - the notice before commands, including FIFO/symlink refusal. -- The export drift predicate records malformed profile JSON as a violation. - Its added malformed-profile mutation first throws `JsonReaderException`, then - passes after extending the existing exception filter with `JsonException`. -- The old username swap does not create a duplicate. Duplicating legacy user 0 - onto legacy user 1 would still be masked by the legacy-identity guard. The - corrected control changes only nonlegacy user 3 to user 2's username; an - isolated exact-source mutant removing only username uniqueness admits it, - while the original predicate refuses it. -- The owned fixture CA/leaf expire after 25/24 hours, preserving both five-minute - backdated starts and all other certificate parameters. Isolated certificate - controls prove a trusted chain at +23 hours and leaf rejection after expiry; - the actual provider custom-CA/wrong-CA test also passes and its two owned - containers are independently confirmed absent. -- Testing Standards now states each integration population's actual dependency - requirement while retaining no mocked repositories and happy/edge coverage. - -Local validation passes all 240 source-censused Node cases, 1,756 guarded frontend -cases, three offline export cases and one real provider TLS case, with zero -skips/todos. Seven corpus/Docker-trait controls also pass. The isolated duplicate -and certificate harnesses each pass six -controls. Scoped formatting, lint and typecheck pass. Both fresh independent -correction review rounds remain pending at this implementation receipt. - -[ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md) is a -Proposed dedicated carrier for the already approved 900-second development -issuance choice. The original phase approval remains valid; this new ADR needs -separate maintainer acceptance before its authority/cross-link changes. It does -not change issuance, API acceptance or the Open G13 session portion. - -#### First independent correction review - -Two new reviewers inspect `abd45611..47069be2`: `gpt-6-astra` at `xhigh` for -runtime/security/proof behavior, and `gpt-6.1-sol` at `high` for ADR/corpus and -approval provenance. The first finds no actionable runtime issue and independently -passes 74 owner/reconciliation Node controls, three export cases, 38 frontend -lifecycle cases and a Release build with zero warnings/errors; no skips/todos. -The second verifies seven ADR parser controls and all scoped links/fragments. -It finds one documentation overstatement: provider-only cases do not configure -application modules. The corrected population sentence requires committed realm -configuration for provider tests and application module configuration for the -combined provider/API cases. ADR-0067 remains Proposed with no verified finding. -The second fresh review round remains pending at this correction receipt. - -#### Second independent correction review - -Two different reviewers inspect `abd45611..d2467543`: `gpt-6.1-sol` at `xhigh` -for runtime/security/proof behavior and `gpt-6-astra` at `high` for ADR/corpus and -decision provenance. Both approve without an actionable finding. The first -independently passes 74 Node controls, three rebuilt export cases and 38 frontend -lifecycle cases, with zero skips/todos. Its isolated exact-source checks pass -four refusal/cleanup, six username-mutant and ten certificate controls, including -late validity, expiry, wrong-root/hostname refusals, SANs and retained algorithms. -The second passes all seven ADR parser controls, all 619 scoped relative -links/fragments and whitespace checks, and verifies the original phase approval -and pinned provider semantics. Both independent review rounds are complete. -ADR-0067 remains Proposed pending its separate maintainer approval; the earlier -hosted A/B receipts do not qualify this changed head. Current-head PR checks own -new hosted qualification; review/merge remain separate. - -### Dedicated issuance-carrier review corrections — 2026-10-21 - -The maintainer's review of Proposed ADR-0067 identifies the missing dedicated -authority in Security 11's header. The revised draft makes that rationale and -the acceptance action explicit: only after separate approval will the header -derive issuance from ADR-0067 and replace its draft/pending notices. The earlier -phase approval remains valid. Neither that approval nor this review makes the -new ADR Accepted. - -The draft corrects the pinned source anchors against raw Keycloak 26.6.2 lines, -clarifies the absence of an override on either named client and distinguishes -shortening a configured lifespan from reducing token production. It names the -planner's action/readback contract, the core's apply/verify loop and the shared -entry's qualification/ownership responsibilities separately. Dated adjacent -notes preserve the original package's no-new-ADR statement and correct the -historical source pointers without rewriting their original text. Both front -doors now link the Proposed dedicated carrier. - -The provider already copies access-token expiration into the paired ID token. -The draft explicitly retains that consequence, including session clamping; it -selects no independent ID-token or BFF session lifetime. Separate issuance -clocks still preclude exact `exp - iat == 900` assertions. Renewal demand, -refresh-custody/rotation ownership and explicit reasons to revisit the -development setting are recorded without changing the executable 900s value, -API acceptance or G13's Open session portion. - -Three existing real-provider Facts pass with zero failures/skips: fresh signed -issuance for all four identities, shorter late-session issuance/refresh and the -existing live mapper/scope/audience/TTL mutation case. Each positive ID token -is cryptographically validated before paired expiration is compared. An -in-memory ID-expiration control preserves the unchanged access token and both -fresh-window predicates while breaking only expiration equality. Against the -old profile predicate, the fresh-profile Fact produces the expected failed -TRX; the final predicate refuses the planted mismatch. This is a payload -predicate control, not a provider-signed altered token. The red run's exact -process exit code was not retained. Both final executions exit zero, their -owned process groups are absent, and all ten retained exact fixture container -IDs have destruction events plus direct-inspect absence. Existing Fact/Theory -declarations and the 13-case population are unchanged. - -[Run `39656889029`](https://github.com/HodeTech/LearnStack/actions/runs/39656889029) -passes at the preceding `61924f0f` source. That earlier result neither qualifies -these corrections nor supplies a second assignment for their source. Local -validation passes seven corpus/Docker-trait cases, seven ADR parser controls, -all 676 scoped relative links/fragments and whitespace checks. Two fresh -independent correction review rounds follow this implementation receipt; -current-head qualification and ADR acceptance remain separate. - -#### First independent issuance-carrier review - -Two new reviewers inspect `61924f0f..d0528d16`: `gpt-6-astra` at `xhigh` for -security/test-proof behavior and `gpt-6.1-sol` at `high` for ADR/corpus and -approval provenance. Both approve without an actionable finding. They verify -the actual predicate and signed-token call sites, unchanged 13-case population, -raw pinned source lines, reconciliation responsibilities and Proposed-only -authority. The first independently confirms all ten exact fixture containers -absent and inspects the retained red/green summaries. The second independently -passes seven ADR parser controls; both pass whitespace checks. Neither reruns -provider execution or claims hosted qualification. All review subprocesses -finish. A second fresh independent round follows before correction closeout. - -#### Second independent issuance-carrier review - -Two different reviewers inspect `61924f0f..7bb9a3ee`: `gpt-6.1-sol` at `xhigh` -for security/test-proof behavior and `gpt-6-astra` at `high` for ADR/corpus and -approval provenance. Both approve without an actionable finding. They verify -clock boundaries, signed-token validation, the independent in-memory expiration -control, exact pinned upstream lines and the unchanged 13-case population. -Both independently pass seven ADR parser controls and whitespace checks. The -first checks retained TRX counts and directly confirms all ten exact fixture -containers absent. No build/provider execution is repeated; all review -subprocesses finish. Both independent correction review rounds are complete. -ADR-0067 remains Proposed awaiting its own maintainer acceptance. The authority -header/index actions remain gated; these local results do not claim current-head -hosted A/B qualification or permission to merge. - -### ADR-0067 acceptance and carrier reconciliation (2026-10-21) - -The maintainer explicitly approves the revised ADR-0067 after the completed -correction reviews. Its lifecycle is now **Accepted — 2026-10-21** and its single -index row moves from Proposed to Active. Security 11 derives development -issuance from this ADR while preserving the earlier package approval and -ADR-0064's independent API acceptance boundary. Draft/pending authority notices -are removed from current guidance; both front doors record separate acceptance. - -Dated adjacent notes reconcile the package's vehicle, G13 answer, test-source -and implementation handoff passages without rewriting historical approvals or -Proposed-state reviews. The existing catalogue source/header gains ADR-0067; -canonical obligations, counts, owners and implementation statuses are unchanged. -Architecture 13 and the Keycloak guide retain Security 11 as the ongoing-rule -pointer and distinguish the dedicated issuance decision from phase provenance. - -No runtime, executable realm value, credential, API policy, BFF session decision -or CI/shard setting changes. The earlier actual-token and hosted receipts remain -bound to their recorded sources. Local validation passes seven corpus/Docker- -trait cases, seven ADR parser controls, all 1,439 scoped relative links/fragments -and whitespace/wrap checks. The parser reports Accepted and the index contains -one Active ADR-0067 row. Two fresh independent acceptance-carrier review rounds -follow before publication. - -The preceding [run `39664005457`](https://github.com/HodeTech/LearnStack/actions/runs/39664005457) -at `c33e529e` fails ordinary-6 and the integration aggregate. Its cause is under -separate investigation; this documentation acceptance does not qualify or waive -that failure. - -#### First independent acceptance-carrier review - -Two new reviewers inspect `c33e529e..03ebd77c`: `gpt-6-astra` and -`gpt-6.1-sol`, both at `high`. Both approve without an actionable finding. -They independently verify the single Accepted lifecycle/Active index row, -completed authority references, unchanged approved semantics and catalogue -obligations, and preserved original phase history. Whitespace, added-prose and -tracked-worktree checks pass. No build, provider execution or hosted -qualification is repeated; all review subprocesses finish. A fresh second -round remains required before acceptance-carrier publication. - -#### Second independent acceptance-carrier review - -Two different reviewers inspect `c33e529e..94618013`: `gpt-6.1-sol` and -`gpt-6-astra`, both at `high`. Both approve without an actionable finding. -They independently verify lifecycle/index consistency, complete authority -references, unchanged obligations and preserved original approval chronology. -The second passes seven ADR parser controls; both pass whitespace and clean -tracked-worktree checks. No build, provider execution or hosted qualification -is repeated; all review subprocesses finish. Both fresh independent -acceptance-carrier review rounds are complete. - -The preceding CI triage independently verifies the ordinary-6 archive against -GitHub's digest and finds 224 completed cases: 223 pass and one existing -background-job cancellation/restart case fails. The failed variant has -`independentFailure = false` and `lieOnlyOnReconcile = true`; both sibling -variants pass. Its sanitized TRX has no error payload and the closed failure -location projection retains no location for this source. Neither a timeout nor -an identity regression is established. The integration aggregate correctly -refuses with `producer_not_successful`; the missing aggregate upload is -consequential. The failed receipt is preserved, without a guessed runtime fix. - -#### Closed lifecycle failure-location follow-up - -Inspection confirms that `BackgroundJobPositiveSdkTests.CausalRestart.cs` is -absent from the launcher's finite source-code projection. The correction adds -only that literal filename as `positive_sdk_causal_restart`. When VSTest supplies -that stack location, existing parsing retains its closed code and bounded line -number; it still emits no raw stack, path, exception or provider message. -This enables future diagnostics without claiming to reconstruct the lost -assertion or fix the observed lifecycle failure. Execution, success witnesses, -aggregate refusal and all time/selection budgets are unchanged. - -The existing projection control plants that filename beside allowed/unknown -sources, duplicates, private canaries and an out-of-range line. It first fails -because the causal-restart location is missing, then all 43 offline launcher -controls pass after the exact mapping is added. Source-inventory and per-entry -projection controls cover the same new literal. No new test case, host mutation, -provider run or hosted qualification is claimed. Two fresh independent reviews -of this diagnostic correction follow before publication. - -**Diagnostic correction, first independent round.** Two new reviewers inspect -`330a8e2e..4cb69463`: `gpt-6.1-sol` at `high` and `gpt-6-astra` at `medium`. -Both approve without an actionable finding. The first independently passes all -43 offline launcher controls; the second passes the focused projection control -and independently makes it fail by removing only the new mapping in memory. -They verify literal-source/line bounds, deduplication, finite output and raw -error/path exclusion. Whitespace and clean tracked-worktree checks pass; all -review/fixture subprocesses finish. No build, provider or hosted execution is -repeated. A fresh second diagnostic review round remains required. - -**Diagnostic correction, second independent round.** Two different reviewers -inspect `330a8e2e..e7a5bf04`: `gpt-6-astra` at `medium` and `gpt-6.1-sol` at -`high`. Both approve without an actionable finding. Each independently passes -the focused projection and removed-mapping negative; the second also passes all -43 offline controls and literal/path/line/trace/output-boundary probes. The -launcher is byte-identical to its baseline after removing the one added mapping. -Whitespace and clean tracked-worktree checks pass; all review/fixture -subprocesses finish. Both diagnostic review rounds are complete. No provider or -hosted qualification is claimed; the failed lifecycle receipt remains unwaived. - - -### P02b-6 additional verification and correction pass (2026-10-22) - -**Status: implementation and local validation complete on `development`.** -Source-bound reviews and correction evidence are recorded below. -[PR #34](https://github.com/HodeTech/LearnStack/pull/34) records current-head -hosted qualification and maintainer review; merge remains separate. External -review assertions are hypotheses until checked against current source or retained -execution evidence. They do not authorize policy changes, host mutations or -cleanup of another task's resources. No next packet or merge starts here. - -The preceding source `57772a2a` has a complete successful hosted execution in -[run `39668841753`](https://github.com/HodeTech/LearnStack/actions/runs/39668841753), -attempt 1: all 27 jobs and seven required contexts pass. Independent artifact -verification binds ordinary-6's 224 distinct passing records to that source; -all three cancellation/restart variants pass, in approximately 24.3–24.5 seconds. -This does not explain or erase earlier failed variants. The failed receipts and -missing error payload are linked by the preceding triage and diagnostic record; -a green run is neither a root-cause analysis nor a reason to relax a deadline. - -ADR-0063 requires materially different full A/B assignments for rollout and -plan/algorithm/fixture-lifetime changes. Normal later pushes require one complete -assignment. Earlier references to current-head A/B are qualification requests for -their recorded changes, rather than an additional permanent requirement on every -push. The `abd45611` A/B receipts remain historical and source-bound. Advisory -weights and source provenance have changed during this packet; unchanged VM counts, -aggregate names and execution ceilings do not mean the plan file is unchanged. - -#### Verified corrections and retained boundaries - -- Actual Compose argv selects a nonsecret, process-only web-secret placeholder - only for recognized lifecycle commands and exact `config --services`. - Container-capable, ambiguous and full-config invocations remain strict. - Private-file ownership/type/link/permission checks remain mandatory: lifecycle - parsing is not permission to read an unsafe secret file. No source file or - provider credential is changed by the placeholder. -- Seed recognizes only locally typed, fixed Compose-selection notices. Demo - setup cancellation exits 130 after owned cleanup; command/readiness deadlines - retain their closed reason. Arbitrary provider/configuration text remains - outside public diagnostics. -- Migration credentials are removed from the inherited environment before tool - restore/build and supplied only to no-build EF children. The migration skill - uses that same environment-only pattern instead of a secret command argument. -- `public-env` qualifies, reads and writes one no-follow descriptor. It refuses - unsafe mode, ownership, link count, file type and size before reading, and no - longer follows a symlink or silently changes permissions. Copied-CLI controls - cover successful preparation, retained secrets, truncation and refusals. -- Node controls exercise forbidden credential destinations, exact issuer/custody, - independent callback/password-grant repair, username query behavior, actor - collisions, created-account checks and lost-write readback. The inherited-secret - exclusion control now contains matching and unrelated canaries. These are - behavioral checks; census counts alone cannot establish assertion adequacy. -- The actual production workflow validator rejects disabled, nonblocking, missing - or duplicate realm-test gates. Offline mutants call that validator; testing - command-string presence alone is insufficient. -- Actor-format and scope-collision export controls use nonlegacy personas so the - separate legacy identity binding cannot mask the rule under test. The latter - retains its own deterministic replacement-actor specimen. -- Failure receipts add only recognized, finite top-level adapter exception kinds. - An unlabelled xUnit assertion or unknown exception remains unclassified; no - message-text guess, raw exception, provider payload or new success witness is - introduced. This improves future diagnostics without diagnosing a lost error. - -#### Findings requiring no new runtime policy - -Proxy casing variants, private CA/package-cache prerequisites, Docker context/config -handling, transport-abort remapping, lock-initialization cleanup and certificate -validity had already been corrected. Existing ID-token expiry, independent expiry -predicate, session-clamp and live TTL controls are retained. The issuance proof uses -its measured clock window and separate readback; it does not promise exact -`exp - iat == 900` or replace that contract with a guessed five-second interval. -The production backchannel's certificate/hostname checks remain intact. - -The committed BFF example is public development data, whereas a missing runtime key -has no automatic fallback; the guide now states both facts. Automatic rotation, -removing the retained API service account/credential, narrowing the accepted full -scope or removing retained provider features are policy changes, not demonstrated -regressions. The approved account-console capability has its own dated maintainer -acceptance above. LearnStack application permissions remain separate. - -Redundant protection mutants need not all fail independently when another operative -check enforces the same refusal. The declared test-file census does not claim to -detect an empty assertion body. A named legacy migration literal is bounded tooling -data, rather than evidence of a domain-specific application branch. Broad historical -CLAUDE consolidation is outside this minimal correction; history is preserved. -Raw historical review transcripts are not committed evidence. Dated summaries and -source commits record the available scope/results; this pass does not invent missing -transcripts or infer a review's validity from elapsed time alone. - -Fresh independent correction rounds and source-appropriate hosted qualification -follow the implementation receipts below. Author checks are not independent reviews. - -[ADR-0068](../decisions/0068-development-warm-realm-qualification.md) is a -Proposed warm-realm correction. Acceptance would change first-write ordering and -permit three independently qualified stock-console assignment detachments. Separate -approval is required before dependent implementation. Existing visibility and -account-console refusals remain active; approval would not itself -prove complete stock-main upgrade compatibility. - - -#### Initial correction validation and tooling review - -The lifecycle correction is committed as `7e8c54f7`. Author controls pass 187 -lifecycle/migration cases and ten held-file CLI cases. Two fresh first-round -reviewers inspect `57772a2a..7e8c54f7`: `gpt-6-astra` and `gpt-6.1-sol`, both at -`high`. They independently pass twenty file/migration cases and 177 demo cases, -respectively; the latter validates JSON with the repository report guard. The -security review demonstrates one additional defect with a fake `dotnet`: the -skill's explicit build can fail and still reach `--no-build` EF in a shell -without errexit. The corrected example uses a subshell and guards build success; -three isolated shell controls prove no EF after failed build, EF-only credential -custody and preserved build/EF failure statuses. No real database is used by -those shell controls. The complete correction still needs its fresh full reviews. - -The expanded author validation passes **251 source-censused Node cases**, all -**43 launcher controls**, six Node-gate controls and sixty combined -shard/aggregate controls. Root validation passes **1,801 frontend cases** in two -packages with the actual repository guard, zero skips/todos. Fresh Integration -and Architecture Release builds produce zero warnings/errors. All three offline -export cases and seven corpus/Docker-trait cases pass. - -Three separate serial testhost invocations execute all three existing native -cancellation/restart variants: **nine passed, zero failures/skips**. Command -wall times are 76.669s, 74.219s and 85.571s, including fixture/runner work; these -are not per-case durations. The same three exact case IDs occur in every run. -All testhost process groups join, and direct inspections confirm absence of -each invocation's two exact created container IDs. The first immediate readback -still finds one owned container; later reads of those same IDs confirm absence. -That first observation is retained, not rewritten as immediate cleanup. No -foreign-resource inventory or cleanup, runtime fix, retry-until-green, deadline -increase or historical root-cause claim accompanies these results. - - -#### Complete correction reviews - -Two fresh reviewers inspect the complete `57772a2a..dbc8e025` correction, -including the guarded migration example: `gpt-6-astra` and `gpt-6.1-sol`, both at -`high`. Both approve without an actionable finding. They independently pass all -251 Node cases, 43 launcher controls and six Node-gate controls; the proof reviewer -also passes the sixty combined shard/aggregate controls. The separately executed -nineteen aggregate cases are included in sixty, not additional coverage. In -isolated source copies, the new username/census controls pass clean and fail when -their respective production `exact=true` or `exact=false` parameter is removed. -All review subprocesses join; no provider or .NET execution is repeated. - -Two different fresh second-round reviewers inspect that same complete correction: -`gpt-6.1-sol` and `gpt-6-astra`, both at `high`. Both approve without an actionable -finding. The security reviewer independently passes 197 focused frontend controls -across the four affected suites. The proof reviewer passes 251 Node, 43 launcher, -six gate and sixty combined controls. Its initial hyphenated-file `unittest` -discovery executes zero cases and is excluded from evidence; direct script runs -supply the recorded results. All review subprocesses join. Proposed ADR-0068, -its later documentation revision and new hosted qualification are outside these -code approvals. Both full correction rounds are complete; none establishes the -historical cancellation failure's cause. - -#### Historical-realm and account-capability feasibility - -A separate private archive at `57772a2a` uses the existing owned PostgreSQL-backed, -TLS-qualified Keycloak 26.6.2 fixture. The historical tenant import is exactly -`24705a7a`'s export, SHA-256 -`39659a4e505c8ad3c1b2963e69e58dadb725e4fb37b408dcf87214a2bb0d2d07`. -Temporary measurement source and raw output remain private; these are decision -support probes, not committed regressions or automatic-path qualification. -Intermediate harness compile/assertion failures are not counted as product defects -or passing qualification. No private workstation environment is read or changed. - -The original visibility guard refuses `plan/identity_conflict`, zero writes. -Test-owned append of three canonical admin-only definitions has independent full -profile deep-equal readback and reveals the existing legacy attribute. The tool -then refuses `plan/unsupported`, again before ordinary mutations. Assignment -summaries omit protocol; full by-ID reads identify six default and five optional -OIDC scopes. A SAML explanation is not the observed result. The current -bootstrap-parity control derives from today's export and cannot establish this -historical bootstrap path. A separate exposed-conflicting-actor probe preserves -the original account/credential and still refuses with zero reconciler writes. - -An initial feasibility variant manually detaches all eleven console assignments, -then the unchanged reconciler completes thirteen mutations and a zero-write rerun. -One legacy provider ID and its complete credential hash remain unchanged. Actual -code/S256 exchanges validate signed identity/scope for all four personas; console -code/S256 and Account REST GET succeed. Its one Fact passes in 29.52s; TRX SHA-256 -is `1d6f21549028cd903a1d276bb3df480163cbf45507b1c0dcab218ea5710b6a64`. -Both exact fixture containers and the network are directly confirmed absent. - -The narrower follow-up removes only default `roles` and optional `microprofile-jwt` -and `offline_access`. A private copied account module resolves full scope IDs and -binds ID/name instead of assuming summary protocol. Five default and three optional -assignments remain. Thirteen ordinary mutations, preserved legacy ID/credential -hash, zero-write rerun, four strict signed personas and console Account GET 200 all -pass. Its one Fact takes 28.95s; TRX SHA-256 is -`d205a91fce22cfdfd730994b0ddd3dd215398d354bd5855c76ad11478f3cd255`. -The measurement-source hash is -`6224f96197cde534084e00c1073bb3cd32387ccb08e2d71916bdce80800eed70`; -the private account-module variant hash is -`b7db43895726f3964f8da64686167677f5b4fc56c8c611e78dfc6a7e00d22c59`. -Both exact fixture containers and network are directly confirmed absent. This -variant is not the unchanged reconciler. It does not prove automatic preparation, -canonical-stock discrimination, planned DELETE ordering, uncertainty recovery or -preservation for every customized realm. ADR-0068 requires those regressions after -approval; its proposed three-edge path preserves compatible remaining scope state -and needs no durable continuation marker. - -A fresh-import BFF-token probe independently demonstrates Account REST GET and -ordinary profile POST, with stored-field readback. A protected actor replacement -does not persist. Removing the owned account capability and obtaining a new token -produces Account REST 401. The explicit JSON Accept header matters: a preceding -HTML/405 observation is not an account-authorization proof. Under current profile -settings, an ordinary email POST returns 204 but leaves email, username and actor -unchanged; original login and zero-write reconciliation still work. Pinned -Keycloak's ACCOUNT email condition explains the read-only projection. This does -not qualify the separate UPDATE_EMAIL required-action journey. Existing provider -self-service capability remains accepted; automatic email rebinding or a narrower -BFF token capability is not introduced. Its exact fixture pair/network are absent. - - -#### ADR-0068 proposed correction plan and first review - -The maintainer decision covers ADR-0068 and these three correction steps together. -They are Proposed; no dependent runtime starts before approval. Each implemented -step receives a commit, two fresh independent review rounds, verified fixes and -another commit before the next step proceeds automatically. - -1. **Qualified console graph.** Record acceptance and pending catalogue extensions - while retaining shipped Implemented coverage; - add the immutable historical fixture/canonical bootstrap expectations. Resolve - assignment IDs through full representations, preserve compatible graphs and - plan only the three qualified detachments. Prove custom/alias/category/role/ - mapper refusals, partial last-edge recovery and existing grant preservation. -2. **Owned visibility preparation.** Reuse all identity-independent qualifiers - before one absent-definition preparation within the existing lock/deadline. - Add exact trigger/stage/write accounting, durable-progress notices, exact - profile readback and a discarded/rebuilt full plan. Preserve readable prior - definitions during preparation; retain any separately planned ordinary PUT. - Prove real stock upgrade with changed credentials/MFA and hidden-actor - refusal after metadata only; exercise malformed/oversized/uncertain progress, - cancellation and explicit rerun without automatic replay or identity overwrite. -3. **Complete integration and qualification.** Exercise both seed/demo entries, - four-persona signed API issuance and manifest/nonmanifest console self-service, - all protected attributes and shared claim changes. Reconcile catalogue owners, - counts, guides and case/plan evidence. Run source-appropriate complete hosted - qualification under ADR-0063, including full A/B where its change triggers apply; - all seven checks and existing ceilings remain required. No merge or next packet - is authorized by this plan. - -Two fresh first-round reviewers inspect the revised three-edge proposal and its -carriers at `2ef9cf97`: `gpt-6-astra` at `xhigh` for security/design, and -`gpt-6.1-sol` at `high` for governance/proof honesty. Both approve as Proposed -without a verified Blocker/Major. The governance review finds three long prose -lines; they are reflowed without policy changes. It independently passes seven -parser controls, 731 links/fragments and whitespace checks, and verifies the -historical export hash and exact phase quotes. The design review confirms the -subset/last-edge compatible handoff and no additional Minor. All subprocesses -join; neither reviewer repeats provider execution or grants implementation approval. - -Full frontend typecheck independently finds three fixture-only child environments -missing Next's required `NODE_ENV`. The correction explicitly supplies `test` -without inheriting credentials or changing production filtering. Complete frontend -typecheck and lint pass; the four affected suites pass all 197 cases. Fresh -independent checks of this small correction follow before publication. - -#### Final proposal and fixture correction reviews - -Two first-round reviewers inspect the three isolated `NODE_ENV` additions and -proposed plan at `55ff0fe5`: `gpt-6-astra` at `xhigh` and `gpt-6.1-sol` at -`high`. Both approve the fixture correction and approve the plan as Proposed, -without an actionable finding. The latter independently passes seven parser -controls, 306 relative links/fragments and whitespace, and confirms all three -prior wrapping corrections. No frontend execution is repeated by these reviewers. - -Two different fresh second-round reviewers inspect the complete final ADR-0068, -carriers, plan and fixture correction at that same source: `gpt-6-astra` at -`xhigh` and `gpt-6.1-sol` at `high`. Both approve as Proposed, and separately -approve the fixture fix, without an actionable finding. They verify the exact -phase replacements, stock-ID qualification, compatible-mode priority, partial -last-edge recovery, preserved budgets and pending automatic proof. The governance -review independently passes 729 links/fragments and whitespace; both verify the -historical export hash and pinned provider premises. All review subprocesses -join. No build, provider or full frontend execution is repeated. - -Both fresh independent rounds for the small fixture correction and final proposal -are complete. Author verification passes seven parser controls and all 1,065 -scoped relative links/fragments; ADR-0068 still parses as Proposed. Its decision -and three-step implementation plan require separate maintainer approval. The -existing guards remain active; these reviews do not grant runtime authority or -qualify the final source on hosted CI. Publication and its complete current-attempt -assignment follow independently; historical green receipts remain source-bound. - - -#### Maintainer follow-up findings and conditional acceptance authority - -The maintainer directs verification of the remaining findings, correction of -still-valid issues, then acceptance and implementation without another approval -request. This is conditional authority, not a claim that outstanding checks or -new runtime have already shipped. - -The metadata-only first draft's missing second obstacle is superseded by the -current three-edge decision and the two existing phase feasibility receipts. -Those receipts remain private decision-support experiments: the automatic path, -canonical discrimination and actual self-service POST still need committed proof. -The read-only assignment-summary defect is independently corrected under the -existing compatible-scope contract; it grants neither preparation nor DELETE. - -Verified design corrections require every identity-independent refusal/capacity -check before preparation, an exact missing-definition/unmanaged-policy trigger, -admin-view-only preservation, a closed preparation stage and durable-progress -notice, and accounting for preparation plus a separately planned ordinary profile -PUT. All other Admin REST writes are ordinary mutations. The exact three DELETE -paths/status, baseline extraction/regeneration prohibition, opt-in/partial/manual/ -temporary-visibility alternatives and provider-change/retirement triggers are -explicit. Existing Implemented catalogue status/counts remain; acceptance adds -pending extension paragraphs and precise Asserts boundaries instead of erasing -shipped coverage. No universal console role-loss or relative BFF security claim -is inferred without token evidence. - -Raw 26.6.2 source confirms that browser-rendered line indices omit blank lines. -The earlier review's substantive premises hold, but several GitHub line anchors -were wrong. The current draft and mutable guide correct physical source spans; -previous dated review receipts remain intact. The implicit-to-stored profile -configuration consequence and shared-budget worst-case refusal are stated. -A fresh source-bound token/action measurement follows; it cannot replace final -automatic-path qualification. - - - -#### Additional console measurement and independent compatible-read correction - -The independent compatible-read correction is `25de7a61`: full scope GETs bind -summary ID/name/protocol before existing allowance/mapper checks. The provider -fixture now models actual two-field assignment summaries. Author validation -passes 256 source-censused Node cases and six gate controls; no preparation or -DELETE authority is added. Two fresh correction review rounds follow. - -A new private measurement imports the same exact historical export into pinned -26.6.2 and captures 83 endpoint representations, including full console scope, -mapper, allowance and referenced role/composite state. Graph SHA-256 is -`183f1790db8e500a04f8fd16bde0f105455d63bc143b99d7dc8d04106b5d0881`; -measurement-source hash is -`cb50701c8bb182ca16b93e31f67dfb36f86b7f8d00b956b8dd91de24725a40fd`; -the console receipt hash is -`489189669f7e1e548d537b8126e610d5e8cac1a3cb8387c95cd063f38b8796df`. -This captured input is not a qualified production baseline or automatic-path proof. - -For the two existing users, stock `openid` access has seventeen claim keys, no -audience and no realm/client roles. The three test-owned detachments leave it -unchanged. ID tokens retain nineteen keys and console audience. Explicit -`microprofile-jwt` adds only `upn` before detachment; afterward authorization -refuses that scope. Both stock clients directly report full scope false. After -thirteen ordinary writes, all four console access tokens add only the observed -account audience and `manage-account`/`manage-account-links` role projection; -ID claims remain unchanged, and a fresh pass writes zero. The final private Fact -then rejects its own overstrict role-hash equality assertion on the intended grant -addition, before POST. This is a harness failure, not a product defect or passing -regression. Actual profile POST/readback remains unverified by this run. Earlier -compile/assumed-audience/missing-user/optional-scope expectations are measurement -errors and excluded. Every measurement process joins; exact owned container IDs -and networks are directly confirmed absent. No foreign resource is inspected. - -The hosted correction run -[`39687329554`](https://github.com/HodeTech/LearnStack/actions/runs/39687329554) -at `8e914a8b`, attempt 1, independently fails ordinary-10. Its immutable artifact -`12387397602` has API-verified SHA-256 -`30be17f155a2c7bbd0bc0b6a31beba3294a62b46450a7a4f4aef985fa4de153e`. -The completed records contain 241 cases and one failed knownFailure=false Outcome -ACK/held-cleanup variant, ID `4172c42b-b84f-59bf-426f-60d6c521ec52`, in 61.95s. -Its sibling passes in 17.19s. The failed execution requires forced cleanup and -lacks successful owned completion. No assertion/location is retained. This is a -different method from the earlier cancellation/restart failure; duration alone -establishes no cause. Investigation and any verified diagnostic correction remain -separate from ADR-0068; no deadline or ownership witness is relaxed. - - - -#### First revised-decision and compatible-read correction review - -Two fresh independent reviewers inspect `8e914a8b..2c06b4a6`: `gpt-6-astra` and -`gpt-6.1-sol`, both at `high`. Both approve the compatible-read correction and -approve the revised ADR for conditional acceptance, without Blocker/Major. The -governance review finds one long plan line; it is reflowed without changing scope. -It independently passes all 256 Node cases, six workflow/census controls, seven -parser controls, 306 relative links/fragments and whitespace. Both verify the -corrected physical provider spans, pre-preparation refusal requirements, preserved -readable definitions, two distinct profile calls, diagnostics/accounting, exact -DELETE paths, baseline limits and pending catalogue extension. All subprocesses -join; no provider, .NET or full frontend execution is repeated. A fresh second -review follows before the acceptance/implementation handoff. - -**Failed-envelope interpretation.** The new ordinary-10 archive is not evidence -that Docker remained live or that native runtime ownership leaked. The launcher -sets `forcedCleanup=true` for failed workload status and sets `dockerAbsent=true` -only on its success path; `owned_completion_missing` also rejects nonzero workload -status despite joined cleanup. Its `cleanupOwnershipComplete=true` is retained. -The successful-completion claim correctly fails, but its cause needs actual test -evidence. NativeSettlement was absent from the finite source projection; the -separate diagnostic correction adds only that literal source and a closed code, -with planted privacy/near-match controls. No deadline, runtime or success witness -is changed by that diagnostic correction. - - - -### ADR-0068 acceptance and implementation (2026-10-22) - -**Status: Accepted; three implementation steps authorized.** The maintainer directs -correction of still-valid review findings, then acceptance and implementation -without another approval request. Both fresh revised-decision review rounds are -complete. The second pair inspects `02b886f7`: `gpt-6.1-sol` and `gpt-6-astra`, both -at `high`, approve the compatible-read correction and revised decision without an -actionable finding. Both independently pass 256 Node cases, six gate controls, -43 launcher controls and whitespace; every subprocess joins. Their separate first -review approves `d3e69b7e`'s finite source diagnostic; its fresh second review remains -required and is included in Step 1's correction review scope. - -ADR-0068 is now Accepted — 2026-10-22. The two original phase clauses receive dated -bounded replacements; the Step 2 review receives an adjacent remedy follow-up. -Security 11, Architecture 13, Keycloak guidance, index and front doors distinguish -accepted authority from pending implementation. The two existing catalogue rules -retain Implemented status/counts with dated pending extension Asserts and owners. -No Accepted ADR body other than this newly accepted decision is changed. - -The three correction steps above proceed automatically with commit and two fresh -independent review rounds per step. Step 1 qualifies the fixed historical graph -and scoped detachments; Step 2 adds owned preparation and fresh planning; Step 3 -completes actual-provider/lifecycle/POST/CI proof and catalogue extension delivery. -No automatic-path activation, complete upgrade claim, green final-source CI or -merge follows merely from acceptance. - -Acceptance-carrier checks pass five CorpusConsistency cases, seven ADR parser -controls, 1,454 actual Markdown relative links/fragments and whitespace. The parser -reports Accepted; the index has exactly one Active ADR-0068 row. Existing inline -code examples are not treated as live Markdown references. - -The bounded native-settlement investigation executes three serial paired runs: -all six cases pass on an isolated `2c06b4a6` source, whose backend is identical to -failed source `8e914a8b`. Release build passes without warnings/errors. All exact -six observed fixture containers are directly confirmed absent without forced -removal; no created network is observed. macOS/SDK 10.0.302 differs from hosted -Linux/10.0.402. This is targeted evidence, not the lost assertion's root cause or -a waiver of the failed hosted assignment. No runtime, deadline or ownership -witness is changed; final source still requires complete qualification. - -### ADR-0068 Step 1 — qualified stock assignment implementation (2026-10-22) - -The first correction step adds full stock-graph qualification and the closed -assignment-only DELETE owner. Compatible existing graphs retain priority, -including compatible custom definitions with historical scope names. Only a -successfully read, definitively incompatible graph can reach the fixed historical -qualifier. Unknown fields, wrong IDs/categories, extra edges, mapper/configuration -changes and unqualified role/composite/container bindings refuse before apply. - -The committed stock expectation preserves stored and effective mapper DTOs -separately; generated IDs are normalized only after independent current reads. -The [extractor](../../scripts/extract-development-realm-stock-console.mjs) checks -an observation against that fixed expectation and cannot overwrite it. Its -[provenance](../../scripts/development-realm-stock-console-baseline.json) records -the original historical source, credential-only fixture transformation, provider -image observation and independent capture/extraction hashes. The committed -historical fixture replaces exactly three published example credential values -with placeholders; the provider test injects test-only values in memory. No other -historical configuration is changed. - -Only opaque qualified bindings can invoke the Admin owner's three assignment -paths, each requiring HTTP 204. Their projected remaining graph must pass the -normal compatible policy. A concurrent or uncertain response ends the pass; -explicit reruns qualify the durable remaining subset, and the last incompatible -edge hands later passes to compatible preservation without a marker. All eleven -global stock definitions, account role closure and other clients' prior edges -remain protected. An ordinary repair of a qualifying stock definition refuses -before writes rather than invalidating its own preservation witness. - -Local offline validation passes 287 exact executed Node cases across six -source-censused files, six census/workflow controls and 43 native-launcher/parser -controls, with no cancellations, skips or todos. The actual-core controls cover -exact DELETE paths, all seven incompatible subsets, compatible custom priority, -non-204/lost acknowledgement, explicit resumption, transport/JSON refusal and -conflicting projected global-definition changes. The NativeSettlement diagnostic -correction remains separately source-bound; these results establish no cause for -the failed hosted case and waive no required check. - -The new `TenantRealmStockBaselineTests` passes both real-provider Facts in -47.1781s after a Release build with zero warnings/errors. The first imports the -credential-redacted historical fixture into pinned 26.6.2 and independently -captures 89 endpoint representations, including account assignment reads and the -four referenced role-name/ID/composite bindings. It matches the fixed canonical -hash recorded in the provenance; a second fresh bootstrap changes generated IDs -while preserving that same canonical shape. Actual image identity is recorded -for the observed Linux/arm64 fixture, not asserted as a universal platform ID. - -The second Fact explicitly appends the three definitions as test-owned setup, -then invokes the production ordinary reconciler: sixteen mutations, followed by -zero on an explicit rerun. It independently verifies the five default/three -optional console edges, unchanged eleven stock definitions/roles, existing IDs, -credential DTO hashes, private API secret and other retained state. The two named -clients' separately approved managed-scope additions are explicitly projected; -other clients' assignments remain exact. An earlier harness rejected those -intended additions after successful sixteen-write convergence. The corrected -preservation predicate and complete two-Fact rerun pass; that earlier run supplies -no passing whole-ordinary-path receipt. All four final-run containers and both -networks are independently absent after joined disposal. - -Seven corpus/Docker-trait cases, seven ADR parser controls, 864 scoped relative -links/fragments, project-scoped C# whitespace verification and diff whitespace -checks pass. The broader solution format invocation reports a local workspace -loading warning and exits nonzero; the explicit integration-project verification -covers the three changed C# files. Current-source hosted checks remain required. - -Committed-source review rounds follow before this step closes. This step supplies -no production preparation implementation, password/MFA login or token/profile -POST proof, full 120-second automatic-path claim, hosted qualification or complete -ADR extension implementation claim. Those remaining proofs retain the following -steps' owners. - -#### First independent Step 1 review and interruption correction - -Two fresh reviewers inspect `db3778c8..57497f01`: `gpt-6-astra` at `xhigh` -for security/runtime/proof behavior and `gpt-6.1-sol` at `high` for provenance, -corpus and test meaning. Both find one persisted proof gap: the original -non-204/lost-acknowledgement loop interrupts only the first DELETE. The successful -subset controls do not establish uncertain failure after the final edge followed -by compatible-mode resumption. Both independently reproduce the later positions -successfully; no runtime defect or new decision is claimed. - -The corrected existing control now covers all three deletion ordinals for each -non-204 response, lost acknowledgement and cancellation. It checks the exact -stopped durable prefix, no repeated DELETE, remaining write counts of three/two/ -one, five default/three optional retained edges, last-edge compatible handoff and -subsequent zero-write convergence. The six-file guarded Node census again passes -287 exact cases, with zero cancellations/skips/todos. Runtime behavior, deadlines, -mutation authority and provider expectation remain unchanged. - -The first reviewer independently passes 67 guarded focused Node cases, 43 native -controls and six supplemental lost-acknowledgement/cancellation scenarios. The -second independently passes the full 287-case Node census, 43 native controls and -supplemental resumption probes. Both independently verify historical/redacted -fixture transformations and hashes, capture/extraction provenance and the bounded -pending-proof claims. Both approve the separate acceptance carriers and provide -the second review of the finite NativeSettlement diagnostic correction. Neither -reruns a provider or build; all review subprocesses finish. A different fresh -second review pair follows this committed test correction before Step 1 closes. - -#### Second independent Step 1 review and closeout - -Two different fresh reviewers inspect `db3778c8..72ee83a5`: `gpt-6.1-sol` at -`xhigh` for security/runtime/proofs and `gpt-6-astra` at `high` for governance, -provenance and test meaning. Both approve without an actionable finding. Both -independently pass the full six-file 287-case guarded Node census and verify -source/redacted/patch/canonical/extraction hashes. The first additionally passes -nine interruption-before-commit probes spanning all DELETE positions. The second -passes six gate controls, 43 native controls and seven ADR parser controls, and -independently reproduces canonical extraction from the private 89-endpoint capture. -Whitespace checks pass. Neither repeats provider/build execution or claims hosted -qualification; every review subprocess joins. - -Step 1 is complete locally after both independent review rounds and its verified -proof correction. Step 2 now proceeds automatically under the same Accepted -three-step authority: bounded metadata preparation, all identity-independent -preconditions first, durable-progress diagnostics and fresh complete planning. -Step 3 retains automatic-path, token/password/MFA/self-service and final-source CI -qualification. Nothing here accepts a background-job failure or authorizes merge. - - -### ADR-0068 Step 2 — owned visibility preparation (2026-10-22) - -The second correction step implements the exact missing-definition/closed-policy -trigger. A preparation probe reads actual provider state and reuses the ordinary -planner's identity-independent qualifiers and capacity checks. It defers only -visibility-dependent identity admission; it invents no account projection or -ownership. Provisional ordinary actions never escape the probe. A successful -probe returns only the absent-definition append and its private exact verifier. - -The owner dispatches at most one preparation PUT, requires HTTP 200 and a JSON -object, then separately GETs and compares the entire profile, including ordered -arrays and unrelated fields. Existing admin-view-only definitions remain exact. -All prior projections/actions are discarded before a fresh complete plan; any -separately necessary ordinary profile PUT has its own admission and write count. -Known independent secret/client/mapper/scope/account/group/storage and byte/count -conflicts refuse before preparation. Newly revealed identity conflicts may leave -metadata durable but admit no ordinary mutation. - -The closed `prepare` stage and dispatched-progress flag survive transport loss, -cancellation, deadlines, later plan/apply/readback refusal and outer cleanup or -lock-release errors. The fixed failure notice instructs inspection of current -realm state before an explicit rerun. Progress is recorded at actual transport -handoff after refresh and pre-dispatch cancellation checks, without claiming a -provider commit merely because the request was dispatched. All ordinary mutation -counts also use this conservative handoff boundary. The existing five-second -request, 120-second pass and response/body/refresh budgets remain unchanged. - -The guarded Node census passes 335 executed cases across seven exact files, -with zero cancellations/skips/todos. Twenty-two new pure preparation controls -include the complete trigger table, preserved readable definitions, strict -profile equality and independent refusal/capacity pairs. Sixty-two core and -24 entry controls exercise actual transport ordering, fresh replanning, separate -profile writes, malformed/non-200 responses, lost acknowledgement, cancellation, -deadline and durable-progress preservation through owned cleanup. These offline -controls do not prove real-provider convergence or final-source hosted fit. - -The actual-provider focused run passes all eleven cases without retries or -skips in 289.261s after Release builds with zero warnings/errors. Seven new -cases exercise the true historical automatic path (seventeen writes, then zero), -a hidden actor (one preparation, fresh-plan refusal, no ordinary writes), -independent secret/custom-stock conflicts (zero writes), lost acknowledgement and -cancellation (one dispatched preparation, explicit sixteen-write resume, then -zero), and partial admin-view-only preservation followed by a separately counted -ordinary profile PUT. Four existing hidden/default/selector variants also pass; -only the unmanaged-hidden variant now admits the exceptional metadata write. -The renamed theory says “before ordinary writes” rather than claiming zero total -writes for that variant. - -The retained TRX SHA-256 is -`89f40f90c099897aca2bfff0454407242dc9195035a4a4200c340040188c0fc9`. -Each new fixture joins disposal and independently checks its two exact container -IDs and network ID absent: fourteen containers and seven networks. The four -existing variants and shared collection fixture complete their existing cleanup; -no separate resource-absence observation is claimed for those lifetimes. -The historical positive control preserves actual provider IDs, password credential -DTO hashes, grants except the approved account capability, all preexisting global -scope definitions, API secret and Hub state. A credential DTO hash is not a -changed-password or MFA login proof. - -Seven corpus/Docker-trait cases, six census/workflow controls, seven ADR parser -controls, 1,283 scoped relative links/fragments, project-scoped C# whitespace and -diff whitespace checks pass. Committed-source independent review rounds follow -below before this correction step closes. Step 3 retains -complete seed/demo lifecycle, changed-password/MFA login, four-persona token and -manifest/nonmanifest self-service POST proof, request/phase cost and hosted -qualification. A passing Step 2 subset does not complete those obligations. - - - -#### First independent Step 2 review and partial-profile correction - -Two fresh first-round reviewers inspect `52c73e60..8b99de3`: `gpt-6-astra` at -`xhigh` for security/runtime/proofs and `gpt-6.1-sol` at `high` for governance, -reliability and test meaning. Both independently pass all 335 guarded Node cases -and reproduce a knowable refusal deferred until after one metadata PUT. With all -four accounts already present, a visible legacy tenant makes an ordinary account -update necessary, but an unrelated writable defaulted attribute's preservation -guard is skipped by the preparation-only branch. Both also reproduce a visible -actor mismatch or duplicate actor being deferred merely because another claim's -definition is missing. These are two verified Major mechanisms of overly broad -preparation deferral, not authorization to adopt conflicting identities. - -The correction derives readable claims from the actual current profile and reuses -the ordinary actor, field and duplicate-actor validators for those values. Only -checks depending on newly exposed values wait for the fresh full plan. The shared -attribute-preservation guard also precedes every prospective existing-account -write. Six new clean/dirty controls cover the profile-preservation failure, -readable actor mismatch/absence, the legacy absence exception, tenant/organization -disagreement, duplicate actor and the genuinely hidden-conflict boundary. The -complete source-censused suite passes 341 cases across seven files, zero -cancellations/skips/todos. The first provider receipt remains bound to the earlier -implementation. After the partial-profile correction, the same eleven actual -provider cases pass without retries/skips in 270.549s after a zero-warning/error -Release build. TRX SHA-256 is -`b701d3166e5266dab904ae7e921a08034db5d2f6683d17c605bc625c8fa5dc83`. -The seven new fixtures again independently establish fourteen exact containers -and seven networks absent after joined disposal; the existing fixtures retain -only their normal joined-cleanup claim. - -Both reviewers find no further verified diagnostic, cleanup, immutable-ADR or -catalogue-status defect; their limits explicitly exclude provider/.NET/hosted -execution. All review and counterexample subprocesses join without tracked edits. -A different fresh second pair reviews the committed correction before Step 2 -closes. Complete Step 3 obligations remain unchanged. - - - -#### Step 1 hosted mapper-reason regression and correction - -[Run `39694542640`](https://github.com/HodeTech/LearnStack/actions/runs/39694542640) -at head `52c73e60`, merge checkout `54730795`, finishes with 25 successful jobs -and failures in ordinary-1 and its integration aggregate. Ordinary-1 retains -220 executed cases: 218 pass and the two unsafe account-console direct/implicit -mapper variants fail. Artifact ID `12391396743` is independently bound to API -archive SHA-256 -`219bdb75b6f13537a9dba07ae386778a396898feb9869151d94e92cea18a77c4`. -The sanitized TRX exposes no assertion payload; empty finite failure locations -are not a diagnosis. Its failed completion envelope likewise proves neither a -runtime resource leak nor unjoined disposal. - -A targeted actual-provider invocation of those exact two rows reproduces both -failures, with no retry, at the reason assertion: stage `plan` is correct, -`unsupported` differs from the existing `mapper_conflict` contract. It is not a -startup failure. The invocation executes two failed cases, zero skips, in -61.217s; retained TRX SHA-256 is -`104eb1c6178f7002c40c902dd967e28fddbcdf7a597656f34e6a3a7a32e72b8d`. -The later zero-write/preservation assertions are not reached in that failed run -and supply no provider-preservation claim. Offline exact variants independently -refuse without writes. - -The stock fallback had reclassified direct mapper incompatibility while trying -its strict baseline. Direct mappers are outside assignment-normalization repair -authority. The correction qualifies that subset with the shared mapper policy -before fallback, preserving `mapper_conflict`. A direct subset need not contain -the resolver if its compatible scope supplies it; the complete graph still -requires exactly one resolver. Two new controls require the precise direct -refusal and prove inherited-resolver preservation plus duplicate rejection. -The full seven-file Node census passes 343 cases with zero cancellations, -skips or todos. The initial inherited-resolver test incorrectly placed it in a scope also -assigned to application clients, triggering their valid duplicate-resolver guard; -the corrected console-only scope isolates the intended existing compatibility. -The code does not weaken application mapper validation. - -The corrected-source provider subset passes all seven selected cases without -retries/skips in 179.348s. All five unsafe variants reach their final zero-write -and exact provider-state assertions; direct and implicit mappers retain -`plan/mapper_conflict`, while the other three retain `plan/unsupported`. Both -historical automatic/partial-admin-view proofs pass with their original write -counts, graph and state assertions. TRX SHA-256 is -`4497a991aab51936afb923cbd60aa6d01d9480a700211580f6a9fe0b183a1db8`. -The two new historical fixtures independently establish four exact containers -and two networks absent; the existing self-service fixtures finish normal -cleanup without a separate absence observation. Every invocation joins. - -Fresh independent reviews follow before this correction closes. No failed -hosted assignment or earlier native settlement failure is waived, and historical -green receipts remain source-bound. - - - -#### Entry-caller durable-progress preservation - -An author follow-through of the seed/demo call chain finds that their existing -outer cleanup can mask the new dispatched-preparation notice. Seed's finally -can replace either a prepared failure or a successful prepared result; demo's -cleanup replacement and local setup-cancellation wrapper can replace a prepared -reconciliation error. These callers are outside the already tested shared -reconciliation owner's own cleanup boundary. - -Ten targeted entry controls first run against unchanged callers. All five real -`RealmError` prepared-progress cases fail while all five nonpreparation twins -pass, isolating this propagation defect. The correction retains the closed -metadata notice through seed cleanup and failed-reconciliation demo cleanup or -local cancellation, without changing unrelated runtime/public-proof errors, -credential flows or the local cancellation exit convention. Six further actual -seed CLI cases extend the entry controls to sixteen additions. The complete -lifecycle file passes all 61 cases, zero skips, in 24.13s; workspace typecheck -and lint pass. Its changed test file receives the configured Prettier formatting. Prepared and unprepared twins prove error/result cleanup propagation, -fixed diagnostics and actual local CLI cancellation/cleanup exits. Successful -demo progress is not retained into unrelated renderer/runtime failures. All -commands join; no actual Compose/provider work is claimed by these stubbed -entry controls. Fresh independent correction reviews follow before closeout. - - - -#### First-round Step 2 correction verification - -Both first-round reviewers independently inspect `8b99de3..16771fc1` and approve -without a remaining verified finding. Each independently passes all 343 guarded -Node cases across seven files and all 61 lifecycle controls. The security reviewer -also passes ten supplemental assertion controls covering the original failures, -genuinely hidden legacy admission, direct mapper conflicts in compatible/stock -graphs and missing/optional-only resolver refusal. The governance reviewer -independently reproduces the old clean/default/visible-actor configurations and -confirms that each dirty version now refuses before preparation with zero writes. -Whitespace checks pass and every review subprocess joins without tracked edits. -Neither repeats provider/.NET/Docker/hosted execution or converts the reported -receipts into independently observed qualification. A different fresh second -pair reviews the whole Step 2 change before closeout. - - - -#### Second independent Step 2 review and closeout - -Two different fresh reviewers inspect the complete `52c73e60..3810b071` Step 2 -change and dependencies: `gpt-6.1-sol` at `xhigh` for security/runtime/proofs and -`gpt-6-astra` at `high` for governance, reliability and evidence meaning. Both -approve without a verified finding. Each independently passes all 343 guarded -Node cases across seven exact files and all 61 lifecycle controls. The security -reviewer additionally passes 92 visibility/mapper cross-product controls across -missing-definition subsets, four personas, visible/hidden conflicts and duplicate -actors, direct mapper failures and explicit rerun. Its first supplemental harness -omits an await on an async fixture; the corrected harness passes and supplies no -product-failure claim. The governance reviewer also passes seven ADR parser -controls and rejects an unverified metadata-capacity hypothesis after checking -the actual derived metadata and reserve model. - -Both verify unchanged Accepted ADR bodies, retained catalogue status/counts, -exact preparation/readback/fresh planning, early readable-fact refusals and fixed -caller progress diagnostics. Whitespace and tracked-tree checks pass; all -review commands join. Neither repeats provider/.NET/Docker/hosted execution or -claims that reported receipts are independently observed. Complete Step 3 proof -is still explicitly pending. - -Step 2 is complete locally after both independent rounds and verified fixes. -Step 3 proceeds automatically under the Accepted plan: genuine historical seed/ -demo entry journeys, changed credentials/MFA, strict signed API issuance and -manifest/nonmanifest self-service, measured request/phase costs, remaining -catalogue/carrier reconciliation and source-appropriate complete hosted checks. -No deadline, identity refusal, required check or earlier failure is waived. - - - -### ADR-0068 Step 3 — complete historical-path qualification (2026-10-22) - -The third correction step starts after Step 2 closes at `f714a5af`. Its provider -journey adds changed-password/MFA, strict signed persona/API issuance and -manifest/nonmanifest console self-service proof. A separate serialized owner -exercises actual seed/demo entries in private source copies with test-owned -historical bootstrap input. No new production seam or identity policy is inferred -from test setup. Complete request/phase costs, catalogue/carrier reconciliation, -case assignment and hosted qualification follow actual evidence. - -The private entry proof freezes `f714a5af`, keeps production scripts, Makefile and -the desired current realm byte-for-byte, and changes only the proof copy's Compose -import bind to an external owned historical-input directory. This explicit -bootstrap delta allows a newly occupied random CI project to start historical; -it neither prewarms a supposedly empty CI project nor mutates a workstation -realm. Credentials remain private, source attestation belongs to the proof copy, -and its results cannot replace untouched final-source hosted qualification. - -The first private entry experiment freezes source tree -`2b3663df5c8dd566158d8eaeaee12542530d7a6f`; its archive SHA-256 is -`41126981657cc35148af17c470ead345cdc23cde85af4c9e431effe0be4133f3`. -Only three historical credential literals are transformed in the private bootstrap -input; the Hub input is byte-identical. The desired export and production entry -sources remain unchanged. The private receipt SHA-256 is -`353fa9338bc155d363f2f54fc8da5321bfebd8b137d089d31540e700b6c38d17`. - -Actual `make seed` succeeds with seventeen writes, then zero on explicit rerun, -in 36.224 and 16.491 seconds. Independent reads confirm the original provider and -client IDs, credential DTOs, the complete appended profile, retained five default/ -three optional console edges and observed Hub state. The second full snapshot is -identical. Credential DTO preservation alone is not a usable password/MFA proof. -Natural teardown takes 10.416 seconds; all seven exact owned containers and the -owned network are independently absent, with no fallback or forced stop. - -The first actual historical `make demo DEMO_MODE=ci` experiment is **red**: -323.004 seconds, make exit 2, an audit worker exit 1 without a signal at lane 1, -lesson run 3. Nine page navigations and twenty-four visibility controls pass, but -only eight of twenty-seven Lighthouse report pairs complete. Each retained report -has no runtime error/warning and accessibility score 1.0; these partial results do -not establish the full audit suite. The initial two-user/eleven-edge state and live -four-user/eight-edge/three-definition convergence are independently observed. -The demo entry does not expose reconciliation mutation counts; none is inferred. -Its native public receipt SHA-256 is -`ad6a02b69c8561401312ad913e77d0826b579d743449c85a50cfaeeb884876d3`. - -The retained finite diagnostic establishes worker exit only, with no worker stage -or failed report; it cannot identify an audit, protocol or budget root cause. -Natural cleanup takes 10.722 seconds and all owned processes join. The selected -Compose project is empty; the two remaining container IDs and network captured -from the exact owned process tree are independently absent. Five earlier container -IDs were not observed, so their individual absence is not claimed. No retry, -threshold relaxation or automatic replay converts this failed receipt into success. -A separately recorded fresh experiment may assess repeatability; it cannot erase -this failure or substitute for final-source hosted proof. - -The committed historical journey in `TenantRealmApiTests.WarmQualification.cs` -starts the genuine stock profile/eleven-edge graph with a test-owned changed legacy -password, usable OTP credential and an already eligible nonmanifest account. -Immediate pre/post reconciliation snapshots avoid confusing subsequent successful -logins with credential metadata changes. All old provider IDs, credential DTOs, -groups/grants, unrelated account fields, global scope/role graphs, other-client -assignments, API secret and observed Hub state are preserved. Only the approved -manifest capability/identity changes and three console edges differ. - -The final-source Fact passes, one case and zero skips. Four independently signed -access/ID token pairs reach matching AccountSite hosts through the production -bearer handler and physical ReadOnly `learnstack_app` transactions. Changed -password/MFA work before and after; missing/wrong OTP refuses. Both manifest and -eligible nonmanifest users complete ordinary Account REST POST with independent -admin readback. All three protected attribute replacements fail to persist, and -fresh signed claims preserve the manifest identity/nonmanifest authority boundary. -ID-token access hashes are checked before comparing complete signed claim deltas. -The closed legacy-console profile alone admits an absent audience, while still -requiring signature, issuer, lifetime, purpose and `account-console` authorized -party; all normal web/API audience checks remain strict. - -Before upgrade, ordinary Account REST returns 401 for the legacy manifest user -and 200 for the already eligible nonmanifest user. The approved mapper/grant -changes add only the measured account capability; no universal role-loss or -security-gain claim is made. Explicit `microprofile-jwt` has the measured `upn` -access/ID delta before detachment; subsequent new requests for either detached -optional scope return the verified `invalid_scope` callback. An actual pre-upgrade -offline refresh succeeds and yields the credential retained for the later check. -Both original and newly returned refresh credentials are positively checked as -nonempty before the post-upgrade negative, preventing an empty-input false proof. -After upgrade, that credential returns 400 `invalid_grant`, with no access/ID token, -while its independently read offline session remains present. This is the observed -owned historical case, not a universal revocation or session-deletion guarantee. - -Production core passes perform seventeen, zero and zero writes. The third -explicit pass follows real self-service edits and preserves their stored fields, -credentials and grants. They issue 481/301/301 bounded requests in 3.126/1.352/1.280 -seconds; preparation uses two requests and the initial/fresh plan each use 112. -Fixture startup is separately measured at 19.130 seconds and token/API/profile -work at 13.220 seconds. These are small-fixture observations, not worst-case -capacity or deadline-fit bounds. The existing five/120-second request/pass limits -are unchanged. The Fact's exact recorded duration is 40.2057204 seconds; its TRX -SHA-256 is `3487a4510af4444908eaef908365e8cc4334b0dfc6a531b0af25276f49e657c9`. -A separate seven-file source manifest has SHA-256 -`92cde32454dfb23f0421ce4e2d92ffe3c054281138cfe2d8a2ebe8c734960da3`; -TRX does not embed a commit. Real disposal joins and both exact owned provider -containers and their network are independently absent. - -Exploratory red Facts exposed pinned v2 OTP-form differences and incorrect test -expectations for historical status/callback behavior. A redundant second failed -password stimulus also triggered the real provider's quick-login protection. -The fixture preserves the exact OTP credential selector and closed `invalid_scope` -error, removes that redundant stimulus and checks attack-detection state. No -provider security policy is weakened. The final-source Fact is rerun after those -harness corrections and scoped formatting, rather than treating an earlier -partially reached assertion as complete proof. Eighteen adjacent provider cases -and seven corpus/Docker-trait guards pass with zero skips. Integration and -Architecture builds have zero warnings/errors; scoped whitespace/style verification -passes for all six C# files. Only newline formatting and the two refresh-presence -proof guards follow the eighteen-case receipt; the final historical Fact runs -again against those exact bytes. -Independent correction reviews and full hosted qualification remain pending. - -The new historical journey source also receives one literal CI failure-location -code, `realm_warm_qualification`, with the existing bounded line projection. -No raw stack, path, message, token or provider value is exported. The existing -planted trace control fails without the mapping, then all forty-three offline -launcher controls pass with it. Source inventory includes the exact new partial -file; no diagnostic code is inferred from arbitrary filenames. - -Measured weights replace the renamed selector and cover the nine completed -Step 2 method groups. Two previously unknown historical-baseline methods gain -actual hosted durations from this Step 2 run's independently verified ordinary-1 -and ordinary-4 receipts: 98,022 and 102,868 milliseconds. Local row sums retain -the existing advisory scaling; hosted rows are not scaled. These weights are -assignment hints, not wall-clock upper bounds or proof of final hosted fit. -The offline shard/result controls pass sixty and nineteen cases respectively. -The journey adds a 91,318-millisecond advisory weight from its actual TRX row; -the plan now has 1,382 weights. Twenty explicit bounded VSTest discovery calls -complete in 20.356 seconds with all owned process groups/readers joined. Actual -ID/FullyQualifiedName metadata preserves all 5,919 earlier case identities and -adds only the new journey: 5,920 total, 3,350 non-Docker, 2,539 ordinary and 31 -native. Every changed selector belongs to that manifest; the retired selector is -absent. Source, plan, parsers and four Release assembly hashes stay frozen. - -On that same complete manifest, the revised plan moves 1,055 methods/2,289 cases -in layout A and 932 methods/2,018 cases in B relative to the Step 2 plan. Both -layouts have complete unions and materially different co-memberships. Maximum -filter/argv bytes are 15,491/16,137 in A and 26,048/26,695 in B, below the unchanged -32,768/65,536 limits. Unknown method weights fall from 53 to 43; those remaining -use the existing default and are not represented as measured. The manifest digest -is `c79e7e37f5304b3e27d966f0e628b80d8746872aa911933a52383c434ac4bc8e`; -the finite validation-summary SHA-256 is -`9f9f400132c21ff9ffd291a2bd4b606bd69f45199c79edfea347f4720210b4b1`. -This is complete metadata/assignment validation, not final-source execution. -The execution VM count of twenty, seven required names and whole-job ceilings -remain unchanged; both final hosted layouts still require execution. - -[Run `39699380813`](https://github.com/HodeTech/LearnStack/actions/runs/39699380813) -finishes successfully at Step 2 head `f714a5af`: all twenty-seven jobs and seven -required contexts pass. Checkout `d55ae6fc37b794e482c42ebbdd49d3e59a9c3f0a` -has the recorded source tree. The hosted fresh demo independently completes all -nine pages and twenty-seven hash-bound report pairs; it does not erase the failed -local historical-input experiment. Native proof passes all thirty-one cases, and -base passes 2,917 cases, with zero skips. Independent revalidation of all twenty -producer archives verifies API digests, current-attempt ownership and exact case -unions: backend 3,350 plus integration 2,569 (2,538 ordinary and 31 native), all -5,919 passing with no skips. Both aggregate receipts match recomputation using -that source's validators. The verification-summary SHA-256 is -`60cf4e7af91b76a512f717b6c7df875e996c7804edcc1197a29a92ab9a637012`. -The failed `52c73e60` assignment remains failed; its reproduced mapper -classification defect is fixed and independently qualified at this later source. -Final Step 3 source and its revised plan still require ADR-0063's materially -different complete assignments at the same frozen source, rather than borrowed -receipts. - -#### Step 3 first independent review round - -Implementation is committed at `ca3560df`. Two fresh independent reviewers inspect -the complete thirteen-file `f714a5af..ca3560df` change and adjacent authorities: -`gpt-6-astra` at `xhigh` for security and nonvacuous provider proof, and -`gpt-6.1-sol` at `high` for governance, assignment/evidence meaning and reliability. -Both approve without a verified Blocker, Major or Minor finding. Neither changes -repository files or executes provider, Docker or .NET/build/format commands. - -The security reviewer reads the complete historical journey and independently -checks the final TRX and seven source hashes. It verifies usable password/MFA -controls, strict web/API versus closed historical-console validation, nonce and -access-token hash binding, stored self-service/protected-field readback, the -positively nonempty offline credential and the exact preservation/cleanup claims. -It distinguishes the observed offline result from universal revocation and keeps -the failed historical demo and final hosted obligations visible. - -The governance reviewer independently verifies the eighteen adjacent and seven -corpus outcomes, all twelve timing upserts/one retirement/five sources and their -actual selector bindings. It reparses all twenty retained discovery diagnostics -to the exact 5,920-case manifest, preserving every prior case identity plus one -new case. Both complete assignment unions, distinct co-memberships, movement and -filter bounds recompute. All forty-three offline launcher controls pass, including -the literal finite failure-location projection. Accepted ADR bodies and catalogue -statuses/counts remain unchanged. All review commands join. A different fresh -second review pair and final-source complete hosted assignments remain required. - -#### Independent historical demo repeat - -One explicit independent repeat of the same historical-input experiment succeeds -without runtime, budget, capture or threshold changes. It freezes the same -`f714a5af` production archive and identical transformed historical/Hub inputs. -The private proof commit is `d7e981ab102b7ae4502789773f422ddba2b61a48`, tree -`304651aa11d636cc456b8bfd40ebb2142a429367`; its only source delta is the owned -Compose import bind, SHA-256 -`3a4773ed123eb159fafe2aae88a7e202485504fd93772c55819935a2769c755a`. -Production-source hashes remain equal and the private proof source stays clean. - -Actual `make demo DEMO_MODE=ci` exits zero in 662.279 seconds within the unchanged -1,200-second whole-run budget. Nine navigations, twenty-four visibility controls -and all twenty-seven JSON/HTML report pairs complete. All reports have no runtime -error/warning and accessibility score 1.0; all nine screenshots are inspected for -readability/clipping. All 134 observed API completions return 200, and both TLS -refusal controls plus the timeout refusal control pass. Independent reads observe -the original two users/eleven edges, then four declared protected identities, -eight retained edges and exactly three appended profile definitions. The unchanged -demo entry exposes no reconciliation mutation count; none is inferred. - -Natural cleanup takes 10.711 seconds. All seven proactively captured owned -container IDs and the network independently return not-found; the selected -Compose project is empty, private environment/lock files are removed and all -owned processes/readers join. No forced or fallback cleanup runs. The final -private receipt SHA-256 is -`64c647657a3a3afe671996d7da957c78e81cca4040fbd820ae80d463ead189d1`; -the native public receipt SHA-256 is -`ae53906f2a476abc4c3f208a2dd0daf646e838ef3ab2f4a8bf83b13b6f336cae`. -This completes the independently recorded historical entry proof. It neither -explains nor erases the first red experiment and does not replace untouched -final-source hosted qualification. - -#### Step 3 second independent review round - -Two different fresh reviewers independently inspect `f714a5af..ca3560df` and -one-hop dependencies: `gpt-6.1-sol` at `xhigh` for security, runtime correctness -and nonvacuous provider proof; `gpt-6-astra` at `high` for governance, CI/evidence -meaning and reliability. Both approve without a verified Blocker, Major or Minor -finding. Both read the entire new historical journey and all thirteen changed -files. Their review approval does not substitute for the separately executed -historical demo or final-source hosted checks. - -Each independently verifies the final historical TRX, its exact duration and all -seven committed source hashes. The security reviewer checks actual credential/ -MFA controls, nonce/access-hash binding, strict web/API and closed historical -console boundaries, physical application-role ReadOnly observations and stored -POST/protected-field assertions. The governance reviewer reparses all twenty -discovery diagnostics, verifies every prior identity plus the one new journey, -and recomputes both complete assignments, limits and local/hosted timing weights. -Both pass all 122 offline launcher/assignment/result controls; the governance -reviewer also checks that removing the diagnostic mapping breaks its planted -control. No reviewer executes provider, Docker or .NET/build/format commands; -all review commands join. Accepted ADR bodies and catalogue counts/statuses stay -unchanged. All three correction steps now complete their local implementation -and two independent review rounds. Full final-source A/B hosted qualification is -the remaining completion gate; no merge or P02b-7 work is authorized by this -record. - -#### Final hosted qualification - -[Run `39705264083`](https://github.com/HodeTech/LearnStack/actions/runs/39705264083) -freezes Step 3 head `ca3560df775ac86304fdfefbc0c3bf81cc118cef`. Checkout -`0d65aa34cf54d3424f1d7870c5a042a971e0b374` has that exact second parent and the -same tree, `e124af40d71057ba73657a925c32c67413956409`. No code, plan, deadline or -success witness changes between assignments. - -Attempt 1, layout A, passes all twenty-seven jobs and seven required contexts. -Its public demo archive is downloaded and independently verified before rerun: -all twenty-seven report pairs, nine screenshots, nine navigations and twenty-four -visibility controls pass. Its private verification-summary SHA-256 is -`aa0f3c673e83ca7bd5ffc10de14f36253c8251cd1ab09bc92a82c89fb2cb61a5`. -After the full rerun starts, prior artifact API endpoints return not-found; no -cause is inferred. Initial job-log capture is separately blocked by the installed -CLI's terminal-escape output guard, not an observed HTTP refusal. Using its -documented flag only into private pipes/files later recovers both original -aggregate log receipts. They report 3,350 backend and 2,570 integration cases at -the exact source/attempt; their private canonical receipt SHA-256 values are -`1242916895281b40c7e21d8d50f18a382904fa95a244fda953a6ab1a6a0e7a19` -and `c8602bea4b1c508a06ee1dcc65f4ae308749247f3e74a1091181d545efee688b`. -The original successful jobs API response and downloaded public proof also remain -retained, but complete independent producer-archive revalidation is not claimed -for attempt 1. The later A assignment is explicitly for complete retained -qualification evidence, not a failed-test retry or permission to combine siblings. - -Attempt 2, layout B, passes all twenty-seven jobs and seven required contexts. -Before any further rerun, all twenty producer archives and both aggregate archives -are downloaded, API-digest checked and independently revalidated with the frozen -source's pure validators. Exact current-attempt job/source identities, build/ -execution/upload gates, cleanup, toolchains, runner observations and complete -case/TRX unions pass. Backend contains 3,350 cases (2,917 base and 433 Architecture); -integration contains 2,570 (2,539 ordinary and 31 native). All 5,920 cases pass, -with zero skips. Both aggregate payloads match independent recomputation. -The longest observed producer whole-job wall time is 911 seconds, within the -unchanged 1,200-second ceiling; queue delay is separate and not hidden in that -measurement. Observed SDK/console are `10.0.402` and -`18.7.0-release-26505-111`, with their actual binary hashes retained. - -The B verification-summary SHA-256 is -`dfb122abc2bab511b8be916baa6566385a408f4eeb62d84f001334265f7554a1`. -The original capture checks both aggregate API digests, but does not retain the -integration aggregate's raw API envelope. Its ZIP, digest, payload comparison and -the verifier source remain retained; the latter has SHA-256 -`1e7d235d74aa63ecf6fdb715a7f68be6f965d9f118717431f6daad8cd6dde5f6`. -A subsequent independent reviewer can replay all twenty cached producer API/ -archive bindings and both complete unions/payloads, but cannot independently -replay that one aggregate API binding from a cached raw envelope. This limit is -distinct from the original capture's checked assertion. Later capture retains -both raw aggregate API envelopes before another transition. -Its plan digest is -`aec25a0597f0944dd4168fc5caf36faef983eb96fc0f053b6eb74befefd2e4be`, -manifest digest -`c79e7e37f5304b3e27d966f0e628b80d8746872aa911933a52383c434ac4bc8e`, -and assignment digest -`fe4cde10ee32f0ef85df6abbfa7e3137cc6a783a1791215abfa182e267d9b244`. -The separate B public-demo verification-summary SHA-256 is -`713a5dd039532fd4c847975c864ed7e466ef37795c467421f7174e3f566b4344`: -all twenty-seven JSON/HTML pairs and nine PNGs match their native manifest, -the full report contract passes, all 134 API completions return 200 and all -cleanup flags pass. This hosted clean-bootstrap evidence remains distinct from -the private historical-import experiment. - -The complete third attempt, layout A, starts only after B's archives and full -revalidation are retained. Its source and plan stay frozen. It finishes **red**: -twenty-four jobs pass, ordinary-7 and frontend fail independently, and integration -correctly refuses the failed producer. No earlier green assignment waives it. -The public demo producer separately passes all twenty-seven report pairs and -owned cleanup; its independent verification-summary SHA-256 is -`6afe2a1b664de4c59013f2a0a85077af3326634a151bada78734cc21bd9c09cf`. - -Ordinary-7 retains one failed known-failure variant of the actual Outcome ACK/ -held-cleanup test, 62.8366378 seconds, with finite source locations 164/179/183 in -`BackgroundJobPositiveSdkTests.NativeSettlement.cs`. The owner reports -`owned_completion_missing`, workload `tests_failed` and forced cleanup. Source -line 164 combines an awaited count query and the exact-two assertion; the retained -TRX/message cannot distinguish a query fault from a count mismatch, and no actual -count is recorded. A simple ledger visibility-delay explanation is not supported -by the transactional ordering. No wait, assertion or deadline is weakened. - -Frontend fails at the first development-server readiness boundary after the -production ingress/optimizer controls. No probe response completes; all existing -closed compilation/configuration flags are false. Current-child progress and the -probe-error kind are absent, so preparation delay, health-route delay, connection -refusal and TLS failure cannot be separated. The subsequent failed-fixture cleanup -command is not reached. Test-only finite diagnostics and exercised transport -controls are the justified next correction; neither failure has a proven -functional root cause from this receipt. Complete corrected-source qualification -remains required. - -#### CI failure diagnosis and exercised transport - -The settlement correction separates the original count read from its assertion -and records a bounded, case-bound observation before cleanup. A separate -application-role query observes ledger stages, counters and closed state; its -later snapshot is never represented as the failed assertion's original count. -Unknown/unavailable observations stay explicit. A bare rethrow preserves the -original failure. Only the three exact settlement cases and actual xUnit -`StdOutMsgs` can project these finite facts; raw output, identities, error text -and SQL are excluded. No assertion, wait or cleanup deadline changes. - -All forty-six offline launcher controls pass. A private copied-source experiment -changes only the last known-failure assertion's expected count to an impossible -negative value. The real pinned adapter transports that failed case's output: -the original count is two, the later snapshot is two (normal/finalize one each), -and the original assertion/stack remain intact. Two sibling cases pass and the -intended case fails, with zero skips. Sanitization removes output and preserves -the failed outcome. Initial immediate reaper absence is not proven; that refusal -is retained separately from later exact-ID proof that both owned containers -disappear naturally. Private compile-harness setup refusals precede execution; -no repository rule is disabled. - -The untouched source is rebuilt and all three real cases pass, with zero skips; -their command takes 62.599 seconds including runner/fixture work. All owned -processes and containers finish. Release builds report zero warnings/errors and -scoped format verification passes. The combined private receipt SHA-256 is -`0074b9dd2bab6371f992163cd76f6f4e4b3920999092cd0b3e58a80969286489`; -root independently checks all nine source hashes and six retained receipt hashes. -Rebuilt binary hashes are recorded per build; byte-identical production binaries -are not claimed. - -Fresh complete metadata discovery executes twenty bounded commands in 18.086 -seconds: the same 5,920 exact cases, manifest, plan and both assignments. Its -summary SHA-256 is -`11ac0e91f607bf3b70cd41e20e2f2da3e4c472388e60937b16ea1e485b8d11b8`. -These receipts qualify diagnostics and preserve the historical A3 failure; they -do not establish that failure's missing root cause. - -Frontend's first instrumented local run remains red: its development child is -running in preparation, with no observed bind and 196 refused probes/zero -responses in 20.058 seconds. A second, separately instrumented run observes -Next 15.5.27's exact informational npm version fetch still pending after 19.533 -seconds. The unchanged readiness boundary fails at 20.052 seconds. Production, -stock and optimizer-mutant listeners had readied in 1.068/0.526/0.642 seconds. -The pinned `HotReloaderWebpack.start()` awaits `getVersionInfo()` before compiler -startup; that exact global fetch has no timeout. This establishes the pending -dependency in the local reproduction, without guessing a DNS/remote/network -cause or claiming to recover the earlier CI child's missing observation. -The second private receipt SHA-256 is -`943f5ce5d18631e2c8151b43c06079172c679fb23643a674f38f9f1b81b7118f`. -Both failed runs retain their outcomes and complete owned cleanup. - -The correction adds an owned two-second abort only to that exact, one-argument -informational fetch inside the disposable development launcher. Next's existing -failure/unknown-staleness path handles the actual rejection. No synthetic HTTP -response or competing completion race is introduced; a delegate ignoring abort -remains pending until its real settlement. Other URLs, URL objects and calls -with options/explicit second arguments pass through unchanged. Any remaining -timer is cleared on actual settlement; notifications cannot replace the original -response/error. -Fetch resolves at response headers: the two-second budget does not extend through -Next's later JSON body consumption. The existing readiness refusal still bounds -that preparation check; no universal body/network I/O deadline is claimed. -The shipped launcher, workflow, plan and all ingress/HMR readiness, probe, -cleanup and success conditions remain unchanged. - -Twenty-three focused controls pass, including actual signal expiry, ignored-abort -settlement, timer cleanup, private-error containment, current-child attribution -and separation from upgrade messages. The single corrected actual native run -passes in 21.828 seconds. Both development children observe a real timeout at -2.004 seconds, then genuine healthy owned binds at 4.298/3.390 seconds; original -TLS, GET/HEAD, stock-bypass, optimizer mutant, DEBUG, query, HMR and both shutdown -signals pass. Its private receipt SHA-256 is -`00743393b8da99607eae39693803a4b51d6415f56f2ab958987bc8295fbb3b4e`. -Root independently matches five proof-source hashes and the observed Next package, -hot-reloader, lockfile and build-ID hashes. This fixes the demonstrated local -informational-lookup stall; it does not invent the earlier CI child's missing -internal trace. Full correction reviews and hosted qualification remain required. - -Final frontend validation passes workspace lint/typecheck, all 1,840 guarded -cases in two packages with zero skips/todos, and all nineteen cleanup controls. -An initial typecheck rejects two unchecked mock-call tuple accesses in the new -controls; explicit call-count/tuple guards correct only that test source. The -immutable native receipt is retained, and all four harness/helper/declaration -files still match it. The final guard binds all five current sources; its -private receipt SHA-256 is -`9422382afa7da79557c63fa799e76db2c23667b34cc8a554d12f600df2a0f29e`. -Root independently matches those five hashes. The unchanged, attested production -build is exercised by the native proof; no new production build is claimed. - -Root passes seven corpus/Docker-trait controls with zero skips; all testhost -processes finish. Changed-document validation checks 1,415 real relative links/ -fragments with no broken target, new analysis reference or overlong added prose. -The diagnostic correction still needs its two fresh independent review rounds -and complete corrected-source hosted qualification before closeout. - -#### First independent CI-correction review - -Two fresh reviewers inspect all seventeen files in `61e47ff3..87ecc114` and -their relevant dependencies: `gpt-6-astra` at `xhigh` and `gpt-6.1-sol` at -`high`. Both approve without a verified actionable finding. They independently -check application-role snapshot attribution, original-count separation, closed -parser output, actual failure preservation, exact fetch targeting/settlement, -current-child admission and unchanged success/cleanup conditions. - -The security reviewer passes all forty-six offline controls and independently -checks nine source hashes, six receipt hashes, the real mutant's original -assertion/stack and sanitized failed outcome. The frontend reviewer independently -passes all twenty-three focused cases through the actual runner/report guard, -with zero skips/todos, and verifies native/final source bindings and installed -provider/build hashes. An initial unsupported runner invocation refuses before -test execution; the corrected repository runner completes. Both inspect the -recorded evidence limits and retain the historical A3 failure. No provider, -native or full frontend experiment is repeated. All subprocesses finish and the -tracked tree remains clean. The second fresh review round remains required. - -#### Second independent CI-correction review - -Two different fresh reviewers inspect all seventeen files in -`61e47ff3..8ae35ecf` and their relevant dependencies: `gpt-6.1-sol` at `xhigh` -and `gpt-6-astra` at `high`. Both approve without a verified actionable finding. -The first independently passes the three added Python controls, checks raw -VSTest events alongside original/sanitized TRX and verifies nine source, six -top-level and seven mutant-subreceipt hashes. The second independently passes -all twenty-three focused frontend cases with the actual report guard and zero -skips/todos. Their source/receipt checks confirm original-count separation, -application-role observation, strict parser output, real fetch settlement, -unchanged readiness/cleanup admission, provider/build hashes and unchanged plan. - -The explicit limit above distinguishes fetch/header settlement from later body -consumption; it adds no runtime change. Both reviewers preserve the historical -A3 failure and pending corrected-source hosted qualification. No provider, -native, .NET or broad frontend suite is repeated. All subprocesses finish and -the tracked tree stays clean. Both fresh correction review rounds are complete; -complete corrected-source hosted qualification is the remaining gate. - -#### Reviewed-source hosted failure and identity attribution - -[Run `39716534536`](https://github.com/HodeTech/LearnStack/actions/runs/39716534536), -attempt 1/layout A, freezes reviewed head -`7b0fd1b6f718d49c7c5daad318685295b48d90cc`. All twenty-seven jobs finish: -twenty-five pass; ordinary-7 fails and integration refuses that producer. The -frontend job now passes. No layout B starts and no earlier green receipt waives -this failed source. All twenty producer archives and the successful backend -aggregate archive are retained and API-digest checked before another transition. -The private failed-run capture summary has SHA-256 -`0c4c7c37ab39af1ed37afa6494a57e68efc63876c4fdbc9d76ba62ed7a6a2394`; -it records a failed run, not complete qualification. - -The known-failure Outcome ACK/held-cleanup case fails in 20.6750301 seconds at -source line 221: the final process-wide `LeaseLossRenewalRefused == 0` assertion. -Its earlier count, generation, outcome and provider assertions pass. Runtime -stop/completion and the preceding zero-execution/elapsed-loss assertions also -pass. This location is distinct from the earlier count boundary. The retained -artifact has SHA-256 -`6f37596cf9acd045fe6993f67adf8c30e6513617d74648566ac8ff2742479c70`. -The diagnostic catch precedes these post-cleanup assertions, so no marker records -the counter value, execution identity or triggering renewal branch. None is -inferred from the stack location alone. - -Independent source inspection identifies a legal candidate interleaving: the -later Finalize execution holds the job row, renewal skips its lock and observes -no renewed row before managed commit acknowledgement. Conservative refusal can -then increment the cumulative counter while a commit already admitted completes. -This is a source-supported counterexample to treating the cumulative counter as -an observation of only the held Outcome identity; it is not a recovered CI trace. -The existing refusal/commit policy remains unchanged. Exact-identity attribution -and a controlled real-store interleaving are required before correcting the -proof; waits and deadlines are not increased. - -Public demo independently passes on the same source. Its immutable artifact -`12400165434`, SHA-256 -`c6c5ab29fb83ca43e187a95d00758cde9eab7db690fbec6ffd539aab9a7fde99`, -is retained before any rerun. All twenty-seven JSON/HTML pairs, nine PNGs, nine -navigations and twenty-four visibility checks pass; all 134 API completions -return 200, both TLS and the timeout refusals pass, and all cleanup flags pass. -Natural cleanup takes 10.732 seconds. Independent verification-summary SHA-256 is -`a0e3688c3ab02d6403d145845485b43499dc8d6f9bbde4ac5ec0866832cd1ef2`. -This successful producer does not change the run's failed conclusion. - -#### Exact lease-loss attribution proof - -The corrected stock proof keeps all three case identities, its held-cleanup -barrier, exact counts, generation, provider observations and original deadlines. -It checks the captured Outcome execution's sticky first cause after actual -cleanup instead of attributing later process totals to that identity. The later -Finalize control is captured independently. Aggregate zero checks remain while -only the original held identity exists. Post-cleanup and cleanup-first failures -now produce the same bounded diagnostics; cleanup cannot replace an earlier -exception. Closed per-identity causes and cumulative counts remain observations, -never admission or completion evidence. - -A separate explicit-owner subphase runs inside the existing known-failure case. -It uses real publication, provider, Outcome, Finalize and PostgreSQL control -owners; it does not claim a stock Hangfire handoff. A test-only proxy holds the -real Finalize COMMIT request only after that exact gate admits commit. An actual -`SKIP LOCKED` read confirms its row remains locked. The production renewal lane -then refuses the omitted identity. A test-owned cancellation callback holds -propagation while the already-admitted real COMMIT request and ACK complete. -All barriers release before actual joins. No control field, counter, completion -or production policy is manufactured or changed. - -The initial experiment uses a COMMIT ordinal and refuses at the required -`CommitStarted` precondition: the held transaction is preparatory. It is not -accepted as the intended negative; both owned containers and all processes -finish. The corrected barrier uses the exact gate predicate and measures the -actual before/after COMMIT count rather than guessing an ordinal. - -The source-attested one-substitution experiment restores the old global-zero -assertion only at the final explicit-owner boundary. Two siblings pass and that -case fails exactly at `later_post_cleanup`, with zero skips. The real pinned -adapter transports original cause `none`, Finalize cause `renewal_refused`, -cumulative renewal loss one, elapsed loss zero and zero active executions. -Actual attempts are two (one normal, one Finalize), generation advances once and -one finalized row exists. The original assertion survives; sanitization removes -output and preserves the failed outcome. Both owned containers are absent. -The private mutant receipt has SHA-256 -`ac261c52d4a5b261cb5928b397b8993e4cb17b24432dd491544f5d3468e7c906`. -Root independently checks its finite facts and receipt hash. This proves the -attribution counterexample, without asserting the missing CI interleaving. - -Untouched-source Release rebuilds report zero warnings/errors, scoped format -verification passes and all forty-seven offline launcher controls pass. The -single clean real run passes all three cases with zero skips: false 16.184 -seconds, known failure 19.449 seconds including the separate counterexample, -and retained recovery 21.383 seconds. Command wall time is 63.415 seconds. -Both owned containers and the process group are absent; all commands join. -The combined private receipt has SHA-256 -`10658b0cf90dea34b533b80941514f243085e4eac0e48d1a71b538570fe3b735`. -Root independently verifies seven current source hashes, nineteen retained -artifact hashes and both clean TRX hashes. Rebuilt production binary identity -is recorded per build; byte-identical binaries are not claimed. - -Fresh complete metadata discovery executes twenty bounded commands in 19.077 -seconds. All 5,920 exact identities, the plan, manifest and both assignment -digests remain unchanged. The private summary has SHA-256 -`f64f219670a3d12a8efa99b81001c05740aec3e6ea4ba63f96d30cd99c0bbdd0`. -Seven corpus/Docker-trait controls pass with zero skips in 9.465 seconds and -their process group is absent. Independent review and complete corrected-source -hosted qualification remain required; no earlier red receipt is waived. - -#### First independent attribution review - -Two fresh reviewers inspect all five files in `7b0fd1b6..9adba275` and their -ownership, renewal, persistence and diagnostic dependencies: `gpt-6-astra` at -`xhigh` and `gpt-6.1-sol` at `high`. Both request changes for the same verified -Major: the new explicit-owner failure cleanup releases barriers but can call -`JoinAsync` before issued business/admission/external tasks actually return. -An unfinished task then makes cleanup fault sticky and retains the invocation; -preserving the first exception does not prove a completed join. The successful -path's retained receipt does not qualify this early-failure path. - -Both otherwise confirm the attribution boundary, real gate-bound COMMIT/ACK, -unchanged default proxy behavior, finite diagnostic privacy and honest evidence -limits. The first passes all forty-seven offline controls in 17.125 seconds and -independently verifies seven source and nineteen artifact hashes. The second -independently verifies changed executable sources and four raw/sanitized TRX -hashes. Neither reruns provider/.NET/Docker work, and all commands join. -The pre-existing stock pre-ACK guards remain setup requirements; this review -does not claim an earlier loss is impossible or change conservative refusal. - -The verified correction retains each actually issued admission, external, -business and disposition flight before its synchronous prefix. Failure cleanup -closes future issuance, requests owned cancellation and releases its barriers, -then independently awaits actual flights and their cleanup results before -positive execution/private joins. An already-started private completion task is -retained and reused. One failed step cannot skip independent stop/join steps, -and an unfinished or cleanup-faulted operation never supplies a positive witness. - -The original failure observation remains separate from a closed post-cleanup -witness. Only the exact known-failure case and stdout category can carry that -optional witness; finite states/counts, malformed/ambiguous/private-output -refusals and sanitizer behavior remain enforced. It grants no completion or -admission authority and cannot turn a failed case into success. - -A single copied-source substitution plants an impossible expected renewal count -after the cancellation callback enters, while the real business task is pending -and COMMIT remains held. The actual adapter reports the intended `later_refusal` -failure with one active execution. Its separate cleanup witness records both -admissions, external/business flights, callback, both identities, private work, -control and generation joined; unissued disposition stays `not_issued`. -Executions, running work and retained work are zero. Two siblings pass, the -intended case fails and zero cases skip. The original assertion survives, -sanitized TRX remains failed and both owned containers/process group are absent -without forced cleanup. The private mutant receipt has SHA-256 -`99cff1933d6de69c190542b2141e04799f7406f45b5de7c6ac3b62399f166889`. -Root independently verifies the pre/post-cleanup facts and seven source hashes. - -Corrected-source Release builds report zero warnings/errors; scoped format -verification and all forty-nine offline controls pass. The single clean real -run passes three cases with zero skips: false 16.070 seconds, known failure -18.092 seconds and recovery 21.263 seconds; command wall time is 61.189 seconds. -Both owned containers and the process group are naturally absent and all -commands join. Combined private receipt SHA-256 is -`bdbf89a86f718b30c6d449dc5f127efa467c961e86beb9bb697c66460d3968c6`. -Root independently verifies seven current source hashes, nineteen artifact -hashes and both clean TRX hashes. The earlier attribution and rejected ordinal -experiments remain source-bound historical evidence, not new-source reruns. - -Twenty fresh metadata commands complete in 16.080 seconds, preserving every -one of the 5,920 identities, the plan/manifest and both complete assignments. -Private summary SHA-256 is -`67d477db5a547e837ac7ea3e908b80f89463884cf7bef3b1670f4ef68c8f41c0`. -Seven corpus/Docker-trait controls pass with zero skips in 8.868 seconds; -their process group is absent. The second fresh independent review round and -corrected-source hosted qualification remain required. - -#### Second independent attribution review and source freeze - -Two different fresh reviewers inspect all six files in -`7b0fd1b6..c9abc978` and their dependencies: `gpt-6.1-sol` at `xhigh` for -ownership/security and `gpt-6-astra` at `high` for evidence/governance. Both -approve without a verified Blocker, Major or Minor. Both independently confirm -the first round's cleanup correction: actual flights precede positive joins, -private completion is reused, independent cleanup continues and first failure -survives. The early negative verifies issued business and held cancellation -cleanup; it does not infer cleanup from process exit. - -The first passes all forty-nine offline controls in 16.588 seconds. Both inspect -the actual driver, adapter output, four raw/sanitized TRX hashes and nineteen -artifact hashes, preserving the intended failure and clean three-case outcome. -The second also approves the unpublished PR description and its explicit -qualification boundary. Neither repeats .NET/provider/Docker/native experiments. -All commands join. One initial status probe reports an existing untracked -directory entry; no contents are opened or enumerated, and later status probes -exclude untracked paths. - -The commit hook normalizes only line 461's leading indentation from sixteen -spaces to twelve. Reversing the exact retained mutant substitution reconstructs -the tested source, SHA-256 -`4538ae656ffded55fe4c39d2918a143a882276958403ea6a4dd8be0db7da68df`. -Both reviewers independently verify the one-line whitespace mapping to committed -SHA-256 `1cefcb2f5c5f6e996cd3f4c9ada7164b2ca487b2d8225361ba62b52ae810c1cd`; -the other six attested files match byte-for-byte. Seven-file byte identity is -not claimed after the hook. The separate private binding receipt has SHA-256 -`e3b73f02e9b572ab602a5875360be7e48450005b23c4195d85695871d2d6b0cc`. -It records a formatting bridge, not a new runtime or binary-identity claim. - -Local implementation, validation and both fresh independent attribution review -rounds are complete. [PR #34](https://github.com/HodeTech/LearnStack/pull/34) -records the frozen head's exact run/attempt identities, complete A/B assignments, -retained producer/aggregate/public artifacts and current seven-check result. -Complete current-source qualification is required before readiness; a successful -sibling or earlier revision supplies no waiver. Merge and P02b-7 remain separate. - - -#### Reviewed-source recurrence failure and evidence boundary - -[Run `39723329277`](https://github.com/HodeTech/LearnStack/actions/runs/39723329277), -attempt 1/layout A, freezes reviewed head -`4e06ffa1359bb2701e7a097a1fb1b7f9244ad9d1`, tree -`565a62db2958306fc29d198b2672e531b5318fb1`. All twenty-seven jobs finish: -twenty-five pass; ordinary-8 fails and integration refuses that producer. No -layout B starts. All twenty producer archives and the successful backend -aggregate archive are retained with their raw API inventory and verified -digests. The failed-run capture summary has SHA-256 -`46a0af0a9af9b64593ef834a8474d5a8fa84887c6d0c1fd9051dd848f8b669e3`. -This capture records failure, not complete qualification. - -The held actual native recurrence callback case fails in 32.5851077 seconds. -Its artifact, `12402495557`, has SHA-256 -`c19332a22de1977c1368e4262430f29bd677ac52d50b40ea81a3d333d1c79be9`. -The retained top-level exception class is `timeout`; no mapped source location -is available. The owner reports `owned_completion_missing`, workload -`tests_failed` and forced cleanup. Multiple independent thirty-second waits -exist; the test's cleanup can also replace an earlier exception. Duration alone -identifies none of these boundaries. - -The actual job log contains no underlying adapter stack or error message. -Ordinary console output is discarded, raw execution diagnostics are deleted and -TRX errors are sanitized. Neither native recurrence source file has a finite -location mapping. Empty exported locations therefore do not establish an empty -original stack. Two independent read-only inspections find no source-proven -production defect; this run's exact timeout boundary is unrecoverable from its -retained evidence. The next correction preserves the first exception, maps both -source files and records finite first-failure and later cleanup facts separately. -It changes no production behavior, assertion, wait or admission rule. - -Public demo independently passes on this same source. Immutable artifact -`12403135471`, SHA-256 -`3d31ba7b57bb3de2c19a868fed71eb7b42fde79fde4ca794ec63b925e2bccd55`, -is retained with its raw API binding. All twenty-seven report pairs, nine PNGs, -nine navigations and twenty-four visibility checks pass; all 134 API completions -return 200. Toolchain, TLS/timeout controls and natural cleanup pass; cleanup -takes 11.783 seconds. Independent verification-summary SHA-256 is -`5335e9a6dcde02f51cda4c103508afdc32e07e75018974d4f1db801847957a72`. -This successful sibling supplies no waiver for the failed recurrence case. - - -#### Recurrence failure transport and first-exception proof - -The correction retains the existing case identity, assertions and timeouts. -Its first body, explicit cleanup or post-cleanup exception is preserved through -`ExceptionDispatchInfo`. Later cleanup steps are attempted independently. An -early body failure also requests the two actual source disposals; only their -positive completion can establish cleanup. No production code changes. - -One exact integration case may project its two test-owned `StdOutMsgs` markers. -Finite boundary, task/thread, owner-count and source-state fields distinguish -the first failure from the later cleanup observation. The sibling task arrays -retain their production-published order. Neither diagnostic proves completion -or changes a failed outcome. Unknown or malformed data is refused; identities, -raw errors, SQL and arbitrary text are excluded. Both recurrence source files -now have finite source-location mappings. These bounds constrain output; the -owner snapshots are not represented as lock-free or universally nonblocking. - -A private one-substitution control changes only the held callback assertion's -expected count from one to an impossible negative value. The actual pinned -adapter transports the intended failed case at `held_assertions`: callback one, -thread alive, return pending and both sources undisposed. Its original assertion -and stack survive. After callback release, the actual thread returns, all three -pools, three control loops and fixed sibling/control/runtime tasks complete, -and both source disposals complete without unconfirmed cleanup. The failed -outcome remains failed after output sanitization; no process exit supplies the -internal cleanup evidence. - -A separate two-substitution control adds an awaited cleanup failure after the -actual stop completes. The exact case's output proves this second fault was -reached. The first assertion and its stack still survive, while subsequent -completion, thread and source cleanup continue successfully. An initial private -build refuses a literal throw under CA2219; the corrected awaited failure keeps -that rule enabled. Offline proof validators initially refuse duplicate summary -output and replay-file bindings. Their refusals remain recorded; validation is -corrected against the same unchanged actual execution and exact case output, -without rerunning the test to replace its result. - -Both fault experiments have one intended failure and zero skips. The untouched -source is then rebuilt with zero warnings/errors; scoped format verification -passes. The original case passes once with zero skips in 2.7962847 test seconds, -9.522 command seconds. Each experiment's process group and two exact owned -containers disappear naturally. The combined private receipt has SHA-256 -`f37b584d22c72191a54465b4dd2e1649ea2d9db641a9a4d5f0139ec1885926b4`. -Root independently verifies seven source hashes and sixty-one retained artifact -hashes, including raw protocol, original/sanitized TRX and actual owner cleanup. -These local controls qualify the diagnostic correction; they cannot recover the -earlier hosted timeout's missing boundary. - -All fifty-three offline launcher controls pass. Twenty fresh metadata commands -complete in 22.886 seconds, retaining all 5,920 exact cases and unchanged plan, -manifest and A/B assignment digests. Their private summary has SHA-256 -`127e95b0d206e067c89d4cbc0061e3c1b706938c62c50569880161c7925e71c9`. -Seven corpus/Docker-trait controls pass with zero skips in 9.863 seconds; their -process group is absent. Changed-document validation finds no broken relative -link or fragment, added analysis reference or overlong prose. -Fresh independent correction reviews and complete current-source hosted -qualification remain required before readiness. - - -#### First independent recurrence diagnostic review - -Two fresh reviewers inspect all five files in `4e06ffa1..55dfeaea` and their -relevant dependencies: `gpt-6-astra` at `xhigh` for ownership/security and -`gpt-6.1-sol` at `high` for export/evidence/governance. Both approve without a -verified Blocker, Major or Minor. Both confirm first-fault preservation, -independent cleanup, unchanged assertions/timeouts, actual thread/owner/source -completion, ordered sibling observations and failure-only finite transport. -Neither treats a disposal request, elapsed wait or process exit as cleanup. - -Both independently verify seven current source hashes and all sixty-one retained -artifact hashes, reconstruct the exact private substitutions and inspect actual -protocol, original/sanitized TRX, proof drivers and cleanup records. The dual -control's exact-case marker proves its second fault was reached while the first -assertion and stack survive. The export reviewer independently replays both -failed controls and the clean result through the decoder, verifies forty-two -clean assembly hashes and passes all fifty-three offline controls in 17.016 -seconds. The core reviewer independently checks the production completion chains -and the sibling helper's unchanged adjacent caller. - -The export reviewer also checks all twenty-one failed-run archives against their -raw API inventory. The record retains the unrecoverable historical timeout and -requires complete corrected-source qualification. No .NET/provider/Docker/Node -experiment is repeated. All commands join, no files change and the tracked tree -stays clean. The second fresh independent review round remains required. - - -#### Second independent recurrence diagnostic review and source freeze - -Two different fresh reviewers inspect all five files in -`4e06ffa1..196a5b4e` and their relevant dependencies: `gpt-6.1-sol` at -`xhigh` for ownership/correctness and `gpt-6-astra` at `high` for -privacy/evidence/governance. Both approve without a verified Blocker, Major or -Minor. They independently confirm first-fault preservation, continued cleanup, -unchanged assertions/waits, actual completion chains, the adjacent helper caller -and strict finite failure-only export. No production code changes. - -Both verify seven source hashes, sixty-one artifact hashes, exact private -substitutions, actual adapter/first-stack transport, original/sanitized outcomes -and forty-two clean assembly hashes. Both also check all twenty-one historical -archives against the raw API inventory. The core reviewer reconstructs the twenty -fresh metadata commands, every identity and both distinct assignment digests, -and verifies the seven-case corpus TRX and build/format records. Independent -launcher runs pass all fifty-three controls in 16.713/18.139 seconds. All commands -join; neither repeats .NET/provider/Docker/Node experiments or changes a file. - -The governance reviewer also approves the unpublished final PR draft subject to -replacing its pending qualification marker with actual current-source results. -Local implementation, validation and both fresh recurrence diagnostic review -rounds are complete. [PR #34](https://github.com/HodeTech/LearnStack/pull/34) -records the frozen head's exact hosted run/attempt identities and retained -producer/aggregate/public evidence. Complete corrected-source A/B qualification -remains required before readiness; the earlier timeout boundary stays -unrecoverable. Merge and P02b-7 remain separate. - - -#### Reviewed-source startup failure and retained evidence - -Frozen-source assignment A at -`dbfad06b1302c76c9d2b4a29dfca0d6db0795026` did not qualify. Run -[39727855228](https://github.com/HodeTech/LearnStack/actions/runs/39727855228), -attempt 1, completed 25 of 27 jobs successfully; `backend ordinary-7` failed -and the required integration aggregate refused its incomplete evidence. No -assignment B was started and no failed-job retry substitutes for this result. - -- Failed case `4172c42b-b84f-59bf-426f-60d6c521ec52`, the Outcome-ACK - settlement case (`knownFailure: False`), returned cancellation after - 32.0671777 seconds. - Its source locations identify the startup wait for the Outcome cleanup - barrier. The retained finite snapshot reports `prepared`, one normal - attempt, one renewal refusal, zero elapsed losses and zero executions. - No original Outcome owner was captured. This establishes failure before - the intended post-ACK proof; it does not identify the renewal refusal branch. -- Producer artifact `12404570952` has SHA-256 - `29cc4750561aabf3efc51b2e59b841033ae5a9c95a7601ff4d66a97b50a42dbc`. - It reports `tests_failed` and `owned_completion_missing`, with forced - cleanup, incomplete ownership and separately completed cleanup ownership. - All 20 producer archives and the successful backend aggregate are retained - against the raw Actions API sizes and digests. The final 21-archive capture - has SHA-256 - `44bb709c4683ad3d9a077ea5ec6686f83790746d6a1cfa30cc0a6ebdb32a1ae6`; - its qualification flag remains false. -- The previous recurrence failure's exact case passed in this run after - 5.5832527 seconds, with complete natural ownership. This supplies no missing - historical timeout cause. The public proof also passed independently; - neither result overrides the failed whole assignment. - -Source inspection identifies a possible legal interleaving: Prepare's real -row lock can exclude the still-active identity from a successful -`FOR NO KEY UPDATE SKIP LOCKED` renewal batch. A timely, acknowledged empty -batch closes that identity's permission; Prepare may still receive its -already-issued COMMIT acknowledgement. The observed startup facts are -compatible with this branch, but do not prove that it occurred in CI. -The correction owner is the settlement test fixture. Production renewal -policy, SQL, lease deadlines and refusal semantics remain unchanged. - -Failed-job reruns do not replace this evidence. Attempt 2's integration job -`119676062757` refused `artifact_api_missing`: only `ordinary-7` produced -an attempt-2 archive. Its artifact `12405733408`, SHA-256 -`68252513daa900062f3f8ed7823922f3dd09da91a6942b3a588d0f2302dee91a`, -contains 240 passing cases under assignment B; the previous failed case is -absent. Reusing the same shard name does not rerun the same assignment. -Attempt 3's integration job `119676234308` refused -`jobs_api_population_changed`; no attempt-3 producer archive exists. -The original API response at that refusal was not retained, so its exact -population discrepancy is not recovered from a later consistent response. -The rerun capture has SHA-256 -`b730e8293ae0a806865579c6e838d0418892f7ddf881fd06efcd34c691d13496`. -The [existing recovery procedure](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) -requires **Re-run all jobs**, with all producer evidence from the same attempt. - -#### Settlement fixture scheduling and real counterexamples - -The three existing settlement cases now isolate the intended post-ACK proof -from unrelated legal pre-ACK renewal refusals. Their fixture uses a distinctive -validated 1125 ms renewal cadence instead of one second. No production code, -SQL, lease duration, deadline or assertion is weakened. - -- The first typed native lease factory creates and retains its real system - timer, then waits outside locks for the actual renewal pacing timer. The - execution identity is still unpublished, so the immediate initial renewal - scan sees no eligible identity. Native lease and deadline clocks keep running. -- The first actual pacing callback waits until the original Outcome ACK and - held cleanup. Its release exercises the real renewal loop. The existing - four-second observation budget also requires the second actual pacing timer - to arm before releasing Outcome cleanup. Holding that callback prevents an - unrelated pre-ACK Finalize race from contaminating this settlement proof. - The existing 30/80-second startup/completion waits remain unchanged. -- Cleanup seals and opens both holds before stopping the runtime. Actual timer - disposal joins queued callbacks before synchronization objects are disposed; - incomplete runtime cleanup cannot close the factory census. Synchronous - timer disposal never joins itself from inside a forwarded callback. The - second callback's separate 120-second safety watchdog cannot extend any - caller deadline or prove disposal. -- An independent explicit-owner counterexample holds the real Prepare COMMIT - request and verifies its PostgreSQL row lock. A separate actual renewal - operation returns a timely, clean, physically acknowledged empty result, - with its exact original job/attempt/token probe. The identity closes with - renewal refusal while the admitted Prepare later ACKs. Application-role - readback confirms prepared state, no execute intent/outcome and no provider - invocation. This proves an available legal interleaving; it does not recover - the historical CI branch or claim stock Hangfire handoff. The existing - later-Finalize attribution counterexample remains independently asserted. -- Failure export adds two fixed source roles and optional finite pacing facts, - retaining the eight-location bound. Prepare-only facts bind the exact - `knownFailure: True` case. No raw path, exception/provider text or identity - enters this projection; diagnostics cannot qualify completion. - -One frozen private copy binds 1,927 source files and five exact changed-source -overlays. Clean execution passes all three original case IDs, zero skips, in -64.145 seconds; their durations are 16.1845573, 21.3963182 and 18.9924022 -seconds. The actual adapter is `2.8.2.0`. - -Two private controls exercise the proof rather than merely its setup: - -- Removing both active-selection and empty-result settlement exclusions makes - all three cases fail at `renewal_second`, on the unchanged open-Run assertion - after physical Outcome ACK. Actual Outcome cleanup is still pending and the - durable phase is `finalize_pending`. The original sticky cause and both loss - counters remain empty/zero, as required for an already settled identity. - Actual pacing callbacks/timers join without a pacing fault. -- A planted Prepare assertion after the genuine empty-ACK observations makes - only the named known-failure case fail; the other two pass. The original - assertion survives. Issued admission, external/business work, cancellation - callback, identity, control, private invocation and generation all join; - execution/running/retained counts are zero. No unrelated operation is labelled - issued or joined. - -All six test-created containers across these runs are naturally absent; owned -process groups join. The complete receipt has SHA-256 -`1ef5254dc6086a722e6d8b95c63b3b3451a755b1222a31d5d4634fd40b19576a`. -It binds original/sanitized TRX, protocol, exact private substitutions, source -and binary evidence, seven command receipts and 749 final workspace outputs. -The final clean workspace Release build reports zero warnings/errors and -scoped format verification passes. Independent pure replay of all three -actual protocol streams agrees with their retained outcomes and finite facts. -All fifty-five launcher controls and nineteen aggregate controls pass. - -Fresh metadata discovery completes twenty bounded commands in 17.379 seconds: -5,920 cases, the same complete manifest and unchanged, materially different A/B -assignments. Its receipt has SHA-256 -`19ab2cfd147b8477983f5addf40eee6bbf207e29c484f887f92189883ca563be`. -This is metadata evidence, not execution of the whole suite. Seven current -corpus/Docker-trait cases pass without skips in 8.042 seconds; their receipt has -SHA-256 -`25d949b4a406b9ad1ecd322166023de788894ae185ab8592a74ead9840196445`. -The phase's 288 relative links/fragments resolve. Independent implementation -reviews and complete corrected-source hosted A/B qualification remain required. - -#### First independent settlement scheduling review - -Two fresh reviewers inspect all six files in `dbfad06b..0dc962dc` and their -relevant production owners, publication, timer, proxy and cleanup dependencies: -`gpt-6-astra` at `xhigh` for correctness/ownership and `gpt-6.1-sol` at -`high` for privacy/evidence/governance. Both approve without a verified -Blocker, Major or Minor. They confirm unchanged production policy, exact -case identities/deadlines, actual timer joins, first-fault preservation and -positive cleanup only after every issued operation is observed. - -Both independently match all five executable-source overlays and forty-eight -scenario artifacts. Raw TRX confirms three clean passes, three intended -post-ACK exclusion failures and the single intended Prepare failure with two -passing siblings. The evidence reviewer additionally reconstructs all three -actual adapter protocols, checks the 1,927-file clean manifest, all twenty-one -historical archives against their API inventory and the partial-rerun capture. -Neither starts tests, builds, processes or containers, edits a file or claims -that the historical refusal branch is recovered. The second fresh independent -review round and complete corrected-source hosted A/B qualification remain -required. - -#### Second independent settlement review: deadline finding - -Two different fresh reviewers inspect the complete six-file change through -`c971f4cc`, with `gpt-6-sol` at `xhigh` for ownership/correctness and -`gpt-6-astra` at `high` for privacy/evidence/governance. The governance -reviewer identifies one verified Major: normal publication calculates the -remaining deadline before creating the lease timer, but starts its deadline -observer only after that factory returns. The fixture's blocking handshake -therefore shifts the native deadline observation by its wait duration. The -running system clock and lease timer do not compensate for that distinct delay. -The ownership reviewer initially approves, then independently confirms this -ordering in an explicit addendum that supersedes that approval. Both require -the correction; neither reports another verified finding. - -This limits the preceding unchanged-deadline claim. The three clean passes and -both private controls remain retained evidence for their exact source, not -qualification of deadline preservation. Recovery's separate elapsed-time -re-debit does not repair the normal publication path. The correction must start -both actual normal timers before holding publication, retain their real -cleanup ownership and keep the initial renewal scan ahead of identity -publication. Production code and deadline policy remain unchanged. - -The reviewers independently verify source/receipt/artifact hashes, the finite -projection, raw/sanitized outcomes and retained failure chronology. No runtime, -test, build, process or container is started. The original API response behind -attempt 3's population refusal remains unavailable. Fresh source-bound proof, -independent fix verification and complete hosted A/B qualification are required -after the deadline correction. - -#### Deadline-preserving settlement correction - -The normal fixture returns the actual lease-timer handle immediately and -intercepts only the next deadline-timer factory in that same execution flow. -A shared consumed slot prevents inherited execution contexts from selecting it -again. The actual System deadline timer starts with its original duration -before the publication hold; its callback is never gated. The test deliberately -holds first pacing-timer creation, verifies both actual normal timers and the -unpublished identity, spends real time inside the existing startup budget, then -opens pacing creation. An expired deadline cannot authorize business execution -when that synchronous construction path resumes. This does not claim the -execution-close action runs while its own synchronous prefix is held. - -Retained recovery keeps its separate lease-return handshake and elapsed-time -re-debit; it has no normal deadline observer. Cleanup seals factories before -opening waits, observes every issued factory return, and joins actual timer -and callback disposal before releasing synchronization resources. The three -case identities, production source, stage durations, four-second post-ACK -observation and physical application-role assertions remain unchanged. +P02b-2 bounds the durable failure descriptor under **G18** to closed stage, +reason and category codes, with only allowlisted SQLSTATE where applicable; +exception text/type, trace identity and payload are not persisted there. The +canonical DDL owns the byte bound. Step 1 implements the migration beside the +lease columns, including redaction of legacy descriptors without rewriting +event facts/state; Steps 2–3 implement transitions and bounded diagnostics. -The finite diagnostic projection adds the normal-only `deadline_armed` -boundary and actual deadline-timer state. Retained recovery cannot claim that -boundary or an issued normal deadline timer. Fifty-six offline launcher -controls pass, including case binding, closed values and canary rejection; -the existing eight-location cap remains unchanged. +### Architecture tests -The corrected-source actual pinned-adapter run passes all three settlement -cases with zero skips. Both normal cases prove actual lease/deadline arming -before the held first pacing factory; the known-failure case also executes the -unchanged real Prepare and later Finalize counterexamples. A copied complete -settlement-exclusion defect makes all three fail at `renewal_second`, preserving -the original assertion, physical acknowledged Outcome and actual timer/runtime -joins. These results are source-bound local proof, not hosted qualification. +[Architecture Tests Catalogue](../standards/21-architecture-tests-catalogue.md) is the +canonical reference for every rule identifier, and a hand-kept second copy of it here +goes stale the moment the catalogue moves. The obligation is therefore stated over the +catalogue's own **Phase** field: **every row whose Phase names 02b is Implemented and +green by this phase's exit, and none is still Registered or Awaiting backfill.** That +set includes the outbox, inbox, partition-key, claim-protocol, job-payload, JWT and +realm-authority rules, and it currently contains rows this document's previous list +omitted. -A separate copied deadline-ordering defect moves actual deadline creation after -the publication handshake. Both normal cases fail at `deadline_armed`, and -retained recovery passes. The original cancellations survive sanitization and -the selected deadline and first pacing timers finish/cancel, but runtime -completion has no positive join within the unchanged drain budget. Its full cleanup oracle therefore -refuses. The bounded test process exits naturally and both exact owned -containers become absent; those observations do not replace the missing -internal runtime witness. This is retained detection evidence with an explicit -cleanup limit, not a passed cleanup control. No corrected-source change or -production change is inferred from that deliberately broken construction. -The earlier planted Prepare control remains evidence for its original frozen -source only; the unchanged helper body does not turn an old binary into fresh -corrected-source proof. +What this phase owes the catalogue beyond implementing those rows: -The retained corrected-source summary has SHA-256 -`195fff62567643010e27f0dc5f0cde5bb2af24a94fe50ef5cd3f319891cb8f5e`; -its 1,927-file frozen source manifest has SHA-256 -`5b0988882c9a6331c4f0c878c063597256566711a2104a5dbdf6a26649813d37`. -Independent replay matches all actual adapter protocol completions, original -and sanitized TRX outcomes/durations, finite facts and source substitutions. -All retained artifact hashes and five workspace overlay hashes match. The -final workspace Release build passes with zero warnings/errors in 47.217 -seconds; scoped format verification passes in 23.198 seconds. Every owned -command group exits. The initial clean Docker absence inspection inherited -its helper environment, with application credential-prefix presence checked -false; all .NET commands and subsequent Docker checks use the explicit tool -environment allowlist. This distinction remains in the provenance receipt. +- **Producer rows delivered by P02b-1:** the announced-transaction write, + produced-work refusal, owner-only completion, outbox-only domain handlers and + identifier-only payloads. Later decision passes register and implement the + ADR-0036 middleware-ordering rule, the + routable-set bound (**G14**) and the Keycloak-role-claim rule — with the realm-role + question it answers — in `P02b-5`, where the API first reads a claim; and `LS0002` + under its rule name (**G16**) in `P02b-8`. +- **Widened assertions** where a catalogued rule is satisfied by the defect it exists to + catch. P02b-1 extends `Outbox_Row_Carries_Correlation_Context` to exact stored + identity, tenant/organization, full traceparent and partition values, including + unresolved provisioning. Its partition declaration rule combines independent + stored-source IL checks, varied identifier probes and real persisted keys; + an uninitialized instance is not a value proof. Publish ordering stays P02b-2. + `Outbox_Claim_IsHeld_Until_Dispatch_Completes` replaces the former unconditional + exactly-once assertion with live-lease contention, expiry/crash redelivery and + stale-transition refusal; Step 3 implements the actual two-worker proof. + P02b-4's accepted `BackgroundJob_Submission_Is_Transactional_And_Stamped` replaces + `Hangfire_Job_Payloads_Include_TenantId` with tenant/org/actor/trace and atomic + submission proofs under Accepted ADR-0047; it is not Implemented today. + `OutboxProcessor_NeverBlocks_OnSingleMessageFailure` gains the hanging-handler + case. Two rules the catalogue stamps **02a** also + widen here, so the Phase-field sweep above does not reach them: the transport arm of + `Tenant_Context_Guard_Fires_Only_On_An_Unmarked_Transaction`, whose second arm has no + subject until the transport announces a tenant, and + `Module_DbContexts_Enlist_In_The_Ambient_UnitOfWork`'s connection allow-list, which + the dispatcher's keyed data source and the job storage both touch — a new entry there + is a decision, taken in the pass of the packet that adds it: the dispatcher's in + `P02b-2`, the job storage's under **G9**. +- **A planted-offender companion for every structural rule this phase ships.** The + catalogue's own rule is that a rule shipping before its first subject exists carries a + companion that plants the violation it exists to catch; with one sample event and one + consumer, most of this phase's structural rules are near-vacuous without one. That is + Packet 9's repeated lesson — a rule that cannot tell *clean* from *blind* — and Packet + 10 established the convention this phase follows: a `*Probes.cs` type holding the + planted violation, and a `The_<X>_Can_Actually_Fail` case beside the rule. +- **Rules that leave this document.** A read-model naming rule belongs to + [Database Standards § Read Models](../standards/05-database.md#read-models), which + already carries `public_<module>_<concept>`; it has no subject, no marker identifying + a table as a read model and no catalogue row, and the first phase that ships a + projection registers it with its first subject. The provider-SDK rule is the + catalogue's and is wider than the paraphrase this document carried. The + [accepted P02b-6 package](phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) introduces no + runtime SDK subject and hands its owning-phase cell to Phase 03's first runtime + identity-provider adapter, triggered by actual SDK introduction. It remains + Awaiting backfill there; direct HTTP does not qualify as SDK coverage. -Fresh metadata discovery completes twenty bounded commands in 18.006 seconds: -5,920 exact identities, unchanged complete A/B unions and materially different -assignments. Its summary has SHA-256 -`940090d702545aa7eb791559b333f7c46408cb0b30ad902c75c2ce6f9ea6072d`. -Seven current corpus/Docker-trait controls pass in 8.631 seconds; their receipt -has SHA-256 -`5e092c42b844d746d7ad6a5be99682641c95a6ec71b08b62542f94253a857ad3`. -All 749 final workspace build outputs match their retained manifest. -Independent fix verification and complete corrected-source hosted A/B remain -required before final qualification. +Two notes on what "green in CI" can mean. Several of this phase's rows are behavioural +rather than structural, and CI runs those in a separate job under a Docker trait filter, +so "the architecture suite is green" does not reach them. `backend integration +(Testcontainers)` is already a required check; the +[P02b-0 receipt](phase-02b-delivery-log.md#p02b-0-entry-verification-2026-10-12) verifies all seven current +required contexts with strict up-to-date protection. `P02b-8` re-verifies those +live settings under the exact reported names. `scripts/assert-tests-ran.py` +already rejects a missing assembly, zero executed tests and any unexecuted test +in the required assemblies; test failures additionally fail the `dotnet test` +command. The phase retains zero skips, per assembly. -#### Independent deadline-fix verification +## Deliverables -Two new independent reviewers approve `c971f4cc..c618414e`: `gpt-6-astra` -at `xhigh` for correctness/ownership and `gpt-6.1-sol` at `high` for -privacy/evidence/governance. Both inspect all five changed files and the -adjacent publication, recovery, native lease and cleanup paths. Neither finds -a verified Blocker, Major or Minor. Each independently checks the original -deadline ordering, actual timer arming before the hold, publication/gate safety, -factory/callback ownership and the recovery distinction. Their offline replay -matches exact identities, durations, raw/sanitized outcomes, substitutions and -retained hashes; focused in-memory parser checks also pass. Neither executes -.NET, providers, Docker, Node or a build, edits the repository or scans processes. +- **ADR-0046 Accepted** — event delivery, the shared inbox contract and separate + delivery + ledger: stable subscription identity, readiness, durable acceptance, attempts, + cancellation, terminal transitions and targeted replay. Canonical inbox/ledger + DDL and consumer runtime are delivered by P02b-3; acceptance of the ADR alone + did not claim implementation. +- **ADR-0047 Accepted** — the background-job runtime, with the dated ADR-0003 Amendment + its storage decision owes. +- **The dated amendments the register names**, each Accepted before the code it governs: + ADR-0044 / ADR-0033 / ADR-0040 for the delivery and domain-event frames (G6), + ADR-0046 with ADR-0044/0033 disclosures and fifth-writer seam + for terminal audit (G7), ADR-0046 with ADR-0003/0006 disclosures for bounded + bypass/retry (G8/G4), ADR-0036 for the matrix staging + (G11), ADR-0032 for `LS0002` (G16), ADR-0038 for the payload-content rule (G18). +- **Database Standards § Inbox** — the canonical inbox DDL beside § Outbox, with its + table class, its policy taken by link and its grants; plus the erratum ADR-0023's + DB-side minting list owes. This phase states the **contract** — how long a + `(event, consumer)` pair stays replayable — and + [Phase 11](phase-11-production-hardening.md) picks the purge interval that honours it. +- `IOutbox` and the `OutboxFlushBehavior` invariant guard, delivered by P02b-1 + under Accepted ADR-0057; immediate INSERT uses the announced transaction. +- `TenantCreatedIntegrationEventV1` from completed provisioning; P02b-3 + independent Customization subscriptions install untouched `card@1` content-type + and `plain@1` taxonomy defaults with one-root effects and the P02b-3 Seeder + identity handoff. +- A durable `OutboxProcessor` implementing the specified lease: a fenced claim, a + per-delivery deadline, bounded retry, a terminal producer state, and the migration + that adds `locked_by` / `locked_until` **and** extends `learnstack_outbox_admin`'s + column-scoped `UPDATE` grant in the same change. +- The dispatcher's credential registered as a keyed data source behind a boot-checked + `Lazy<>`, with `LearnStack_OutboxAdmin_Role_OnlyUsedBy_OutboxProcessor` promoted + from Registered only after the full census and planted controls pass. +- `partition_key` persisted onto the row and rebuilt into the envelope on dispatch. + `PartitionKey` abstract on `IntegrationEventBase` and per-key serialisation in + `InProcessEventBus` shipped in Packet 5; the durable hop is this phase's. +- `inbox_messages` and `IInboxGuard` over the canonical DDL, the per-`(event, consumer)` + delivery transaction opened before handler construction, and tenant and organization + context restored in every handler scope from the envelope. +- A subscriber-side ledger and terminal path accepted by ADR-0046: a terminal + outcome per + subscription, a sanitized failure descriptor, its counter, its MUST-class audit row, + and targeted internal replay through the executor/inbox boundary. Producer + reset and operator permission/reason/fencing remain Phase 03 contracts. +- A worked sample flow — enqueue → outbox → dispatch → idempotent consumption — placed + where G19 settles, between modules that hold domain code, so the module-scoped sweeps + have a subject. +- Domain-event collection on the shipped seam and one dispatch site inside the owning + frame's transaction, ordered before producer invariant checks and MUST audit. + Domain reactions translate to immediate outbox INSERTs only. +- **The delivery path's audit frame** in the shape **G6** settles — the component that + performs the four owner-side acts on a transport-opened transaction, and the same + owner duties performed in the same order by every frame that owns an ambient + transaction (Packet 9 hand-off). +- The background-job runner, its storage on the path ADR-0047 names, its tenant-context + hook, its enqueue-time guard over four fields, its package pins — and no job + definition and no dashboard route. +- The registered, unmapped `outbox` health check and accepted producer event + metrics in + [Observability Standards](../standards/10-observability.md#required-metrics), + including bounded immutable snapshots. P02b-3 Step 4 delivers the separate + subscriber signals and registered, unmapped `delivery` health check. +- `UseAuthentication` and `UseAuthorization` at their two pinned positions, the claim + signal populated at the resolver's reserved site, one JWT authority for `/api/v1/*` + with its full validation contract written into + [Security Standards § Authentication](../standards/11-security.md#authentication), and + token-keyed rate-limit partitions going live with authentication — including the + change **G14** settles to the existing pre-auth floor: 60/min per canonical + visitor and 600/min peer acquisitions/allocations under ADR-0053/0054. These + anonymous visitor/peer quotas remain distinct from the token-keyed budget. +- The rejection record carrying a source, an actor and a correlation id; the recorder + writing `metadata.assertionSource` and populating `actor_user_id` on the authenticated + tier; and the resolver's refusal path calling the recorder rather than only logging. +- The host-vs-JWT tenant cross-check returning 404 through Packet 9's existing recorder + and operation key — the same key, no second detector. +- The Keycloak `learnstack` realm with a shared client scope carrying the `tenant_id` + mapper, the `user_id` mapper G10 settles, an explicit audience mapper, UUID-valued + seed attributes agreeing with `SeedData`, both attributes declared admin-only, + tenant-only seed users, the realm-role question resolved, and per-host redirect URIs. +- An idempotent reconciler that applies all of that to a warm Keycloak database on every + `make seed`, preserving existing accounts and the `learnstack-hub` realm. +- OIDC PKCE login through the BFF on the visitor's own tenant host, a cookie session + with host-only scoping and single-flight refresh, an `Origin` plus session-bound-token + CSRF control, RP-initiated logout, and Auth.js wired in `apps/web` with the two + skills' illustrative `auth` references replaced with the shipped helper. +- The first authenticated `/api/v1/*` read and the first guarded page, both in the + OpenAPI document and the regenerated SDK. +- A Keycloak test fixture over the committed realm JSON and an in-process JWT issuer for + the ADR-0036 token rows, both carrying the Docker trait where they need a container + and both visible to the trait sweep. +- `LS0002` shipping as a Warning under its catalogued rule name, with its ADR-0032 + amendment, its catalogue entry, its `AnalyzerReleases` row, its linked token source + and its four tests. +- **Carrier reconciliation**, in the change that lands each mechanism: + [Events and Outbox](../architecture/15-event-and-outbox.md) (§ Inbox table, § + Subscriber side, § Ordering, § Dead-letter — producer side, whose pushed-out + `available_after` terminal reading and manual-replay recovery both change; the + producer and consumer samples; and the dispatcher sketch's non-existent context, + unbounded type resolution, unfenced `RecordFailure` write and raw `ex.Message`); + [Infrastructure Stack Standards § Outbox and Inbox](../standards/20-infrastructure-stack.md#outbox-and-inbox) + and § Background Jobs; + [Error Handling Standards § Outbox](../standards/09-error-handling.md#outbox) and + [§ Background Jobs](../standards/09-error-handling.md#background-jobs); + [Database Standards](../standards/05-database.md); + [Observability Standards](../standards/10-observability.md); + [Identity and Auth](../architecture/13-identity-and-auth.md) and + [Frontend Architecture](../architecture/14-frontend-architecture.md); + [Security Standards](../standards/11-security.md) and + [Frontend Architecture Standards](../standards/07-frontend-architecture.md); + [Testing Standards](../standards/06-testing.md), which names Postgres as its only + integration container; the `add-integration-event` skill, whose consumer sample still + writes an audit row through a module `DbContext`; and the glossary, both for the + headwords this phase's mechanisms need and for its existing `IInboxGuard` entry, which + calls the table per-module. Four carriers will contradict this phase the day it lands + and are corrected with it: [Phase 03](phase-03-identity-admin.md), which still owns + the BFF session, the host-and-claim cross-check and logout, and acquires instead the + Hangfire dashboard route behind the Platform-scope permission with its ADR-0015 + amendment, the operator recovery surface, and this phase's stale in-code messages; + [Phase 11 § Data Operations](phase-11-production-hardening.md#data-operations), which + acquires the processed-outbox and aged-inbox purge under the `learnstack_platform` + `DELETE` grant with the no-principal constraint **G9** carries; + [Phase 08a](phase-08a-assessment-notifications.md), which credits + `OutboxFlushBehavior` to Phase 02a and books the queue two ways; and + `infra/apisix/README.md`, which dates the dashboard's gateway gating to Phase 08a. Two + more sentences go stale on landing: the post-commit-seam comment that names this + phase's outbox dispatch as its obligation, since a polling dispatcher needs no such + seam; and + [Security Standards § The out-of-band setters](../standards/11-security.md#the-out-of-band-setters), + whose transport row and reproduced count both change when the transport opens a + transaction. -Both explicitly preserve the ordering control's refused runtime-cleanup -oracle. Its natural process/container absence is not substituted for internal -quiescence. The earlier unchanged-deadline claim remains limited by the dated -finding above. Post-commit hashes match all five tested overlays. The reviewed -correction is ready for a new complete hosted A/B qualification; no prior green -sibling or failed-job rerun supplies that missing final-source proof. ## Completion Criteria @@ -17637,22 +1016,15 @@ shape depends on an open gate say so, and are written when that gate is Accepted **Producer and dispatcher** P02b-2-owned dispatcher criteria below are met by the -[Step 4 local closeout](#p02b-2-step-4--enforcement-and-closeout-2026-10-12). +[Step 4 local closeout](phase-02b-delivery-log.md#p02b-2-step-4--enforcement-and-closeout-2026-10-12). P02b-3's -[Step 6 proofs](#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 proofs](phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) also cover the combined HTTP/event-delivery tracing criterion: actual committed rows match the enqueuing activity, announced tenant/org and exact nonempty partition. The -[P02b-3 merge closeout](#p02b-3-merge-and-closeout-2026-10-15) owns final combined -event verification. P02b-4's job infrastructure is complete and merged; its -[merge closeout](#p02b-4-merge-and-closeout-2026-10-19) owns exact qualification. -P02b-5 is complete and merged after all five steps and their independent reviews; -its [merge closeout](#p02b-5-merge-and-closeout-2026-10-20) owns exact final-source -qualification and validation limits. P02b-6's four implementation steps and local -reviews are complete; its Step 4 and correction records own local qualification, -independent reviews and source-bound complete hosted receipts. -P02b-7–8 remain pending. -The whole phase is not complete. +[P02b-3 merge closeout](phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final +combined event verification. Packet state lives in the Status block at the top of +this document; this section names criteria and the records that prove them. - An aggregate change and its outbox row commit together and roll back together, asserted as `learnstack_app`. An enqueue whose event `TenantId` differs from the @@ -17756,7 +1128,7 @@ The whole phase is not complete. **Background jobs** P02b-4 meets these criteria. Its -[merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final PR-source +[merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final PR-source CI and merge verification; its dated local receipts retain their original scope. - A job enqueued without a tenant id, and one enqueued without a correlation id, each @@ -17833,7 +1205,7 @@ CI and merge verification; its dated local receipts retain their original scope. - The development realm declares the exact accepted access-token lifespan with no override on either named client. Fresh signed expiration fits the observed UTC/monotonic code-exchange window plus that configured lifespan, under the - accepted [TTL semantics](#accepted-g12g13-answers). Independent configuration, + accepted [TTL semantics](phase-02b-delivery-log.md#accepted-g12g13-answers). Independent configuration, client-override and wrong-expiration controls detect drift; shorter late-session issuance is covered separately. Exact `exp - iat` equality is not required. - The callback route rejects a response whose `state` does not match the transaction @@ -17873,7 +1245,7 @@ CI and merge verification; its dated local receipts retain their original scope. Refresh publishes one complete immutable queue snapshot; each gauge reads an immutable snapshot. Pending, deferred, terminal and normal eligibility are tested as distinct states. Job dimensions are implemented under Accepted G9/G17; - the [P02b-4 merge closeout](#p02b-4-merge-and-closeout-2026-10-19) records final + the [P02b-4 merge closeout](phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) records final qualification, while Standards 10 owns the exact inventory. - **No row in the [catalogue](../standards/21-architecture-tests-catalogue.md) whose Phase names 02b is still Registered or Awaiting backfill.** Structural rows are green diff --git a/docs/roadmap/phase-02c-hub-foundation.md b/docs/roadmap/phase-02c-hub-foundation.md index c5caf4d0..8ddf5731 100644 --- a/docs/roadmap/phase-02c-hub-foundation.md +++ b/docs/roadmap/phase-02c-hub-foundation.md @@ -220,7 +220,7 @@ never a reason to fail a tenant's request. `IFeatureFlags.GetLimitAsync` returns the allowance — `-1` unlimited, `0` denied, `> 0` the allowance — and every `LimitKey` declares its `LimitEnforcement` (`Soft` | `Hard`). It shipped no gate. The first hard authoring gate is the -[approved content-type quota](phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19), +[approved content-type quota](phase-04-cms-media-pages.md#content-type-quota-accounting), which introduces the shared `403 limit_exceeded` mapping. The soft-limit reporting path lands here, because this is the first phase in which it has anywhere to report to ([ADR-0045 § 6](../decisions/0045-entitlement-and-feature-flag-socket.md)). diff --git a/docs/roadmap/phase-02d-delivery-log.md b/docs/roadmap/phase-02d-delivery-log.md new file mode 100644 index 00000000..59e36146 --- /dev/null +++ b/docs/roadmap/phase-02d-delivery-log.md @@ -0,0 +1,6795 @@ +# Phase 02d — delivery log + +The dated record of +[Phase 02d: Two-Tenant Walking Skeleton](phase-02d-walking-skeleton.md). +The phase document holds the plan and the current Status; this log holds what +each packet decided and delivered, as +[ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md) decides. + +- **Append-only.** A new entry is a `###` heading under its packet's `##` + section, with its date in the heading. A shipped packet's entries are not + rewritten; a false citation gets the dated inline correction + [Documentation Standards § Doc Types](../standards/13-documentation.md#doc-types) + prescribes. +- **Decision packages are normative.** An Accepted package's answers bind exactly + as the phase document would; the phase document's decision register links each + one. +- **Moved, not rewritten.** Every entry dated up to 2026-10-22 moved here from the + phase document with its heading text and anchor unchanged. Heading levels shifted + to sit under the packet sections, and links whose targets now live in the other + file were retargeted. Position words inside a moved entry — *above*, *below*, + *the register* — still mean the single document it was written in; the plan + sections they point at now live in the phase document. The + [Status archive](#status-archive) keeps the retired Status block. +- **Read the index, not the log.** The index below lists every packet section, + every entry and every dated sub-entry with its length in lines. Pick the entry + there, search for its heading to find its line, and read only that many lines. + After adding an entry, run `make docs-index`: the index is generated navigation, + not a record, and CI refuses a stale one. + +<!-- BEGIN GENERATED INDEX: scripts/delivery-log-index.py — run `make docs-index`; do not edit by hand --> + +**Index** + +- [P02d-1 — Education schema and database-level isolation](#p02d-1--education-schema-and-database-level-isolation) — 430 lines + - [P02d-1 decision pass (2026-09-14)](#p02d-1-decision-pass-2026-09-14) — 134 lines + - [Delivery Record (P02d-1)](#delivery-record-p02d-1) — 294 lines + - [Step 1 — Shared database controls (2026-09-14)](#step-1--shared-database-controls-2026-09-14) — 28 lines + - [Step 2 — Education schema and isolation (2026-09-14)](#step-2--education-schema-and-isolation-2026-09-14) — 45 lines + - [Step 3 — Packet completion (2026-09-14)](#step-3--packet-completion-2026-09-14) — 210 lines + - [PR verification (2026-09-14)](#pr-verification-2026-09-14) — 36 lines + - [Independent PR review follow-up (2026-09-14)](#independent-pr-review-follow-up-2026-09-14) — 63 lines + - [Merge and closeout (2026-09-14)](#merge-and-closeout-2026-09-14) — 37 lines +- [P02d-2 — Writers and seed](#p02d-2--writers-and-seed) — 730 lines + - [Pending Course Marketplace proposal](#pending-course-marketplace-proposal) — 30 lines + - [P02d-2 decision package (2026-10-02)](#p02d-2-decision-package-2026-10-02) — 195 lines + - [G3 supersession (2026-10-02)](#g3-supersession-2026-10-02) — 28 lines + - [P02d-2 implementation delivery (2026-10-02)](#p02d-2-implementation-delivery-2026-10-02) — 449 lines + - [PR review corrections (2026-10-02)](#pr-review-corrections-2026-10-02) — 71 lines + - [Additional PR review corrections (2026-10-02)](#additional-pr-review-corrections-2026-10-02) — 89 lines + - [Branding tenant-existence correction (2026-10-02)](#branding-tenant-existence-correction-2026-10-02) — 28 lines + - [P02d-2 merge and closeout (2026-10-02)](#p02d-2-merge-and-closeout-2026-10-02) — 54 lines +- [P02d-3 — Read internals](#p02d-3--read-internals) — 543 lines + - [P02d-3 decision package (2026-10-02)](#p02d-3-decision-package-2026-10-02) — 212 lines + - [Delivery record: P02d-3](#delivery-record-p02d-3) — 276 lines + - [PR #24 review remediation (2026-10-03)](#pr-24-review-remediation-2026-10-03) — 78 lines + - [PR #24 depth and settings correction (2026-10-03)](#pr-24-depth-and-settings-correction-2026-10-03) — 30 lines + - [P02d-3 merge and closeout (2026-10-03)](#p02d-3-merge-and-closeout-2026-10-03) — 53 lines +- [P02d-4 — Public read API and contract checks](#p02d-4--public-read-api-and-contract-checks) — 1,016 lines + - [P02d-4 decision package (2026-10-03)](#p02d-4-decision-package-2026-10-03) — 650 lines + - [P02d-4 Step 3: public Education reads](#p02d-4-step-3-public-education-reads) — 89 lines + - [P02d-4 Step 4: contract, SDK and CI](#p02d-4-step-4-contract-sdk-and-ci) — 216 lines + - [P02d-4 merge and closeout (2026-10-08)](#p02d-4-merge-and-closeout-2026-10-08) — 59 lines +- [P02d-5 — Server-rendering path](#p02d-5--server-rendering-path) — 1,155 lines + - [P02d-5 decision package (2026-10-08)](#p02d-5-decision-package-2026-10-08) — 237 lines + - [P02d-5 delivery record](#p02d-5-delivery-record) — 372 lines + - [P02d-5 packet closeout (2026-10-09)](#p02d-5-packet-closeout-2026-10-09) — 88 lines + - [P02d-5 external-review remediation (2026-10-09)](#p02d-5-external-review-remediation-2026-10-09) — 483 lines + - [P02d-5 merge and closeout (2026-10-09)](#p02d-5-merge-and-closeout-2026-10-09) — 61 lines +- [P02d-6 — Public renderer](#p02d-6--public-renderer) — 1,713 lines + - [P02d-6 decision package (2026-10-09)](#p02d-6-decision-package-2026-10-09) — 300 lines + - [Acceptance validation (2026-10-10)](#acceptance-validation-2026-10-10) — 9 lines + - [External i18n draft review reconciliation (2026-10-09)](#external-i18n-draft-review-reconciliation-2026-10-09) — 24 lines + - [P02d-6 Step 1: Localization and document foundation](#p02d-6-step-1-localization-and-document-foundation) — 93 lines + - [Step 1 review round 1 (2026-10-10)](#step-1-review-round-1-2026-10-10) — 14 lines + - [Step 1 review round 2 (2026-10-10)](#step-1-review-round-2-2026-10-10) — 18 lines + - [P02d-6 Step 2: Catalog and course pages](#p02d-6-step-2-catalog-and-course-pages) — 67 lines + - [P02d-6 Step 3: Ordered lesson presentation](#p02d-6-step-3-ordered-lesson-presentation) — 89 lines + - [Step 3 review round 1 (2026-10-10)](#step-3-review-round-1-2026-10-10) — 20 lines + - [Step 3 review round 2 (2026-10-10)](#step-3-review-round-2-2026-10-10) — 19 lines + - [P02d-6 Step 4: Product proof and accessibility closeout](#p02d-6-step-4-product-proof-and-accessibility-closeout) — 1,095 lines + - [Step 4 review round 1 (2026-10-10)](#step-4-review-round-1-2026-10-10) — 23 lines + - [Step 4 review round 2 and automated verification (2026-10-10)](#step-4-review-round-2-and-automated-verification-2026-10-10) — 36 lines + - [Manual accessibility handoff (2026-10-10)](#manual-accessibility-handoff-2026-10-10) — 17 lines + - [Manual browser observations and remaining AT check (2026-10-10)](#manual-browser-observations-and-remaining-at-check-2026-10-10) — 60 lines + - [P02d-6 packet closeout (2026-10-10)](#p02d-6-packet-closeout-2026-10-10) — 63 lines + - [P02d-6 external-review remediation (2026-10-10)](#p02d-6-external-review-remediation-2026-10-10) — 51 lines + - [P02d-6 systematic-review decision package (2026-10-10)](#p02d-6-systematic-review-decision-package-2026-10-10) — 800 lines + - [Maintainer decisions (2026-10-10)](#maintainer-decisions-2026-10-10) — 49 lines + - [Test-toolchain migration — approved (2026-10-10)](#test-toolchain-migration--approved-2026-10-10) — 24 lines + - [ADR-0055 draft review reconciliation (2026-10-10)](#adr-0055-draft-review-reconciliation-2026-10-10) — 29 lines + - [ADR-0055 isolated feasibility observation (2026-10-10)](#adr-0055-isolated-feasibility-observation-2026-10-10) — 38 lines + - [ADR-0055 acceptance and implementation plan (2026-10-10)](#adr-0055-acceptance-and-implementation-plan-2026-10-10) — 384 lines + - [P02d-6 merge and closeout (2026-10-10)](#p02d-6-merge-and-closeout-2026-10-10) — 67 lines +- [P02d-7 — Demo, full-stack CI and exit](#p02d-7--demo-full-stack-ci-and-exit) — 956 lines + - [P02d-7 decision package (2026-10-10)](#p02d-7-decision-package-2026-10-10) — 219 lines + - [P02d-7 Step 1 — shared demo lifecycle (2026-10-11)](#p02d-7-step-1--shared-demo-lifecycle-2026-10-11) — 83 lines + - [P02d-7 Step 2 — genericity and exit foundations (2026-10-11)](#p02d-7-step-2--genericity-and-exit-foundations-2026-10-11) — 92 lines + - [P02d-7 Step 3 — browser and audit proof (2026-10-11)](#p02d-7-step-3--browser-and-audit-proof-2026-10-11) — 150 lines + - [P02d-7 Step 4 — CI enforcement and phase exit (2026-10-11)](#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) — 342 lines + - [Step 4 review round 1 (2026-10-11)](#step-4-review-round-1-2026-10-11) — 35 lines + - [Step 4 review round 2 (2026-10-11)](#step-4-review-round-2-2026-10-11) — 25 lines + - [P02d-7 CI and phase-exit closeout (2026-10-11)](#p02d-7-ci-and-phase-exit-closeout-2026-10-11) — 217 lines + - [Reviewed implementation head verification (2026-10-11)](#reviewed-implementation-head-verification-2026-10-11) — 19 lines + - [External review follow-up (2026-10-11)](#external-review-follow-up-2026-10-11) — 21 lines + - [Systematic review remediation (2026-10-11)](#systematic-review-remediation-2026-10-11) — 117 lines + - [P02d-7 merge and closeout (2026-10-11)](#p02d-7-merge-and-closeout-2026-10-11) — 68 lines +- [Status archive](#status-archive) — 143 lines + +<!-- END GENERATED INDEX --> + +## P02d-1 — Education schema and database-level isolation + +### P02d-1 decision pass (2026-09-14) + +**Accepted — 2026-09-14, verified against `6c58343`.** The maintainer approved +this decision package before implementation. The +[Education spec](../modules/education/README.md) owns the accepted schema detail and +matrices, with its pinned module-list registration. No production implementation is +claimed by this decision pass. The kickoff remains the historical entry record; +[P02d-1's delivery record](#delivery-record-p02d-1) records this pass separately. + +#### P02d-1 accepted answers + +| Gate or part | Accepted answer | Decision/detail owner | +|---|---|---| +| G1 | Roadmap-wide closure notation: preserve the original question, record `Accepted — YYYY-MM-DD` with an anchor to the answer and its accepted vehicle; identify the exact closed part of a split gate. Packet status and delivery record list the closed parts. A proposed document closes nothing | [Decision Timing](README.md#decision-timing) | +| G2 | Separate `Course` and `Lesson` roots; natural-key translation entities contained by their own root; Lesson → Course `RESTRICT`, translations → root `CASCADE`; no independent satellite soft deletion. Stable ids and URLs survive Phase 05's migration | [Education data model](../modules/education/README.md#data-model-and-invariants) | +| G3 — values and publication contract | Both roots have `draft` / `published`; publication permits anonymous reading, with both states required for a lesson. No version snapshot or cascade publication. The transition contract is decided with the column; command names and seed acts stay with P02d-2 | [ADR-0048](../decisions/0048-walking-skeleton-publication.md); P02d-2 still closes the remaining G3 details | +| G4 | One exact content-type revision pin on `lessons`; JSON object body per locale on `lesson_translations`; repeated non-translatable values remain per locale. No schema-profile keyword or cross-chain FK | [Education data model](../modules/education/README.md#data-model-and-invariants); Standards 08 removes the unimplemented `isLocalized` claim | +| G5 — column | Optional all-or-none, revision-pinned taxonomy/band triple on `courses`. A successor cannot relabel or remove the course's stored band by rebinding it | [Education data model](../modules/education/README.md#data-model-and-invariants); Phase 05 carries an explicit pin-preservation obligation | +| G6 (a) | The shipped `LocaleTag` spelling in `varchar(35)`, including script Title case and region uppercase | [Education locale identity](../modules/education/README.md#localization-and-url-identity); Standards 08 and Standards 05 satellite sketch | +| G7 — database control | Exact organization write scope, including INSERT; an invoker INSERT/UPDATE trigger checks each parent mirror in addition to factory derivation and tenant-composite FKs. No audit exception to the stricter INSERT rule | [ADR-0003 Amendment 6](../decisions/0003-tenant-isolation-defense-in-depth.md#amendment-6--insert-scope-and-parent-mirrors-2026-09-14); writer contract details remain in P02d-2 | +| G8 | Structural proofs for tenant-composite foreign keys, organization immutability, parent-scope mirroring and Pattern A storage, each with a planted offender; shared immutability errors must not read `OLD.id` | Register rows in Standards 21 before implementation; Standards 05 owns the SQL and chain dependency | +| G9; G26 — slug grammar | Content slugs: 1–160 lowercase ASCII characters with single interior hyphens; refuse UUID `N` and `D` shapes, and do not normalize invalid input silently. No Tenancy or Customization FK. Role grants are enumerated below | [Education URL identity](../modules/education/README.md#localization-and-url-identity); Standards 08 and Standards 05. G26 route templates remain open | +| G10 — order | Catalog `(created_at ASC, id ASC)`, oldest-created first; lessons `(sort ASC, id ASC)` with nonnegative sort and permitted ties | [Education data model](../modules/education/README.md#data-model-and-invariants); the cursor codec remains P02d-4's decision | + +**Database privileges for P02d-1.** On both roots, `learnstack_app` gets +`SELECT, INSERT, UPDATE`; updates are needed for publication, root concurrency and +later translation writes. On both satellites it gets `SELECT, INSERT`; P02d-2's +writers add a locale once, and no replacement or editing command is introduced here. +`learnstack_platform` gets `SELECT` on all four tables. `learnstack_outbox_admin` and +`PUBLIC` get none. Migration ownership is unchanged. A later command needing more +privileges brings its own migration; grants do not anticipate that command. To prove +an UPDATE/DELETE policy independently of a missing privilege, a separate disposable +test database commits the owner's test-only grant, then asserts through a separately +authenticated `learnstack_app` connection. The database is discarded afterward. The +real grant matrix is tested against an untouched migrated fixture. + +**Organization-immutability scope.** G8's shorthand "every table carrying +`organization_id`" needs a table-class qualification. The guard covers tables +classified organization-scoped by Standards 05. `platform_host_to_tenant` is a +platform-scoped host projection, and `outbox_messages` is tenant-wide with organization +metadata; neither becomes organization-scoped because it has that column. +`audit_log`'s append-only guard counts only if its behavior demonstrably refuses an +organization change. The catalogue must enumerate these distinctions and prove its +exemptions cannot hide a newly unguarded organization-scoped table. + +#### Review findings and implementation obligations + +The four accepted catalogue identifiers are +`Every_TenantOwned_Foreign_Key_Includes_TenantId`, +`Every_OrgScoped_Table_Has_An_Organization_Immutability_Guard`, +`Every_Organization_Mirroring_Child_Has_A_Parent_Scope_Guard` and +`Pattern_A_Content_Uses_Translation_Satellites`. They are Registered in Standards +21 by this decision pass and become Implemented with their proofs. The last rule +rejects ad-hoc per-locale columns as well as a misplaced translatable parent column. + +Two independent pre-development reviews checked the model/localization and database +isolation surfaces. The following are confirmed against this pass's baseline: + +- The `WITH CHECK` on `tenant_settings` and `audit_log` admits a null organization + from an organization-scoped session. ADR-0003 Amendment 5 tightened UPDATE and DELETE + only; the adjacent erratum and Amendment 6 correct its broader statement. Both + existing tables need forward migrations; old migrations remain untouched. +- `fn_organization_id_immutable` refers to `OLD.id`, which neither satellite + has. The shared function needs a Tenancy-chain replacement and a no-id regression + case. Education must migrate after that dependency, including in rollback tests. +- A generated normalized scope key with a three-column FK worked in PostgreSQL but + failed the natural EF graph mapping on the repository's pinned packages. The pass + therefore chooses the invoker INSERT/UPDATE parent check, tested independently + under the application role, rather than prescribing an unproven EF workaround. +- An unlocked parent lookup admitted a delete/reinsert race under test-only DELETE + privileges: a parent could be replaced under the same id with another organization + before the child FK ran. `FOR KEY SHARE` prevented the replacement; the child and + parent retained matching scopes. Amendment 6 requires that lock. +- A BEFORE parent check can refuse a malformed child before RLS or the FK does. The + Education suite needs a separate disposable fixture with only that parent guard + removed by committed owner setup, followed by assertions through an authenticated + `learnstack_app` connection, to prove each lower layer independently. The normal + fixture proves all controls together; no production bypass is introduced. +- The level revision pin must be preserved by Phase 05's future `Level` projection; + its current active-only wording cannot silently reinterpret a stored course. +- Plain satellites retain slug reservations after parent soft deletion. The spec + states this explicitly; applying a soft-delete filter to a nonexistent column is + not a valid uniqueness strategy. +- Standards 08 now records canonical locale casing and removes the unimplemented + `isLocalized` marker. Schema `$ref` recursion and content-entry reference depth are different + mechanisms: ADR-0043 refuses all schema cycles. The Phase 05 wording is corrected. +- The extension overview's stale phase table and runtime claims, and Phase 04's stale + customization uniqueness premise, are corrected against the canonical owners. +- The decision-pass inspection found that live GitHub branch protection required + `meta (commit hygiene + link audit)` while CI reported + `meta (compose + commit hygiene + link audit)`, and did not require + `backend integration (Testcontainers)`. The approved exact repair preserves the + other checks and maintainer-approved settings; [Step 3](#step-3--packet-completion-2026-09-14) + records its application and verification. + +The relevant corpus includes the roadmap baseline and exit criteria; Domain Model, +module boundaries, tenant isolation, localization and customization architecture; +ADRs 0003, 0008, 0010, 0013, 0017, 0018, 0023, 0033, 0039–0044; the Tenancy, +Customization and Audit specifications; and Standards 01, 02, 05, 06, 08, 11, 13–15, +17–19 and 21. Accepted decision bodies are preserved, with the bounded ADR-0041 +erratum beside Amendment 5's false statement. The approved records and their carrier +documents form the packet's first commit, before production implementation. + +#### Approved implementation sequence + +All work stays on `development`. No destructive migration, new package, Hub change or +cross-module Domain reference is planned. + +0. **Decision commit.** Accept the records, close the exact gate parts above, register + the structural rules, and reconcile the carrier documents and Education spec. +1. **Shared database controls.** Tighten the two existing INSERT policies by forward + migrations, fix the shared immutability function, and add structural/regression + proofs over existing tables, including audit, no-organization and pooled-GUC cases. +2. **Education schema and isolation.** Add both roots and their satellites, EF mapping, + the Education migration chain, its role grants and parent-scope control. Add unit, + schema-level isolation and Pattern A proofs with positive controls, and wire every + fixture, migration runner and matrix-discovery list that must see the new chain. +3. **Packet completion.** Apply and re-read the exact GitHub required-check changes; + run the complete relevant checks, verify fresh migration and reverse-chain behavior, + update all counts/status carriers and the packet delivery record, then commit. + +Each implementation step is committed after its checks, then receives two independent +review rounds from fresh agents. Confirmed findings are fixed and committed before +the next round or step. Reviewer assignments cover security/isolation, correctness, +concurrency, migration/rollback, tests that can fail, maintainability and corpus drift. +The available review models are used; this environment provides no Opus or Sonnet. + +Validation includes warnings-as-errors builds, backend formatting, architecture, +unit, contract and integration suites (real PostgreSQL as `learnstack_app`, zero +skips), a documentation link audit and migration-chain coverage. The pre-change run on +2026-09-14 passed **2,039** tests: 1,373 unit, 175 architecture, 490 integration and one +contract, with zero skips. This is a baseline, not validation of the accepted schema. +P02d-1 does not claim the later packets' writer, HTTP or browser evidence. + +### Delivery Record (P02d-1) + +**Decision pass — 2026-09-14.** Maintainer approval closes G1, G2, G3 (values and +publication/transition contract), G4, G5 (column), G6 (a), G7 (database controls and +factory derivation), G8, G9, G10 (order), and G26 (slug grammar), through the +[accepted answers](#p02d-1-accepted-answers). ADR-0048 is Accepted and ADR-0003 gains +Accepted Amendment 6. At this decision commit, the Education spec became design stable, +the module matrix list gained Education, and the four structural rules were Registered. +The following records distinguish that accepted design from its implementation and +verification. + +#### Step 1 — Shared database controls (2026-09-14) + +The Tenancy and Audit forward migrations require exact organization scope for +INSERT while preserving reads, existing restrictive write policies and stored rows. +Tenancy's shared immutability function now supports natural-key rows without `id`. +The tenant-composite FK and organization-immutability catalogue rules are Implemented, +with planted violations and repaired positive controls over the applied schema. + +Behavioral proofs use authenticated `learnstack_app` connections. They cover both +existing tables, the tenant reporting hatch, pooled-session reuse after commit and +rollback, the no-id function and audit's append-only alternative. Disposable databases +keep test-only grants and control removal outside the shared schema. A populated +historical-schema test proves upgrade, exact Down restoration and reapplication. + +The full backend suite passes **2,082** cases: 1,373 unit, 175 architecture, +533 integration and one contract, with zero skips. Backend formatting and generated +SQL checks pass. The first full run exposed three legacy audit tests whose manually +declared intents omitted the organization their transaction announced; those fixtures +now copy the execution context exactly as `AuditLogBehavior` does. No production audit +exception or policy relaxation was needed. The localization overview and storage +examples also now distinguish accepted Education storage from later authoring behavior. + +Commit `807049a` completed two independent review rounds: three reviewers in round 1, +two fresh reviewers in round 2, covering security, migrations, runtime writers, proof +soundness and corpus consistency. Both rounds approved without findings or a required +fix commit. Each round independently reran 39 focused schema/migration cases; round 2 +also reran six architecture/corpus checks. All reported zero skips. + +#### Step 2 — Education schema and isolation (2026-09-14) + +Both aggregate roots and their natural-key translations are implemented. Education's +fifth migration chain creates four tables with exact organization INSERT scope, +restrictive UPDATE/DELETE policies, immutable organization ids, tenant-composite FKs, +parent-scope checks and the accepted grants. The API and seeder resolve its context on +the existing ambient transaction. No command or endpoint is introduced here. + +The parent-mirror and Pattern A catalogue rules are Implemented. Their companions +plant absent subjects, weakened trigger controls, misplaced localized fields and +widened slug uniqueness. The applied schema sweeps and populated fixture include all +four Education tables. Domain tests constrain independent publication, locale +identity, exact pins, slug grammar and mutation atomicity. Actual app-role EF writes +prove graph persistence, contained audit capture and optimistic concurrency for +translation additions. Raw and filter-bypassing reads independently prove RLS. + +Disposable databases isolate tests that grant missing mutation/TEMP privileges or +remove the parent trigger to reach RLS and foreign keys separately. Parent checks are +tested on insertion and reparenting, against temporary-table shadowing, and while a +test barrier holds execution between the lookup and the FK. This distinguishes the +required lookup lock from the FK's later lock. Reversal removes dependent chains first; +reapplication then persists populated Education rows as `learnstack_app`. + +The full backend run passes **2,363** cases: 1,453 unit, 177 architecture, +732 integration and one contract, with zero skips. The migration model has no pending +changes; backend formatting, generated Up/Down SQL and the documentation link audit pass. PostgreSQL text +validation reuses the shared predicate instead of introducing an Education copy. + +Round 1 reviewed commit `e5b8187` with three independent reviewers. Domain/EF/audit +and security/migration reviews approved; the latter independently reran all twelve +parent-scope cases and the complete reverse/reapply case. The proof review found one +Major gap: Pattern A's parent-field detector omitted `description` and +`seo_description`, although Standards 08 explicitly forbids them on a parent. The +production schema contained neither field. Three new applied-schema companions +failed against the old detector (plain, locale-suffixed and SEO-prefixed descriptions), +then passed after both the schema and CLR/model predicates were corrected. Each +companion also removes its planted column and verifies the same detector is clean. +All 41 Education structural cases pass with zero skips after this repair. + +Round 2 reviewed the implementation and fix with three fresh reviewers. All approved +without further findings. Independent focused runs passed 281 security/persistence +cases and 129 structural/schema/migration cases, each with zero skips. The final full +run after the repair passes **2,366** cases: 1,453 unit, 177 architecture, 735 integration +and one contract, with zero skips. + +#### Step 3 — Packet completion (2026-09-14) + +The approved GitHub repair was applied only to `main`'s `required_status_checks` +endpoint. A fresh full-protection API read at **2026-09-14 13:04 UTC** verified the +following snapshot, comparing check identities as a set because GitHub reordered the +entries. All five retain GitHub Actions `app_id: 15368`; `strict` remains `true`. + +```json +{ + "strict": true, + "checks": [ + { "context": "backend (build + unit + arch + contract)", "app_id": 15368 }, + { "context": "frontend (typecheck + lint + build + test)", "app_id": 15368 }, + { "context": "secret scan (leakwatch)", "app_id": 15368 }, + { "context": "meta (compose + commit hygiene + link audit)", "app_id": 15368 }, + { "context": "backend integration (Testcontainers)", "app_id": 15368 } + ] +} +``` + +Verification command: +`gh api repos/HodeTech/LearnStack/branches/main/protection/required_status_checks`. +The full before/after comparison also verified that every field outside +`required_status_checks` remained unchanged, including the separately approved +single-maintainer exceptions. CONTRIBUTING and both affected standards-index rows now +state the live setting. The later OpenAPI and Lighthouse gates retain their owning +packets and open decisions. + +The previous packet's `main` merge commit was merged into `development` without +rewriting history or switching branches. The tree before and after that merge was +identical, and `origin/main` is now an ancestor of the packet branch. This satisfies the +strict up-to-date requirement without changing the reviewed implementation. + +The final full backend run passes **2,366** cases with zero failures or skips; the +nonempty-run checker verifies all four assemblies. Fresh-schema, populated upgrade, +full reversal and app-role reapplication proofs pass. The manual aggregate review +also confirms the accepted roles match the applied foreign keys: Lesson is a separate +root with RESTRICT to Course; each plain satellite CASCADEs only to its own root. +Education commands and public-read eligibility remain the explicitly owned work of +P02d-2 and P02d-4. + +Informational coverage combines successful unit and integration runs by source +line/branch identity, excluding generated `obj` and EF migration files: Education +Domain is **235/235 lines and 80/80 branches (100%)**; Infrastructure is **139/152 +lines (91.45%) and 0/2 branches**. The uncovered lines and branches belong only to the +design-time factory, exercised separately by the EF CLI model and SQL checks. The +first solution-wide coverage attempt failed when a Coverlet-injected tracker type +could not be resolved by NetArchTest's IL/reflection sweep; it is not passing evidence. +The subsequent unit/integration coverage runs and uninstrumented **177-case** +architecture run pass. The local-test skill now records that working procedure; +no test or assertion was skipped or weakened. + +Backend formatting, all 177 architecture cases, 1,479 changed-Markdown relative +path/anchor checks, the tracked-file `docs/analysis/` residual scan and strict commit +hygiene pass. The two fresh-agent review rounds and PR required-check rollup +comparison are recorded below. + +Round 1 reviewed commit `7c50e01` with two fresh reviewers. The delivery reviewer +recomputed the TRX and coverage figures, checked the migration assertions and reran +the link audit without findings. The operational reviewer independently verified the +live protection setting and found one stale inherited-baseline paragraph still saying +integration was not required; it is corrected above. The author's PR preparation also +found that CONTRIBUTING and the commit skill prescribed headings different from +Standard 14. Both now follow its canonical description structure, with the skill's +existing isolation-risk disclosure retained. These are carrier corrections, not new +decisions. + +Round 2 reviewed `4d46560..ddb3454` with two fresh reviewers. Both approved without +further findings. They independently recomputed test/coverage figures, reran the +1,479-link audit, checked migration evidence, verified the live required-check names +and attribution against CI, and confirmed that the merge tree matches its first +parent and all unrelated protection fields remain unchanged. All three implementation +steps and their two review rounds are complete. + +##### PR verification (2026-09-14) + +[PR #22](https://github.com/HodeTech/LearnStack/pull/22), `development` → `main`, +passed [CI run 34848230938](https://github.com/HodeTech/LearnStack/actions/runs/34848230938) +on head `158f67da62dd6d8b4b542ec27ca0107c980d3ff5`. At **13:20 UTC**, a fresh live +protection read was compared with the commit's check runs. Each of the five required +contexts appeared exactly once with `app_id: 15368`, status `completed` and conclusion +`success`; none was satisfied by a skipped job or a legacy name. + +| Required context | Result | +|---|---| +| `backend (build + unit + arch + contract)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296320) | +| `frontend (typecheck + lint + build + test)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296248) | +| `secret scan (leakwatch)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989295976) | +| `meta (compose + commit hygiene + link audit)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296236) | +| `backend integration (Testcontainers)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296276) | + +The backend jobs reran the same **2,366** cases: 564 Docker integration, 171 HTTP +integration, 1,453 unit, 177 architecture and one contract, all with zero skips. +Both jobs' nonempty-run checks passed. + +The deferred OpenAPI and Lighthouse placeholders are outside this required set and +retain their later packet gates. The PR's current check rollup is the verification +source for any later head. P02d-1 is complete and the PR is ready for the maintainer's +detailed review. + +The PR's subsequent automated review identified three corpus corrections: a remaining +CODEOWNERS reference in the extension overview, omitted P02d-1 expansion metadata on +the migration-order rule, and an ambiguous Phase 04 revision paragraph. The first two +now match their current owners. The revision clarification records the shipped +Draft-only body guard and links the lifecycle question that ADR-0043 § 6 already leaves +with Phase 04; it does not introduce a successor-draft/history-storage design or change +the accepted versioned identity. These documentation corrections preserve P02d-1's +implementation and accepted scope. + + +##### Independent PR review follow-up (2026-09-14) + +The maintainer's review report was assessed against `35e54eb` and the accepted +P02d-1 answers. Two bounded follow-up steps address its verified findings without +adding production behavior or changing an accepted decision. + +**Step 1 — proofs (`c98bcb2`, `58afa6d`).** All eight Education field-level refusal +keys now have exact field and message-key assertions. Invalid summary controls cover +NUL and unpaired high/low surrogates while preserving prior content and the root's +version. Pattern A detects localized slug/locale suffixes in the applied schema and +uses separate probes for unmapped CLR fields and EF shadow columns. The old detector +fails six new controls; the repaired detector passes all 49 structural cases. +Application-role checks now cover the remaining constraint and organization-scope +connection boundaries, including both pool checkouts. + +Two fresh reviewers approved round 1. Round 2 used two different reviewers and found +that publication tests sampled invalid values without proving the database's complete +closed set. `58afa6d` compares the validated applied CHECK's whole predicate and value +set with each root's actual EF converter. Four planted constraints cover extra states +and an OR bypass on both roots; each is rejected by the comparison and passes after +repair. The reviewer who identified the gap verified the fix and closed the finding. + +**Step 2 — corpus reconciliation.** The result of every report item is recorded below; +items that proposed a new rule are distinguished from defects in the accepted scope. + +| Report item | Disposition | +|---|---| +| H1 | Corrected Database Standards' stale P02d-1 completion statement. | +| H2 | Exact field/reason assertions cover all eight Education keys, including dedicated Summary refusals. | +| H3; T1; T2 | Repaired slug/locale suffix detection; added applied, unmapped-CLR and shadow-column controls. | +| H4; Doc4 | Kept the accepted Education column inventory; aligned Standard 08's illustrative satellite with `summary` and clarified the inventory's scope in the test catalogue. Pattern A does not require every possible SEO field on every entity. Also corrected the stale publish-only collision wording: a draft reserves its slug on translation insertion. | +| H5 | Indexed existing Amendments 4–6. Preserved ADR-0003's Status under [the immutable-metadata rule](../standards/13-documentation.md#when-the-body-says-something-false). No ADR body or decision changed. | +| D1 | No nonblank rule exists for optional Summary in the accepted model. Whitespace acceptance is not a demonstrated defect; the proposed rejection policy was not introduced. | +| D2 | Canonicalization remains the shipped application responsibility, per [Localization architecture](../architecture/12-localization.md#tenant-locale-configuration). A new database locale-shape policy was not part of the accepted P02d-1 contract. | +| D3 | Parent scope and public eligibility are separate contracts. [ADR-0048](../decisions/0048-walking-skeleton-publication.md) assigns combined parent/deletion eligibility to reads; an active-parent creation rule was not silently added. | +| D4 | The private helper's `nameof(key)` names its actual parameter. Assigned-id helper reuse, parsing consolidation and cached read-only wrappers are optional refactors without a demonstrated correctness or workload defect; no production cleanup was bundled. | +| C1 | Corrected the ordering claim: fixtures and `make migrate` both honor Tenancy's dependencies; their independent Audit/Customization order need not match. | +| C2 | Documented the full-index versus live-only ordered-index purposes in the [Education performance section](../modules/education/README.md#performance-budget); retained the indexes. | +| C3 | Aligned the illustrative `created_at` DDL with the existing application-clock audit convention. No database timestamp fallback was added. | +| C4 | Compared actual converter output with the applied closed-set constraint, including the additional round-2 mutation controls above. | +| T3 | Added explicit authenticated/effective application-role and no-superuser/no-bypass assertions at the reported connection boundaries. | +| Doc1 | Not a defect: the earlier wording names the repository policy scan, not a private artifact. Its exact historical wording is preserved under the [delivery-record rule](../standards/13-documentation.md#doc-types). | +| Doc2 | Added glossary entries for publication, revision pin and parent organization mirror, with links to their existing authorities and from the module spec. | +| Doc3 | Kept normative slug grammar in [Standard 08](../standards/08-localization.md#education-slug-grammar) and executable checks in Standard 05; architecture and module prose link to them. The accepted-answer table remains its historical decision summary. | +| Doc5 | Added the current resource/action/scope matrix with no registered permissions or default grants, preserving the named owners of later command surfaces. | +| Doc6 | Distinguished Standard 14's canonical PR sections from the commit skill's existing risk and attribution supplements. | +| Doc7 | Stale at the reviewed head: the final-check checkbox was already checked for `35e54eb`. Later heads are verified through the live PR rollup. | + +The report's R1–R5 observations introduce no new packet defect. The +[isolation template and role model](../standards/05-database.md#tenant-owned-and-organization-scoped-tables), +[migration dependency and reversal rules](../standards/05-database.md#migrations), +[accepted database privileges](#p02d-1-accepted-answers) and +[Education scope/locale contract](../modules/education/README.md#data-model-and-invariants) +remain their authorities. No new production writer, cross-chain foreign key or +publication/deletion policy is inferred from those observations. + +The full Release backend run after the test fixes passes **2,381** cases: +**1,456 unit, 177 architecture, 747 integration and one contract**, with zero failures +or skips. The nonempty-run checker verifies every assembly. The earlier 2,366-case +and coverage figures above remain dated evidence for their original heads. This +follow-up changes no production source or migration. [PR #22](https://github.com/HodeTech/LearnStack/pull/22) +remains the current check-rollup and review surface. + +##### Merge and closeout (2026-09-14) + +[PR #22](https://github.com/HodeTech/LearnStack/pull/22) merged into `main` at +**20:22:17 UTC**, with final PR head `bc181702e379fec99da43015b2ee357ad772d6d1` +and merge commit `1d3a0f717523bebbf8c397ae9facba7c80eafae9`. The merge tree is +identical to the final PR head. `development` was fast-forwarded to that merge +commit without switching branches, rewriting history or changing file contents. + +- [x] P02d-1's accepted decision parts, all three implementation steps and their + two review rounds are complete, as recorded above. +- [x] The final review's three verified documentation findings are resolved in + `bc18170`: README delivery status, the Course/Lesson glossary distinction between + Phase 02d and Phase 05, and Phase 02b G19's stale module count. +- [x] The README refresh and the requested removal of mandatory commit coauthor + attribution (`dde8e0b`) are included in the merged head. +- [x] The final PR-head and merge-commit CI runs both completed successfully. + +| Verified revision | CI evidence | Result | +|---|---|---| +| Final PR head `bc18170` | [Run 34892449509](https://github.com/HodeTech/LearnStack/actions/runs/34892449509) | All five required jobs succeeded | +| `main` merge commit `1d3a0f7` | [Run 34892508893](https://github.com/HodeTech/LearnStack/actions/runs/34892508893) | All five required jobs succeeded | + +The live required-check list still has the five contexts recorded in Step 3, with +GitHub Actions `app_id: 15368` and `strict: true`. The merge run verifies **2,381 +backend tests**: 1,456 unit, 177 architecture, 171 Docker-free integration, +576 Docker integration and one contract, with zero failures or skips. The frontend, +meta and secret-scan jobs also pass. The OpenAPI and Lighthouse placeholders remain +outside the required set, with their existing P02d-4 and P02d-7 decision gates. +Both completed runs were verified at **20:25 UTC**. + +**P02d-1 is closed. Phase 02d remains in progress.** P02d-2 through P02d-7 have not +started. P02d-2 first resolves its writer, customization-contract, locale, branding, +seed-context and data-safety decisions, then implements the commands, audit wiring +and repeatable tenant-specific seed. The packet table and decision register above +own its exact scope and open gate parts. Public reads, rendering and the browser +demo remain the later packets' work; this merge does not complete those surfaces. + +## P02d-2 — Writers and seed + +### Pending Course Marketplace proposal + +**Pending direction review — 2026-09-17.** At the maintainer's request, P02d-2's +decision pass first considers institution sites alongside a +[Course Marketplace](../decisions/0049-institution-sites-and-course-marketplace.md). +ADR-0049 is Proposed; this note accepts no gate and assigns no marketplace delivery +scope to P02d-2. Its +[acceptance checklist](../decisions/0049-institution-sites-and-course-marketplace.md#implementation-notes) +records the unresolved product, delivery and commercial decisions. + +**Review follow-up — 2026-10-01.** The +[scoping companion](../architecture/34-course-marketplace-scoping.md) separates +live-product delivery, operations, privacy, regional topology and commerce recovery +from this packet. Public-only P02d-2 has no technical dependency on those capabilities; +the maintainer's planning hold remains until they resolve or release it. No review +recommendation selects protected authoring or accepts marketplace delivery scope. + +**Historical boundary before exact acceptance.** G3's publication answer was accepted +on 2026-09-14 under ADR-0048; direction endorsement alone did not reopen it. The +maintainer's subsequent exact approval of ADR-0050 supplies the superseding contract +and [dated G3 supersession](#g3-supersession-2026-10-02) below. The original question, +accepted answer and delivery record remain intact. + +**Maintainer endorsement — 2026-10-02.** The maintainer approved following the +recommendations and completing preparation. The hybrid direction and proposed +[Phase 09a](phase-09a-course-marketplace-pilot.md) are planning targets, not accepted +commerce contracts. The preparation hold is released. Protected authoring is prepared +in ADR-0050. The subsequent exact approval is recorded below; it does not accept +marketplace commerce. Future commerce feasibility does not block this packet. + +### P02d-2 decision package (2026-10-02) + +**Accepted — 2026-10-02.** The maintainer approved ADR-0050, ADR-0051 and the exact +packet statements, inventory and four-step plan below, then requested documentation +updates and a wait. Current gate cells and ADR lifecycle/index records are updated; +new source proofs were Registered at acceptance. The original G3 question, +P02d-1 accepted answer and delivery record are preserved. At acceptance, implementation +had not started; the [delivery record](#p02d-2-implementation-delivery-2026-10-02) +tracks the subsequently resumed work. + +#### G3 supersession (2026-10-02) + +ADR-0050 supersedes ADR-0048's public-only implication. Independent `draft → published` +states, one-root publication and no version snapshot remain unchanged. Explicit +Course content policy is inherited by lessons: `public` or `enrollment_required`. +Legacy rows backfill restricted; the migration was planned for P02d-2 and is now +recorded in the Step 1 delivery below. + +This dated entry governs the current P02d-2/4/6 criteria wherever the inherited +packet text below describes publication as sufficient for anonymous body access: + +- P02d-2 requires explicit policy, restricted legacy backfill, six separate Education + commands and exact seed convergence; publication does not grant access. +- P02d-4 admits published marketing fields under either policy but exposes no + restricted lesson inventory, count, descriptor, body or media URL. Direct hidden + lesson lookup remains indistinguishable `not_found`; eligibility precedes public + serialization, caching and conditional responses. +- P02d-5/6 preserve that public DTO boundary and render a bounded locked state with + no invented payment or enrollment action. Credentials never unlock anonymous reads. +- Phases 04/05/07 own protected media, version/policy evolution and grant evaluation; + unsafe live rollback is prohibited under ADR-0050's containment contract. + +The accepted inventory and text-card subset below govern seed and rendering scope +where older packet planning differs. Remaining transport/cache/OpenAPI/renderer +gates stay open for their named packets; acceptance claims no implementation. + +<a id="p02d-2-proposed-answers"></a> + +#### P02d-2 accepted answers + +| Gate part | Accepted answer and detail owner | +|---|---| +| G3: access, commands and seed states | [ADR-0050](../decisions/0050-publication-and-course-content-access.md) separates publication/access, backfills restricted policy and denies protected lesson inventory. Lifecycle stays independent draft → published. [Education writer plan](../modules/education/README.md#p02d-2-accepted-writer-contract) names six commands; seed states are explicit below | +| G5: level validation | New course binding requires the exact Active taxonomy revision and declared band; never resolve a live key. The [Customization contract](../modules/customization/README.md#p02d-2-accepted-exact-write-contract) owns eligible revision rules. Unresolved public labels remain G5's P02d-4/6 decision | +| G7: child derivation | Scope comes from trusted context and authorized parent; missing/cross/sibling parent is `not_found`, visible but unwritable parent scope is `resource_scope_violation`. No request tenant/organization authority; database guards remain unchanged | +| G11: writers, failures and convergence | Separate create, translation-add and publish commands per Education root; translation insertion reports known slug uniqueness as `business_rule_violation`. Tenancy locale and whole-theme commands write one root. The specs own matrices; seed never treats a generic lifecycle failure as success | +| G12: contract | Uncached Customization application interface returns immutable value DTOs for exact revisions; new binds Active, existing-pin writes Active/Deprecated. No foreign Domain/Infrastructure reference, FK, public marker or cache. Snapshot eligibility is at validation read, not a claim of Active-at-commit | +| G13: locale | Uncached Tenancy application contract requires canonical enabled membership. No platform locale registry; use existing LocaleTag grammar/canonicalization/35-character bound. No rows means no content locale, not implicit `en`; label fallback does not change URL/body eligibility. Removal/disable retains Education data and later reads recheck membership; the lifecycle commands belong to Phase 03 | +| G14: seed | Inventory and test-owned controls below; all literal identities and expected counts move into `SeedData` with implementation. Tenant-wide branding/content announce null organization. Built-in `card`/`plain` stay unchanged and Active | +| G15: setter fence | Ownership verification becomes contextual `ISender` queries, explicitly audit Off; no direct seeder transaction/context setter. [Caller fence implemented in Step 4](../standards/21-architecture-tests-catalogue.md#seeder_does_not_call_tenant_context_setters) has a planted-caller companion; no new ADR-0040 setter admission | +| G16(a–e): branding | One tenant-wide `branding.theme` document, four closed color fields, complete replacement and contrast refusal; exact version for replacement. Command-local registry preserves generic settings. Organization overrides refused; no fonts, logo, URL or layout setting in this packet | +| G17: PII | Mark generic `TenantSetting.Value` `[PiiSensitive]` before its writer, including whole JSON audit redaction. Public branding allowlisting is a separate boundary, not permission to expose generic settings | +| G18: presentation | [ADR-0051](../decisions/0051-ordered-text-card-presentation.md) extends ADR-0043 with optional strict root `x-fields`; seed opts into ordered localized plain-string cards. Legacy schemas remain valid, unchanged; no renderer-key or presentation-column change | +| G19: active content | The seeded profile has no active URL/markup sink; output is escaped text, never linkification or Markdown/HTML. ADR-0051 names first-sink owners; generic schema validation is not navigation/media authorization | +| G20: literal source | `SeedData` owns all demo identities, literals and expected inventory. The [Registered literal guard](../standards/21-architecture-tests-catalogue.md#production_code_does_not_branch_on_demo_tenant_literals) consumes that declaration when implemented; production subjects/exemptions and behavioral genericity proof stay with their later packet parts | +| G21: subresources | No new remote asset/font/logo or cross-origin subresource from seed/theme/text cards. Cookie behavior remains P02d-5; public output still needs later transport/render gates | +| G23: freshness bound | No settings cache in P02d-2/3: no seed-process staleness, generation migration or out-of-band loader. P02d-3 owns the ambient typed accessor and scoped merge; latency is a later measurement, not a passed budget | + +G18/G19's selected vehicles are accepted ADR-0051 and append-only ADR-0043 +Amendment 5. The original register's Leaning/Vehicle text remains review history; +this acceptance records the selected vehicle explicitly. Existing ADR decisions +are preserved; ADR-0048's Status and dated supersession are lifecycle bookkeeping. + +#### Seed inventory and ownership + +Step 4 delivers this inventory; both review rounds and final verification passed. +Exact IDs, schema/body literals, slugs, labels, palettes and computed counts live +in `SeedData`; no +production branch knows `demo-english`, `demo-yoga`, `grammar-topic` or `asana-pose`. +The existing fixed tenant, organization, host and built-in customization IDs stay. + +| Data | English tenant | Yoga tenant | +|---|---|---| +| Host context | Existing tenant host, organization null | Existing Studio One host | +| Locales | `en`, enabled default | `tr-TR`, enabled default; `en`, enabled | +| Tenant content type | `grammar-topic`, revision 1 Active, `default-card`; plain-string `concept`/`example` | `asana-pose`, revision 1 Active, `default-card`; plain-string `pose`/`instruction`/`breathing` | +| Taxonomy | `cefr`, revision 1 Active; six declared bands | `yoga-difficulty`, revision 1 Active; three declared bands | +| Branding | One tenant-wide `branding.theme`, complete valid palette | One tenant-wide `branding.theme`, distinct complete valid palette | +| Courses | Four: tenant-wide published public, tenant-wide draft public, tenant-wide published restricted, Kadıköy-scoped published public | Four: tenant-wide published public, Studio One published public, Studio Two published public, Studio One published restricted | +| Lessons | Five: two under public tenant-wide course (published/draft), one published under draft parent, one published under restricted parent, one published Kadıköy-scoped | Five: one tenant-wide, two Studio One public, one Studio Two, one Studio One restricted; published | +| Translations | One `en` translation per course/lesson | Both `tr-TR` and `en` per course/lesson; genuinely different translated slugs/labels | +| Cross-tenant positive control | Published public tenant-wide course uses `en` slug `foundation` | Published public Studio One course also uses `en` slug `foundation`; no uniqueness across tenants | + +All eight courses and ten lessons have explicit pins and access/state choices; +lesson policy is inherited. The declared translations total 27: nine English and +18 Yoga. No remote media is seeded. Wrong-course proof uses the two visible Yoga +courses; organization controls are hidden/visible against the appropriate host. + +Pagination uses **test-owned** courses and a test-selected bounded page size in +P02d-4, not arbitrary mass demo data or a premature G10 default. A retained +disabled-locale translation is also a P02d-4 historical-state fixture, with an +explicit test setup; `make seed` does not bypass locale admission to fabricate it. +Schema mismatch, absent presentation, missing labels and unresolved pins are negative +test fixtures rather than invalid demo rows. Packet 7's raw `tz`/organization `theme` +fixtures remain legal and are counted separately from the new seed theme. + +Every act derives a fresh composed trusted seed scope, with nullable organization. +Tenant locales, customization definitions, branding and tenant-wide courses run in +tenant-wide context; organization courses/lessons run in their exact organization. +Translations and publication use the root's write scope. No admin role, superuser, +RLS bypass, direct EF mutation or ad hoc seed SQL supplies normal writes. + +Seed order is provisioning/organizations/hosts, enabled locales, built-ins and tenant +types/taxonomies (create then publish), branding, course/lesson drafts and translations, +then each selected root's publication. Translation precedes publication on a new root. +Restricted controls depend on accepted ADR-0050 and its applied migration. + +Before skipping an existing act, the ownership query verifies exact ID, parent, scope, +pins, enabled locale, translated slug/text, semantic JSON, policy and state as relevant. +Absent acts are written; exact completed acts are skipped without mutation/audit. +Creation verification accepts only the declared draft intermediate state or intended +final publication state, with identical immutable data; later acts still verify all +translations and final state. It does not demand draft on a completed published root +or accept arbitrary states. This rule also covers customization create/publish acts. +A typed uniqueness, concurrency or lifecycle race triggers one fresh-scope ownership +check against that act's completed postcondition, never blind retry or +matching by display name. Mismatch fails nonzero without editing, unpublishing, +rebinding or selecting another revision. Existing published translations are checked +and skipped before calling the draft-only translation command. A published mismatch +is not accepted merely because that command returns `translation_requires_draft`. +If a competing runner has not completed the exact postcondition, fail safely for a +later explicit rerun rather than returning false success or spinning indefinitely. +Interrupted partial seeds converge; a second completed run adds no roots or audit rows. + +#### Implementation steps and review loop + +All steps run on **development**. No branch switch, push or PR is part of preparation. +Each implementation step follows the maintainer's requested loop: implement and +commit; first fresh independent multidisciplinary review; verify/fix valid findings +and commit; second fresh review agents; verify/fix and commit; continue automatically. +Agent models/effort follow complexity and available models. Unverified findings are +rejected with evidence; an unresolved material defect blocks that step's completion. + +| Step | Coherent change | Required evidence before step completion | +|---|---|---| +| 1 — policy and contract foundation | Education access value/configuration and additive migration; exact Customization/Tenancy read DTO contracts; ADR-0051 profile parser/resolver; module-scoped seed verification queries | Domain/profile positive and negative cases, exact revision and locale isolation, policy/default/legacy preservation, migration forward/down/reapply and pending-model check; unsupported schemas remain valid but not implicitly renderable | +| 2 — Tenancy writers | Locale commands and pre-mutation guards; default-enabled CHECK migration; whole-theme registry/command, contrast and concurrency; PII capture; matrices/composition | Disabled-first→enabled-second, disabled promotion leaves root/audit unchanged, invalid legacy refusal, injected second-save rollback, scoped writes, palette and concurrent replacement/create conflicts, whole-value audit redaction | +| 3 — Education writers | Six separate commands, validation against exact schema/taxonomy and enabled locale, parent scope, named-constraint failures, audit and ambient transaction | Body/pin/locale/slug failures, one-root lifecycle, publication audit atomicity, RLS mirrors, uniqueness races, stale versions, and swallowed nested failures cannot later flush dirty state | +| 4 — convergent seed and packet closeout | Contextual verification replaces direct setter; complete SeedData acts; source guard and planted companion; seed tests and Packet 7 counts recomputed; documents match delivery | Fresh seed, second-run no-change, interrupted recovery, concurrent seed convergence, mismatches fail nonzero without writes, host/scope positive controls, no caller-fence escape, full required verification and two review rounds | + +Checks scale to each step's change. Final closeout runs Release build/format and all +required unit, architecture, contract, Docker-free and Docker integration suites with +zero skips; applicable EF chains' pending-model/forward/rollback/reapply checks; +seed convergence; Markdown links/anchors and `git diff --check`. Record actual commands, +counts and results in the delivery record, not a speculative passing total here. + +#### Approval boundary and readiness + +**Preparation verification — 2026-10-02.** The reviewed documentation commit is +`7bc8e63`, against `6bbcb1e`; no implementation is included. First-round security +and governance findings were verified and fixed: post-build extension resolution, +explicit lesson seed states, no platform locale registry and endorsed participation +wording. Two fresh second-round agents independently returned Approve, with no +remaining actionable findings. Reviews used `gpt-6-astra` (high) for security and +`gpt-6.1-sol` (xhigh) for governance/seed/corpus consistency. + +- Architecture: 177 passed, zero failures/skips, Release `--no-build --no-restore`; + the TRX execution-count check passed. This verifies existing guards, not future + policy migrations, writers or public readers. +- Documentation: 33 Markdown files, 1,715 local references and 444 fragments checked; + added prose wrapping and `git diff --check` passed. External provider/legal evidence + was not reassessed in this preparation pass. +- Accepted ADRs were unchanged. The entire P02d-1 decision/delivery suffix was + compared byte-for-byte with the baseline and is unchanged. +- Commit hooks, including staged Leakwatch and commit-message validation, passed. + Work remains on development; no push or PR was performed. + +**Exact acceptance and wait — 2026-10-02.** The maintainer approved ADR-0050/0051 +and this package, with the explicit instruction to complete documentation and wait. +Lifecycle, dated G3 supersession, current gate statuses, corpus references and new +Registered source-proof rows are updated. P02d-2's decision pass is complete and +the document is ready for Step 1 when implementation is resumed. No code, migration, +handler or new seed data has been delivered; the packet is not marked complete. + +The marketplace's company/country, provider, selected region, legal roles, seller +corridors and detailed Phase 09a contracts remain its own first-consumer gates. +ADR-0049 and Phase 09a remain Proposed. They neither expand P02d-2 nor hold its +independent protected-content work. No implementation, push or PR follows this update. + +**Acceptance verification — 2026-10-02.** Two independent reviewers returned Approve +after verified bookkeeping findings were fixed: `gpt-6.1-sol` (xhigh) for governance +and `gpt-6-astra` (high) for security/corpus consistency. Both checked the final scope, +partial gate closure and absence of implementation claims. + +- Existing Release architecture suite: 177 passed, zero failures/skips; the TRX + execution-count guard passed. Future Registered proofs are not included in that count. +- Documentation: 33 changed Markdown files, 2,117 local links and 486 fragments checked; + added prose wrapping and `git diff --check` passed. +- ADR-0043's pre-existing text and ADR-0048's original decision body are unchanged; + additions are dated lifecycle/extension disclosures. The complete P02d-1 suffix + remains byte-for-byte unchanged against `3f849d1`. +- The two new catalogue rows remain Registered; all 144 Implemented entries are + unchanged. No backend/frontend implementation or deployment operation is included. + + +### P02d-2 implementation delivery (2026-10-02) + +The maintainer resumed implementation after exact approval. The earlier acceptance +and wait record remains historical; work now follows the four accepted steps on +**development**. No public endpoint, marketplace commerce or authorization grant +is introduced by P02d-2. + +**Step 1 — policy and contract foundation, complete.** Course creation takes +an explicit closed policy. The additive Education migration defaults/backfills +`enrollment_required`, preserving existing content and scope; technical Down is +proved only in a disposable database, not approved as a live public-reader rollback. +Exact revision/locale ports, ordered text-card semantic resolution and contextual +seed verification queries are registered in both composition roots. Read queries +are Off; no seed context-setter change or writer completion is claimed yet. + +**Step 1 pre-review verification.** Release build completed with zero warnings/errors. +Docker-free tests: 1,489 unit, 177 architecture, 171 integration and one contract, +all passing with zero skips. Fifteen focused Docker integration cases passed, +including both composition roots, exact revision/locale reads, Education persistence +and migration forward/down/reapply. Full format verification and the TRX execution +count/zero-skip checks passed. Markdown validation checked 2,137 local references +and 487 fragments across 34 files against the preparation baseline; P02d-1's frozen +record and all Accepted ADR bodies remain unchanged. `git diff --check` passed. + +**Step 1 review round 1.** The policy/contract implementation is `682f858`. Two +independent agents found no production defect. Verified gaps in positive/sibling/foreign +setting proofs and disabled/foreign locale proofs were corrected independently of +invalid-default configuration checks. All five strengthened foundation tests pass, +including a disposable predecessor-schema proof for a disabled legacy default. +Current README, glossary and module/standard +status statements were aligned with the delivered foundation. A broader Docker +regression run passed all 228 cases, with zero skips. Fixes are `a8a51ce`. + +**Step 1 review round 2.** Fresh agents independently returned Approve for +`45805c8..a8a51ce`, with no actionable findings. Security review used `gpt-6-astra` +(high); profile/corpus review used `gpt-6.1-sol` (xhigh). Independent runs passed 116 +profile/registration unit cases, six foundation/migration Docker cases and all 177 +architecture cases, with zero skips. Links/anchors and the frozen P02d-1 suffix passed. +Step 1 is complete after both requested rounds. + +**Step 2 — Tenancy writers, complete after both review rounds.** +Three unrouted tenant-wide commands implement locale addition/default selection and +complete branding creation/exact replacement. Existing locale configurations are +validated before mutation; the first enabled locale is promoted even after disabled +rows. Two-pass default saving also handles newly Added defaults. The additive CHECK +refuses disabled defaults and never repairs legacy data automatically. Generic setting +JSON is wholly redacted at capture. Palette fields and CSS mappings share a closed +registry, with per-pair contrast admission and no entitlement gate. Failed saves after +mutation mark the ambient unit rollback-only. Steps 3–4 remain pending. + +**Step 2 pre-review verification.** Release build passed with zero warnings/errors. +Docker-free tests passed: 1,538 unit, 177 architecture, 171 integration and one +contract. The expanded Docker regression group passed all 75 cases, including +composition, locale/default and branding writers, whole-value audit redaction, +concurrent creates/replacements, MUST audit failure, injected second-save rollback, +invalid legacy refusal and migration forward/down/reapply. Execution-count checks +confirmed zero skips. The broader group also exposed a test-isolation defect in +Step 1's writing foundation case: its independent audit rows survived the business +rollback in the shared fixture. That case now owns a disposable database; the full +75-case group passes without leaking rows into other tests. + +**Step 2 review round 1.** Security (`gpt-6-astra`, high) found one verified +classification defect: the shared EF helper wrapped unknown unique constraints with +a business error before the handler could distinguish them. New Tenancy writer +methods now supply owned constraint sets; unowned failures stay database faults. +Two planted PostgreSQL constraints prove `500 internal_error`, unchanged state and +no successful audit. Existing helper callers retain their contract. The corpus/theme +review (`gpt-6.1-sol`, xhigh) found two Minor documentation gaps; prose wrapping and +public contract XML documentation are corrected. Palette key-order and exact/over-cap +input proofs also cover its optional test suggestion. After fixes, Release build +passed with zero warnings/errors; 77 Docker regression cases, 185 focused unit and +177 architecture cases passed with zero skips. The implementation is `1b98352`; +first-round fixes are `63ed4bc`. + +**Step 2 review round 2.** Fresh security (`gpt-6-astra`, high) and corpus/theme +(`gpt-6.1-sol`, xhigh) agents independently returned Approve for +`a8a51ce..63ed4bc`. Each independently passed 160 focused unit and 12 PostgreSQL +writer/migration cases, with zero failures/skips. The one verified Minor was a stale +Tenancy component description; its root/writer claim, command/store inventory and +table count now match code. Links/anchors, wrapping and the frozen P02d-1 record pass. +Step 2 is complete; Steps 3–4 remain pending. + +**Step 3 — Education writers, complete with both review rounds.** +Six separate commands write one Course or Lesson and its contained translations. +New binds resolve exact Active revisions; existing lesson pins remain eligible after +deprecation. Enabled locale admission and schema evaluation precede mutation. Visible +but incompatible write scope is refused; hidden roots remain indistinguishable misses. +Translation insertion reserves its tenant-local slug; diagnostics identify only visible +conflicts. Publication remains independent and MUST-audited. Known post-save failures +poison the ambient unit, including when an outer handler absorbs the refusal. +No public endpoint, protected reader or seed execution is claimed by this step. + +**Step 3 pre-review verification.** Release build passed with zero warnings/errors. +The full Docker-free run passed 1,557 unit, 177 architecture, 171 integration and +one contract case, without failures/skips. The focused database regression run +passed 249 cases, including all 14 Education writer cases, the existing Education +isolation suite, Tenancy writers and migration reversal. Both known post-save +refusal variants were absorbed by an outer handler that saved another root; the +owning transaction still refused commit and rolled back both writes. Concurrent +publication and localized-slug insertion produced one durable winner. Unknown +unique constraints retained `internal_error`; hidden collisions disclosed no root +identity. Full format verification, Markdown links/anchors and `git diff --check` +passed. This step changes no EF model or migration. Two fresh review rounds follow. + +**Step 3 Round 1.** Fresh GPT-6 Astra (high) security/transaction and Claude Sonnet 5 +(high) contract/validation/corpus reviews both returned Approve. The security reviewer +independently reran all 14 Education writer database cases. Two verified Minor test +findings were fixed: validator tests now resolve the registered internal validators +through DI, and organization-scoped translation/publication attempts against a visible +tenant-wide Lesson explicitly assert refusal and unchanged state. The optional +unreachable policy-switch suggestion is not a defect: the composed validator admits +exactly the two explicit values, and the domain guards its closed enum. No production +change was justified. Round 2 uses new review sessions after the fixes. +Release build, all 16 validator cases and all 14 writer database cases passed again, +without failures/skips. Full format verification exited zero; links/anchors and the +unchanged P02d-1 suffix check passed. + +**Step 3 Round 2.** Two fresh read-only Codex review sessions (high and xhigh) +reviewed `8b981c7..a4a29d3`. The security reviewer returned Approve; the contract +reviewer requested changes. All findings were verified against current code. +Internal parent and collision ports now retain module-local typed IDs; conversion +occurs at the command boundary and unwraps only for exported diagnostics. The +aggregate-write census excludes typed keys without exempting the reader by name; +its planted companion still detects direct, nested generic, array, by-ref and mixed +object writes. The existing 1 MiB instance cap now has one shared owner, and the +Education validator checks UTF-8 size before any JSON parse. Inclusive ASCII and +multibyte boundary tests and a composed writer refusal/unchanged-state proof cover +it. New null suppression is removed or justified by the exception filter. README, +Database Standard and the old Backend Coding publication example now name the +shipped writer contract. Additional focused review follows these production fixes. +The attempted fresh Claude sessions reached the provider's session limit and +produced no review; they are not counted as completed rounds. + +**Step 3 fix verification and closeout.** Fresh xhigh read-only review of +`a4a29d3..2e498ce` returned Approve with no blocking findings. Its two low-priority +suggestions were verified and applied: the oversize proof now counts every audit +outcome, and a stale XML description no longer attaches the old size limit to +`BuildOptions`. The fixed census passes all 178 architecture cases; its planted +controls also cover inherited interface signatures. Release build has zero +warnings/errors, 1,559 unit cases and the contract case pass, and all 780 integration +cases pass, including 15 Education writers. No failures/skips remain; format, +local links/anchors and the frozen P02d-1 suffix check pass. Step 3 is complete; +Step 4 follows below. + +**Step 4 — convergent seed, complete after both review rounds.** +The fixed identities remain unchanged. SeedData owns every declaration and expected +count: two tenants, four organizations, two hosts, three locales, four content types, +four taxonomies with fifteen bands, two distinct whole themes, eight courses, ten +lessons and twenty-seven translations. Published/draft and public/restricted cases +include tenant-wide and both organization scopes. English and Yoga have their own +schemas, labels and bodies; Yoga has complete tr-TR/en translations. No remote media, +marketplace fields or P02d-4-only historical/negative fixtures are introduced. + +Every verification and write goes through contextual ISender requests. Completed acts +skip before a writer, partial declared acts resume, and a typed race gets exactly one +fresh postcondition read. Mismatches fail without overwrite; no private transaction, +setter or direct persistence path remains. Internal reader ports retain typed IDs. +The caller-fence guard and planted companion are Implemented; G20(a) reads all literal +sources from SeedData, while the full production branch guard remains P02d-7's owner. +The seed skill, host/isolation projections, catalogue and current-state documents +now match implementation. Tests own disposable databases rather than shared cleanup. + +**Step 4 verified consumer defects.** Concurrent seed execution exposed a real +Customization publication race: a competing publish between two READ COMMITTED reads +caused EF to return the already-tracked Draft as its own Active incumbent. Both +handlers now return typed concurrency before mutation. A failed publication save now +marks rollback-only even without an incumbent, so an absorbing outer request cannot +flush dirty publication state later. Six controlled database cases cover both roots, +the precise race and post-save conflict/concurrency absorption. An old unit expectation +that assumed no retirement meant no dirty state was corrected against these proofs. +No new ADR or schema decision is introduced. + +**Step 4 pre-review verification.** The 49 focused database cases pass without +failures/skips: thirty-five Seeder, eight host/isolation and six Customization race +cases. These include full inventory/scopes, all-outcome audit neutrality on repeat, +two real interruption points, coordinated concurrent seed, seventeen mismatch cases, +semantic JSON equivalence and the executable's actual zero/nonzero exit behavior. +A fresh complete seed produces ninety successful audit rows; provisioning writes two +aggregate audit rows, and all counts derive from SeedData. Full verification and +both fresh review rounds were still required at this pre-review stage. + +**Step 4 broader regression corrections.** The complete Docker run exposed two +inherited audit groups tied to the old seed: fixed counts and direct repeat writers +had been inferred from a runner that now skips completed acts, and shared cleanup +could not remove the new restricted dependencies. AuditPipelineTests and +AuditWorkflowTests now own disposable databases and focus their declaration on +provisioning/built-ins. Rollback audit proof sends explicit refused commands and +retains the two provisioning intents plus the standalone organization refusal. +All eighteen cases pass; the expanded 67-case seed/host/Customization/audit group +passes without failures/skips. Complete Docker regression then passed 638 cases. + +The two seeded schemas now differ in property count, as the inherited phase criterion +requires: Yoga also declares ordered, bilingual plain-string breathing text. The +inventory proof checks actual persisted schema shape, beyond changed names/labels. +A verified publication mismatch could otherwise retire a different Active revision +under the same key. Seed sets both publish commands' optional `RequireNoIncumbent` +precondition, which refuses before mutation and retains ordinary succession by default. +Two additional seed cases prove unchanged definitions/versions/generations and no +successful audit on that refusal; normal failed-command audit remains legitimate. +The two new cases and six controlled race/rollback cases pass. Release build has +zero warnings/errors; all Docker-free suites pass again. At that stage, fresh review +closure and final complete verification remained pending. + +**Step 4 Round 1.** Fresh read-only Codex xhigh security review requested changes; +Claude Sonnet 5 high contract/corpus review returned Approve with one cosmetic Minor. +The security finding is verified: publishing the declared revision could retire an +incompatible Active revision. Contextual Off queries now check the logical key's +Active identity before registration, and publication checks `RequireNoIncumbent` +inside its transaction before retirement. Four pre-existing absent/Draft cases and +two coordinated different-revision winners accompany the same-ID race proofs; +failed seeds preserve existing content, versions, generations and audit successes. +The cosmetic extra blank line is removed. The earlier 67-case regression corrections +and schema-shape proof are included in this fix set; a fresh second round follows. + +**Step 4 Round 2 and packet closeout.** Two fresh read-only Codex review sessions +(high for contracts/corpus; xhigh for security/transactions) reviewed +`951acd2..fecdc76` and independently returned Approve. No Blocker or Major remained. +Both found the stale README bootstrap statement; the contract review also found the +old Step 4 review heading. Both verified Minor findings are fixed, and current-state +carriers and the seed skill now name completion. No additional production change was +required. The implementation is `5081724`, with first-round fixes at `fecdc76`. + +**Final verification — 2026-10-02.** All required local checks pass: + +- Release build: `dotnet build backend/LearnStack.slnx --no-restore -c Release`, zero + warnings/errors. Full format verification uses `dotnet format` with + `--no-restore --verify-no-changes` and exits zero. +- Backend: Release `dotnet test --no-build --no-restore` with separate + `Requires!=Docker` and `Requires=Docker` runs; 1,559 unit, 181 architecture, + one contract, 171 Docker-free integration and 644 Docker integration cases pass. + Total: **2,556**, zero failures/skips. TRX counters were inspected for failures; + `scripts/assert-tests-ran.py` also proves execution and zero skips per assembly. +- The focused seed/host/Customization/audit group passes all 73 cases: 39 Seeder, + eight host/isolation, eight controlled publication and eighteen audit cases. + Actual CLI exits, interrupted/concurrent recovery, exact repeat neutrality, + incompatible Active winners and transaction absorption are covered. +- All five EF chains report no pending model changes using the pinned tool in + `backend/`, Release `--no-build` and a design-time-only placeholder connection. + The complete Docker run includes every-chain forward/down/reapply, populated + access-policy preservation and disabled-default migration refusal. This is + disposable-database reversal evidence, not approval to remove live access policy. +- Frontend: frozen install, typecheck, lint, build and all thirteen Vitest cases pass. + Four default/gated dev/e2e compose combinations and actionlint pass. These surfaces + did not change after verification; no browser-rendered demo is claimed. +- The PR documentation sweep checks 45 Markdown files, 2,868 local links and 571 + fragments. Added prose wrapping and `git diff --check` pass. Analysis-directory + hits are the existing prohibition/history wording, not links to scratch material. + The complete P02d-1 suffix is byte-identical to the acceptance baseline. Accepted + ADR bodies have no implementation-time edits. +- Commit hooks pass, including staged Leakwatch, formatter and strict message checks. + The pre-closeout PR range's seventeen non-merge commits pass the same strict hook. + Final closeout is checked with the resulting PR range before publication. + +**Disposition.** P02d-2 implementation, both review rounds per step and required +verification are complete on development. PR review and merge remain the maintainer's +next step. Phase 02d remains in progress. P02d-3 owns generation-keyed customization +read internals and the uncached ambient typed settings accessor; its remaining gates +open before that work. P02d-4 owns public reads and hidden-response/query-plan proofs; +P02d-5–7 own transport, rendering and the running two-site demo. No marketplace, +authentication, enrollment, public API or browser-delivery completion is inferred. + +#### PR review corrections (2026-10-02) + +External PR #23 findings were verified against `6fce655` before changes. Current +carriers now separate delivered P02d-2 policy, migration, writers, presentation +resolution and seed from P02d-4 public reads, P02d-6 rendering and Phase 07 grants. +ADR-0050/0051 retain their acceptance-time Status and Decision text; dated +implementation disclosures and Amendment 1 record delivery. The indexes, glossary, audit +review state, implemented setter fence, contrast refusal and unrestricted default +entitlement provider are aligned. No access, branding, marketplace or governance +decision changes. + +The exact presentation reader now returns `/properties` validation failures for missing +or non-object members and non-object roots. Eleven regressions preserve its Result +contract and optional legacy profile behavior. Migration reversal locates the policy +migration by stable ID; both Up applications prove the restricted backfill. Lesson and +Course post-save refusal absorption, both Customization MUST-audit replacement rollbacks +and the incumbent rollback-only branch have direct proofs. A controlled non-provisioning +translation race witnesses two real save attempts, one successful act and one audited +refusal, fresh completed-state recovery and an unchanged all-outcome repeat snapshot. + +Theme replacement-version requirements do not apply to create-only seed writes. +Reference admission remains with the authoritative exact-revision writers; no new +whole-declaration preflight contract is introduced. Existing inventory comparisons +already prove both tenants' shared English slug and foreign-tenant invisibility. +Existing repeat snapshots include every audit outcome; the new race additionally retains +an observed failed audit. These findings require no production expansion. + +Release build has zero warnings/errors; 1,570 unit, 181 architecture, 171 Docker-free +integration, one contract and all 69 affected database cases pass with zero skips. +Relative links, fragments, added prose wrapping, format and `git diff --check` pass; the +P02d-1 suffix remains byte-identical. + +**Independent review round 1.** The correction commit is `40d207d`. A fresh Codex +reviewer at xhigh effort traced parser callers, migration targeting, rollback and seed +race evidence; a fresh Sonnet 5 reviewer at high effort checked corpus/governance and +source claims. Both returned Approve with no material findings. A separately detected +89-column prose line is wrapped without changing its meaning. + +**Complete backend verification.** After the corrections, all 2,573 cases pass: 1,570 +unit, 181 architecture, one contract, 171 Docker-free integration and 650 Docker +integration. TRX counters show zero failures/errors/skips; the execution guard passes +for every assembly. All 69 affected database cases pass within the full run. Release +build has zero warnings/errors, and full format verification exits zero. The PR +documentation sweep checks 45 Markdown files, 2,892 local links and 577 fragments. No +frontend or operational surface changed in this correction. The second independent round +and its correction are recorded below. + +**Independent review round 2.** Fresh Codex (xhigh) and Sonnet 5 (high) sessions +reviewed `6fce655..a436a51`. Sonnet approved the corpus. Codex found one valid proof +gap: identical translation contenders did not falsify removal of the loser's required +post-race recheck. All other code/security, rollback, migration and documentation +boundaries were clean. + +The test now covers identical and divergent payloads for the same course/locale. A +conflicting loser must refuse its exact state before reporting the act completed; the +independent later final-state check cannot supply this proof. A controlled mutant that +skipped only the losing-race recheck passed the identical case and failed the divergent +case at the completion assertion. `SeedRunner.cs` was restored byte-for-byte; no +production seed behavior changes. Both positive variants and the complete backend suite +then passed. The standards index's current-state date now matches the delivered +2026-10-02 table. + +**Targeted follow-up review.** A fresh Codex session at high effort reviewed +`a436a51..163eb90` and returned Approve: the completion assertion kills the missing +recheck mutant, winner selection is arrival-order independent, real save/audit witnesses +and cleanup remain intact, and the revised documentation counts agree. The correction +and both independent review rounds are complete; the only verified second-round finding +is fixed and independently rechecked. Final hooks, wrapping, links/fragments and the +frozen-record check pass. PR #23 carries the updated range and validation; merge remains +the maintainer's decision. + +#### Additional PR review corrections (2026-10-02) + +The subsequent review was verified against `eaa72aa`; findings and suggested edits +were treated as evidence, not instructions. No decision, public route or migration +changes were needed. The following corrections retain the accepted packet scope: + +- The tenant write lookup excludes soft-deleted roots, preserving both navigations, + identity matching and cancellation. A real application-role test proves retained + locales/flags on a live root and refusal of locale writes after deletion. +- The aggregate census shares its production predicate with planted fused-port, + two-port, notification, non-public-constructor and negative controls. Key-only + writes remain visible; read exemptions enumerate methods rather than all typed IDs. + Four controlled mutants (first construction only, omitted notifications, blanket + key exclusion and public-only constructors) each fail the intended companion. + The source is restored byte-for-byte before positive verification. +- Both runtime hosts build application pools through the shared role guard. Direct + seed execution now refuses owner/bypass credentials and transitive bypass access; + malformed credential exceptions carry no raw inner parse exception. Unit canaries + inspect full exception text; real direct/transitive refusal runs through both callers. +- The exact presentation resolver converts invalid JSON syntax into a root-located + validation failure. The seed fence also checks IL for direct EF mutation and ad hoc + commands, while admitting immutable data construction and request dispatch. +- Additional proofs cover foreign-context Education writes, locale tenant isolation + and concurrent exact-version changes, identifier-conflict details, renderer-registry + non-emptiness, CHECK removal on Down and refusal of an undeclared persisted locale. +- Current documentation records accepted/delivered branding and writers, the exact + current/planned route boundary, the Tenant locale audit subject and accepted anchors. + ADR-0050/0051 show their dated disclosure inside `#status` and preserve the original + acceptance text under Amendment 2. The catalogue records delivered presentation + proofs separately from Registered public projection/rendering obligations. + +**Verified dispositions.** No remaining item is silently assigned to a later packet: + +| Finding | Disposition and reason | +|---|---| +| Inline tenant lookup / ADR-0049 / permissions | Fixed against the current store, delivery record and Phase 02c route contract. | +| M1 | Fixed; the same production census now has permanent planted controls and four failing mutants. | +| m2–m4 | Fixed: current-state references, JSON syntax refusal and the shared seed/runtime role guard. | +| m5 | Documented per-act durability: a competing Active revision may appear after a registration pre-read, leaving a committed Draft/generation/audit before refusal. Explicit reconciliation is required; seed never rolls back completed acts. | +| m6 | Added the narrow requested proofs, retaining real application-role transactions. | +| m7 | Skipped: ADR-0051 requires existing localized messages plus offending JSON Pointers, which the resolver already supplies; distinct cause keys are not required. | +| m8 | No missing registration found. Both roots are exercised by composed writer/publication tests; a separate parity scanner is optional protection, not a current correction. | +| m9 | Skipped: ADR-0050 explicitly permits disposable Down/reapply and denies live rollback authorization; the forward-only operational rule already applies. | +| m10 | Fixed: the existing seed caller fence now includes direct persistence writes, with positive and negative planted controls. | +| m11 | Refuted: every existing locale must match a declaration under `SeedVerification.Tenant`; the new persisted-extra-locale test proves refusal without a write. | +| m12–m14 | Fixed: audit subject, unused proposed anchor aliases and Status navigation with dated historical disclosure. | +| s1–s5 | No defect: supported calls validate the closed policy; repeated subject designation is sanctioned; titles/summaries map to unbounded text; no unchanged-version promise exists for default-setting commands; parent reads already use `AsNoTracking`. | +| s6 | Skipped: an admitted named race still requires exact fresh-scope postconditions, already mutation-proved; it never accepts a refusal alone. | +| s7–s8 | Ambient is the sanctioned trusted origin. Exit codes are documented; malformed credential failure text is now proven secret-free. | +| s9 | No current public oracle: explicit-ID writers are unrouted trusted operations and replacement lookup hides foreign roots. Phase 03 owns authoring authorization before reachability. | +| s10–s11 | No supported incumbent-deprecation uniqueness collision or registered authoring route found. Unexpected faults already poison the transaction; anonymous admission remains fenced. | +| s12 | Fixed: delivered profile/exact-order evidence and future renderer/sink obligations are catalogued separately. | +| s13–s15 | No current defect: no production lock incident/online-migration mandate; seed DTOs are private verification contracts; raw foundation inserts intentionally model isolated/legacy fixture states, not provisioning. | +| s16 | Historical counts are retained. Supplemental link counts count occurrences outside fenced blocks across PR-changed Markdown and linked ADR/phase carriers; CI's changed-target audit has a different scope and excludes fragments. | +| Legacy profile boundary | Compatibility applies to schemas without root `x-fields`. Its presence explicitly opts into ADR-0051's profile; a formerly inert annotation at that location is now semantic. | +| PR-external follow-ups | Unchanged scripts and legacy conflict helpers are outside this correction. G20's remaining branch fence stays P02d-7; public reads/rendering/grants retain their existing named owners. | + +The shared [seed workflow](../../.claude/skills/seed-tenant/SKILL.md) records direct +role enforcement, failure codes and the committed-Draft race boundary. + +**Positive verification.** Release build has zero warnings/errors. All 2,590 backend +cases pass: 1,577 unit, 184 architecture, one contract, 171 Docker-free integration +and 657 Docker integration. TRX counters show zero failures/errors/skips, and the +execution guard passes for every assembly. Full format verification exits zero. +Eight controlled mutants fail the intended guard; both source files are restored +byte-for-byte and the positive structural suite is re-run before commit. +The supplemental documentation sweep checks 45 Markdown files, 2,901 local link +occurrences and 580 fragments; `git diff --check` passes and the frozen P02d-1 +suffix remains byte-identical. Independent reviews follow the correction commit. + +**Independent correction review — round 1.** Fresh GPT-6.1-sol (`xhigh`) +reviewed the backend/security/proof boundary at `05682d8`; fresh GPT-5.5 (`high`) +reviewed documentation/governance. Neither found a correctness or isolation defect. +The code reviewer found one unused API redaction helper left by extraction; it is +removed, leaving the shared implementation as the only caller-backed helper. The +parent also corrected one added catalogue prose line exceeding 88 columns. +Release build remains warning/error-free; credential guard tests pass 20/20, +architecture passes 184/184 and scoped format verification exits zero. Links and +the frozen suffix remain unchanged. Fresh round 2 reviews the complete correction +range after this fix commit. + +**Independent correction review — round 2 and closeout.** Two new GPT-5.5 +sessions (`xhigh` for backend/security/proofs, `high` for documentation/governance) +review the full `eaa72aa..15123ca` correction range and both approve without an +open actionable finding. They independently inspect the positive TRX, mutation +and restoration evidence; the documentation reviewer also verifies the unchanged +1,799-line frozen suffix. The reviewed production code is complete. This closeout +adds only the review record; the PR remains open for maintainer review and merge. + +#### Branding tenant-existence correction (2026-10-02) + +The outside-diff finding is verified against `3a4bb5d`. Branding now refuses a +missing or soft-deleted announced tenant with the existing `not_found` result, +after scope validation and before any setting lookup or write. A scalar, uncached +Tenancy reader is registered in both runtime composition roots; the handler still +holds one aggregate write capability. Live Trial tenants remain supported. + +Four application-role regression cases cover missing/deleted tenants and +create/replace intent. A throwing setting store proves refusal precedes any +setting access; fresh reads prove unchanged values/versions and no additional +successful setting audit. The existing seeder-root deletion proof also covers both +branding writes. Unit scope guards prove no existence read before scope admission. + +Release build has zero warnings/errors. Final suite runs pass all 2,594 backend +cases: 1,577 unit, 184 architecture, one contract, 171 Docker-free integration and +661 Docker integration. TRX counters and execution guards report no failures, +errors or skips. Full format, local links/fragments and the frozen P02d-1 record +check pass. Two fresh independent review rounds follow the correction commit. + +**Independent reviews and closeout.** Two fresh GPT-5.5 (`high`) read-only +sessions review the exact `3a4bb5d..50518e7` correction range independently. Both +approve without an actionable Blocker, Major or Minor finding. They verify scope +ordering, live Trial support, both DI registrations, refusal before setting access +and the positive build/TRX evidence. No further production change is required; +this documentation-only closeout records the completed rounds. PR #23 remains +open for maintainer review and merge. + +### P02d-2 merge and closeout (2026-10-02) + +[PR #23](https://github.com/HodeTech/LearnStack/pull/23) merged into `main` at +**11:41:47 UTC**, with final PR head `161314313eeb0d87758fb38c20af5e4c4c1b5766` +and merge commit `8edbb032b81313aae7e635b2782af511a9fe02cc`. Their trees are +identical. `development` was fast-forwarded to the merge commit without switching +branches or rewriting history. This closeout changes documentation only. + +- [x] Accepted P02d-2 gate parts and all four implementation steps are complete; + each step and the subsequent verified PR corrections completed both review rounds. +- [x] ADR-0050's policy, restricted backfill and Education writers are delivered; + ADR-0051's profile parsing and resolution are delivered. Public-read enforcement + remains P02d-4, rendering P02d-6 and course access grants Phase 07. +- [x] Three Tenancy and six Education writers, exact-definition/locale validation + and convergent two-tenant seed execution are delivered and registered. +- [x] The final tenant-existence correction refuses both branding write intents + before setting access; live Trial tenants remain supported. +- [x] The final PR head passed all five required checks; CodeRabbit also succeeded. +- [x] The merge commit passed the same five required checks. + +| Verified revision | CI evidence | Result | +|---|---|---| +| Final PR head `1613143` | [Run 36986675925](https://github.com/HodeTech/LearnStack/actions/runs/36986675925) | All five required jobs succeeded | +| `main` merge commit `8edbb03` | [Run 37002423112](https://github.com/HodeTech/LearnStack/actions/runs/37002423112) | All five required jobs succeeded | + +Final implementation verification records **2,594 passing backend cases**: 1,577 +unit, 184 architecture, one contract, 171 Docker-free integration and 661 Docker +integration, with zero failures or skips. Release build has zero warnings/errors; +format and link/fragment checks pass. The historical P02d-1 record remains unchanged. + +The live required-check list still contains the five recorded contexts with +`strict: true`. The documentation closeout also passes 184 architecture cases, +execution/zero-skip guards, added-prose wrapping and relative-link/anchor checks. + +**P02d-2 is closed. Phase 02d remains in progress.** P02d-3 through P02d-7 have +not started. No public business endpoint or browser demo is delivered by this merge. +ADR-0049 and the Course Marketplace pilot, Phase 09a, remain Proposed. + +#### P02d-3 entry readiness + +P02d-2's merged definitions, settings and seed satisfy the implementation dependency. +The next action is P02d-3's decision pass, followed by read internals with no HTTP: +generation-keyed Customization projections/cache families and a typed Tenancy +settings accessor. The packet table and decision register remain authoritative: + +- G12's cache-key part, G22's ambient loader/generation/rollback/cache contract and + G24's display fallback remain to be accepted. +- G23's no-settings-cache bound is already Accepted. The accessor's name, ambient + loading and tenant/organization scope contract remain P02d-3's decision work; + organization branding overrides and their token merge remain Phase 06. +- Cold/warm statement-count, cache-fault and rollback safety proofs belong with + these readers. Public contracts/eligibility remain P02d-4; transport, rendering + and the final browser/CI demo remain P02d-5, P02d-6 and P02d-7 respectively. + +## P02d-3 — Read internals + +### P02d-3 decision package (2026-10-02) + +**Accepted — 2026-10-02, verified against `0dec43b`.** The maintainer approved +the three decisions and implementation steps below before source changes. This +closes G12's cache-key part, G22, G23's accessor part and G24's internal fallback +part; it claims no implementation. Detail owners are synchronized in this first +commit. Original questions and shipped delivery records remain intact. Public +response and page-state decisions remain with P02d-4/6. + +#### Verified premises and document review + +The review baseline is `0dec43b` on `development`, following merged PR #23. +The required context reading, relevant module specs, localization/cache/isolation +architecture, ADR-0008/0010/0013/0038/0040/0043/0050/0051 and governing standards +were checked against the current adapters and composition roots. Two fresh +read-only review sessions independently examined cache/transaction safety and +settings/localization boundaries. A third reviewed the completed proposal and +verified no blocker or major finding. These sessions ran no tests and changed +no source. + +- The four Customization writers bump the durable tenant generation inside their + business transaction. A rollback discards that increment; a later commit can + reuse its value. An uncommitted cache fill would then become reachable. +- The ambient unit opens the default PostgreSQL isolation level. Under + [READ COMMITTED](https://www.postgresql.org/docs/18/transaction-iso.html#XACT-READ-COMMITTED), + successive queries may see different committed states; a generation-first + query alone does not prove a coherent definition snapshot. +- `ICacheService.GetOrSetAsync` has a shared factory lifetime. An ambient + connection must not be captured by a factory that may outlive its request or + be shared with another request. This contract uses awaited get/load/set calls. +- P02d-2's exact writer reader is uncached and purpose-aware. It remains so; + display reads must not weaken NewBinding eligibility or change stored pins. +- G23 already rejects settings caching in P02d-2/3. Standards 20's stale TTL rows + are corrected to a reserved, unused family; its metric spelling remains intact. +- The localization architecture, standard and `LocalizedText.Resolve` describe + different fallback chains. G24 below reconciles them before the first caller. +- Organization branding/token merge remains Phase 06. The glossary now states + that ownership explicitly; generic setting scope is not branding authorization. + +The selected vehicles remain the ones assigned by the register: module specs, +architecture/standard details and this dated package under existing ADRs. No new +ADR is required by the accepted ambient design. A different setter, transaction +mode, access policy or cross-module mechanism requires its decision record and +maintainer approval before implementation. + +#### Accepted gate answers + +| Gate part | Accepted answer | Detail owner | +|---|---|---| +| G12: cache key | Cache immutable, untranslated definition families per tenant/generation; indexes inside each family use exact `(key, schema_version)`, including Active and Deprecated, excluding Draft/deleted. Never substitute Active for an unresolved pin. The writer reader stays uncached | Customization spec, Education pin invariant; architecture 32 § 8.2 | +| G22: loader and correctness | Ambient caller transaction only; fresh generation probe per batch, coherent generation/rows snapshot on a miss, mutation-scope cache bypass, bounded statements, cache-fault fallback and generation-driven freshness as specified below | Customization spec § Primary read flow; architecture 32 § 8.2; standards 10/20 | +| G23: accessor | `ITenantSettingsAccessor`, uncached and ambient; typed registered settings, explicit tenant/current-organization selection and whole-value precedence. `branding.theme` remains tenant-wide. No caller-supplied tenant/organization authority | Tenancy spec and glossary; standards 20's existing no-cache answer | +| G24: display fallback | Localization architecture owns the chain; the standard links it. Exact requested tag, progressive narrowing, exact tenant default, platform `en`, then deterministic first-authored Pattern B label. Every resolved label carries its actual locale. Nullable Pattern A display fields end absent; URL/body lookup never falls back | Localization architecture § Fallback Rules; standard 08; SharedKernel and Customization contract; public fields remain P02d-4 | + +#### Customization projection and cache contract + +`ICustomizationDefinitionProjectionReader` is an application +interface returning immutable values through mechanism 1 of ADR-0010. This is an +in-memory projection, not a new `public_*` table or an integration-event consumer. +It resolves a batch of exact content-type and taxonomy revision pins with one +caller-provided display-locale context. No foreign Domain/Infrastructure type, +public marker, HTTP endpoint, schema validator or compiled-validator cache is added. + +Unresolved/ineligible individual pins remain identifiable as missing members of +the batch, without substituting another revision or failing unrelated members. +The API's placeholder/refusal contract, warning attribution and protected-content +eligibility remain G12/G5/G26 in P02d-4. Stored labels stay immutable in the cache; +resolved labels are produced per call, so a locale is not needed in these keys. + +Two families contain all eligible revisions, including taxonomy bands. Loading +both sets together prevents N+1 work for lists and gives one coherent snapshot: + +| Family | Key via `CacheKey.ForTenant` | Stable `cache.name` | +|---|---|---| +| Content types | `{tenant_id}:customization:content-types:v{generation}` | `customization:content-types` | +| Taxonomies | `{tenant_id}:customization:taxonomies:v{generation}` | `customization:taxonomies` | + +The generation is a separate logical-name component passed to the existing +multi-part factory, never a hand-built separator. These templates replace +architecture 32's generation-embedded names and per-key taxonomy example in +this decision pass; the registry, metrics list and adapter mapping change together. +`TenantPageBlock` and its cache family remain Phase 04 work. + +- Require a resolved real tenant and an active, correctly announced/enlisted + transaction before every read, including cache hits. Keys come from that + trusted context, never from a request tenant id. RLS remains effective. +- Read the durable generation afresh for every batch; do not memoize or cache it. + A fully warm read uses one generation SELECT and no definition query. +- On any miss/fault, load generation and both eligible sets in one read-only SQL + statement snapshot on the same connection. Use parameterized, explicit tenant + predicates over Customization-owned tables only, following + [Database Standards § Raw SQL](../standards/05-database.md#raw-sql). + Use that statement's generation for both returned sets and cache fills; + discard earlier cache hits if the probe's generation changed. Cold/partial-hit + reads use at most two SELECT statements, independent of the number of pins. +- An absent counter with no definitions yields an empty projection; no built-in + values are synthesized. Do not cache the absent-counter result. A nonempty + definition set with no counter is a bounded configuration refusal and is not + cached. A present counter with empty sets is valid. +- Before a supported Customization store mutation or generation bump, mark this + scoped reader state dirty. Dirty or rollback-only scopes bypass cache get and + set entirely; they can read their saved database changes through the ambient + snapshot. The flag is sticky for the DI scope, avoiding transaction-object + reuse and nested-frame resets. Pending tracked changes are not auto-flushed by + the reader. A fresh scope regains normal caching. +- A clean scope can fill before its own read transaction commits because its + snapshot contains committed Customization data only. Rolling that read back + cannot publish speculative definitions. Fill safety must be proved for reads + before and after nested writers and for rollback/reissued generation values. +- Await each cache operation in the caller's lifetime; do not pass the ambient + loader to `GetOrSetAsync`, spawn work or parallelize module queries. Concurrent + cold callers may each load the bounded snapshot; this trades coalescing for + explicit transaction ownership without changing the cache port. +- Cache read/write faults degrade to database results with a bounded diagnostic; + caller cancellation propagates. Database errors are not cache misses. No + partial cache result may make a batch look complete. +- L1 TTL is 60 seconds; future L2 remains 15 minutes on Phase 11's trigger. + Generation reads bound definition freshness, while TTLs reclaim stranded keys. + Each instance's L1 follows the same durable counter; no event or L2 is required + for this family's invalidation correctness. + +The warm/cold statement counts are acceptance proofs, not measured latency. +The existing `< 1 ms` hit target must distinguish in-memory resolution from the +mandatory generation database probe. Record end-to-end timings and query plans +for the seeded fixture; do not claim a production p95 from a small local sample. +The family-wide load has a data-volume cost: it includes retained revisions, not +just the bounded requested pin list. Report rows/bytes with the measurements; +Phase 04's larger authoring workload re-evaluates that cost before expanding it. + +#### Typed settings and display fallback contract + +`ITenantSettingsAccessor` exposes typed registered reads through Tenancy contracts, +without a raw string-key/JSON export or a generic settings HTTP surface. The +production registration initially admits only the delivered `branding.theme` +palette. Reuse its grammar/contrast policy; return a typed four-color value and a +bounded absent/invalid outcome, never a partial palette or raw JSON. P02d-4 owns +safe public defaults/allowlisting; P02d-6 owns CSS injection. + +For a registered setting that permits organization scope, select tenant-wide and +exact current-organization rows explicitly, excluding soft-deleted rows; no +organization context selects tenant-wide only. Merge the organization value over +the tenant value as one whole value, without deep JSON/token merge. Invalid selected +values return a typed configuration refusal, without silently adopting another +scope. Synthetic test registrations prove this generic precedence; no speculative +production setting key or organization-branded palette is added. Even a future +`app.scope = 'tenant'` hatch cannot introduce sibling overrides into this selection. +The branding registration selects tenant-wide only in every organization context. + +The accessor opens no transaction, announces no context and caches neither values +nor per-scope snapshots; a supported write is visible to the next read under the +ambient database isolation. Audit and permissions matrices identify this internal +interface as unrouted, not as a new audited write. Any request used only by tests +stays test-only; any production MediatR query added must be classified Off. + +For G24, add a locale-carrying resolution result to `LocalizedText` and retain the +existing string-returning API as a compatible wrapper over the same algorithm. +First-authored means canonical locale keys ordered ordinally, as the shipped +`ImmutableSortedDictionary` implements; it does not mean JSON insertion order. +Do not widen `tr` to `tr-TR` or narrow the tenant/platform default candidates +implicitly. The platform `en` candidate is for display labels only; it authorizes +no content locale. The caller supplies the tenant default once for the batch. + +Pattern A rules concern optional display fields after an exact routable translation +has been found. They never locate another slug/translation/body. Required content +fields keep the authored translation; a nullable field with no permitted display +fallback remains absent. P02d-4 specifies field-level response applicability and +resolved-locale fields; P02d-6 emits the corresponding language attributes. + +#### Implementation steps and required review loop + +| Step | Scope and evidence | +|---|---| +| 1 | Locale-carrying fallback and uncached typed settings accessor. Unit fallback/grammar tests; app-role tenant/org/no-org selection, invalid/missing/soft-deleted settings, future tenant-scope hatch, read-after-write and no-cache proofs; register both API and Seeder roots | +| 2 | Batched exact-pin display contract and coherent ambient snapshot loader, initially uncached. Active/Deprecated versus Draft/deleted, mixed missing pins, tenant separation, empty/missing generation, no validation on read, resolved locales and coordinated generation/row race proofs | +| 3 | Generation cache families, scoped mutation bypass and metrics. Cold/warm counts, partial/cache-fault/cancellation behavior, cross-tenant warm alternation, nested write/read, rollback/reissue and independent-process freshness proofs; measured budgets, composition parity, full validation and packet closeout | + +Each step: implementation and focused validation, commit on `development`, fresh +independent security/correctness/contracts/documentation review, verify findings, +fix and commit; then a second fresh review round and verified fix commits before +the next step. Models/effort follow the complexity of each review surface. No +branch change. Packet completion updates the current-state docs and delivery +record; the PR is opened for maintainer review after all three steps pass. + +Relevant workflow skills are `add-integration-test`, `add-architecture-test`, +`update-glossary`, `standards-check`, `code-review`, `run-tests-locally` and +`commit-and-pr`. No new handler, entity or migration is planned; if implementation +requires one, dispatch its matching skill before the change. + +At acceptance, synchronize the Customization/Tenancy specs and matrices, glossary, +architecture 09/12/32, standards 08/10/15/20 and any catalogue rows for new guards. +Preserve existing Accepted ADR bodies and dated P02d-1/P02d-2 delivery history. +README, CLAUDE and roadmap index follow the actual decision/implementation state. +The full backend validation includes Release build, formatting, positive unit, +architecture, contract and both integration populations, with zero failed/skipped +cases. Documentation checks cover links/anchors, prose width and frozen delivery +history. No frontend behavior or public endpoint changes in this packet. + +#### Maintainer approval + +The maintainer approved the package together: + +1. G12/G22's ambient coherent-snapshot cache contract, batched exact pins, + two family keys, dirty-scope bypass and bounded database statement counts. +2. G23's uncached typed accessor, whole-value generic scope precedence + and explicitly tenant-wide branding registration. +3. G24's architecture-owned fallback, ordinal-first label terminal and + actual resolved-locale metadata while retaining exact content/URL admission. + +The three-step plan is part of the accepted package. This decision commit precedes +implementation, as required by the maintainer and +[implement-task Step 1](../../.claude/skills/implement-task/SKILL.md#step-1--scope-and-alignment). + +### Delivery record: P02d-3 + +**Complete, unmerged — 2026-10-02.** The accepted decision commit is `307bbcd`. + +#### Step 1: typed settings and locale resolution + +Implemented `ResolvedLocalizedText` and the compatible string wrapper, plus the +registered typed settings accessor in both composition roots. The sole production +registration is tenant-wide branding; synthetic tests prove generic whole-value +organization precedence. Explicit predicates, soft deletion and ambient admission +protect reads without a cache or raw configuration export. + +Release build: zero warnings/errors. Unit: 1584 passed; architecture: 184 passed; +integration: 241 passed (Docker/settings, writer/seed and Docker-free cases). +All three populations have zero failed/skipped; formatting and document checks pass. +Both independent review rounds passed; Step 2 follows. Public consumers/metadata +remain P02d-4/6. + +**Step 1 review round 1.** Two fresh GPT-5.5 high sessions reviewed +`307bbcd..9293202`. No verified Blocker/Major. Two verified Minor findings were +fixed: the localization illustration used a second stale fallback helper, and +both composition roots overstated feature flags as the only module-facing read. +The illustration now calls the shipped resolver; comments describe their own +read. No behavior changed. + +**Step 1 review round 2.** Two fresh GPT-5.5 xhigh sessions reviewed +`307bbcd..5848066`. Both approved the code; no verified Blocker/Major. +They independently identified the same stale delivery-status sentence above, +which is corrected in this closeout. Related current-state carriers now record +both rounds as passed. Documentation link/fragment and diff checks pass. + + +#### Step 2: batched coherent definition reads + +Implemented the immutable exact-pin display contract and ambient loader in both +composition roots. One SQL statement returns the generation, both eligible +families and taxonomy bands using their composite revision key. Individual +invalid/ineligible pins remain missing without revision substitution or dropping +valid neighbors. Actual display locales and authored descriptor order survive; +raw schemas stay inside the loader. The writer's purpose-aware reader is unchanged. + +The reader is deliberately uncached in this step. Every batch probes the durable +counter and loads the coherent statement snapshot; cache, dirty-scope behavior +and warm counts remain Step 3. The no-validation-on-read architecture guard walks +module helper dependencies and has planted direct/helper and clean controls. +Release build has zero warnings/errors; 1584 unit, 186 architecture and 21 focused +Docker integration cases pass with zero failures/skips. The real guard rejects a +planted validator dependency in the production snapshot helper, then passes after +restoration. Formatting and documentation checks pass. Both review rounds passed. +No cache implementation is claimed. + +**Step 2 review round 1.** Two fresh GPT-5.5 high sessions reviewed +`4829414..77197b9`. No verified code or SQL finding; two Minor document carriers +still treated G23 or Step 1 review as pending. Both are synchronized. The root's +additional guard check demonstrated a concrete validator adapter escaped the +interface-only ban; a planted concrete probe failed before the fix and passes +with the adapter census. The full architecture suite passes after the fix. +Round 1 is complete. + +**Step 2 review round 2.** Two fresh GPT-5.5 xhigh sessions reviewed +`4829414..94a84ab`. Both approved, with no verified findings. Current-state +carriers record both rounds as passed; link/fragment and wrapping checks pass. +Step 3 follows. No public consumer or cache implementation is claimed here. + + +#### Step 3: generation cache and read safety + +Implemented the two untranslated immutable definition families, awaited cache +get/load/set and stable metric names. Every read probes the durable generation; +a miss loads both families and generation from the same statement snapshot. +Supported stores and generation bumps mark a sticky scoped dirty flag before +mutation. Dirty and rollback-only reads bypass cache get/set entirely. Cache +fault diagnostics omit private exception/key payloads; cancellation and database +failures propagate with their own meaning. L1 is 60 seconds; L2 remains Phase 11. + +Release build: zero warnings/errors. Unit: 1586 passed; architecture: 186 passed; +focused Docker integration: 33 passed, including 23 projection/cache/composition +cases and ten publication-failure/concurrency cases. All have zero failures/skips. +The tests prove cold/warm statement counts, partial-hit publication coherence, +locale-neutral families, tenant alternation, independent L1 freshness, nested +write/read, store-save-before-bump, absorbed post-save refusal, rollback/reissued +keys, faults/cancellation, missing-counter admission and API/Seeder root parity. +An attempted test-only transaction reopen after rollback was correctly refused; +the proof uses a fresh scope, preserving ADR-0040's irreversible rollback-only rule. +The first full run passed unit, architecture, contract and Docker-free suites. +It exposed four missing scoped-state registrations in two legacy test fixtures; +those fixtures now supply the new state. A separate Seeder case encountered a +connection-open timeout before reaching its seeded race. All six focused fixture +and seed-race cases passed after the fix; the full Docker rerun was pending at +the implementation commit. No retry +or weakened +assertion was added. The review closeout below records completion of both rounds. + +**Local seeded measurement.** The executable +`Seeded_local_measurement_records_statement_plans_payload_volume_and_end_to_end_timings` +case uses a disposable PostgreSQL database through `learnstack_app`, the full +P02d-2 seed and 20 observations after warmup. Tenant `demo-english`, generation 8: +two content types, two taxonomies and nine bands. UTF-8 JSON payload from the +coherent statement is 1984 bytes; this measures wire JSON, not managed heap size. + +| End-to-end path | Minimum / median / maximum, ms | SELECT statements | +|---|---|---| +| Cold | 0.736 / 0.781 / 0.975 | 2 | +| Warm | 0.235 / 0.259 / 0.304 | 1 | +| Typed branding setting | 0.259 / 0.300 / 0.352 | 1; uncached | + +**Measurement erratum — 2026-10-03.** The historical “median” column above +reported upper medians, not the average of both middle observations. The routine +is corrected; the new sample and its limits are recorded in +[PR #24 review remediation](#pr-24-review-remediation-2026-10-03). + +`EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)` on the actual parameterized statements +uses `pk_customization_generations` for the probe and composite tenant/key/version +indexes for both families; bands use `ux_tenant_level_taxonomy_items_taxonomy_sort`. +Probe execution: 0.007 ms, two shared-buffer hits. Snapshot execution: 0.117 ms, +12 shared-buffer hits; both have zero shared-buffer reads. The snapshot's nested +band aggregate remains one SQL statement. These small local observations are not +production p95 evidence, do not isolate the in-memory `< 1 ms` target and do not +prove the cold `< 20 ms` or settings `< 5 ms` production budgets. Retained revision +volume, concurrent load and Phase 04's larger authoring workload require renewed +measurement before extending the families. No latency threshold is hard-coded +into the test. + + +**Step 3 review round 1.** Two fresh GPT-5.5 xhigh read-only sessions reviewed +`287318f..7ac197f`, covering transaction/cache safety and contracts/test evidence, +performance and corpus consistency. Both approved with no verified findings. +No source fix was necessary; Round 2 was pending at that milestone. + +**Complete backend verification after fixture repair.** Release build: zero +warnings/errors; formatting passes. All 2637 cases passed with zero failures/skips: +1586 unit, 186 architecture, one contract, 171 Docker-free integration and 693 +Docker integration. Positive TRX counters confirm `passed = executed = total` in +each suite; the full Docker rerun includes the earlier seed timeout case and +legacy fixture cases. Markdown links/fragments, diff checks and frozen P02d-1 +suffix checks pass. This evidence precedes the second independent review round; +it does not mark the packet merged. + + +**Step 3 review round 2 and packet closeout.** Two fresh GPT-5.5 xhigh read-only +sessions independently reviewed `287318f..5b50995`. No verified code, security, +transaction, cache, performance or test finding. One reviewer identified a Minor +status ambiguity in the phase's opening P02d-2 milestones, which still described +P02d-3 as next/open. Those sentences now explicitly describe their historical +moment; the current completion note and packet table name the accepted, delivered +P02d-3 state. Current-state carriers record both rounds as passed. The verified +fix changes documentation only; the complete backend execution evidence above +still applies to the unchanged source. Final links/fragments, formatting, diff +and architecture metadata checks pass. + +All three implementation steps and both review rounds per step are complete. +No new ADR, migration, HTTP endpoint, context setter or transaction mode was +required. P02d-3 is ready for PR review and remains unmerged. Phase 02d remains +in progress; P02d-4 owns the next decision pass for public eligibility, response +contracts, locale/cursor/cache rules, Off classification and read-only controls, +OpenAPI/SDK drift gates and request-level Education isolation. P02d-5/6 provide +SSR and rendering; P02d-7 provides the full-stack demonstration and exit proof. + + +**PR documentation correction — 2026-10-02.** After PR #24 opened, two CodeRabbit +Minor findings were verified against the current files: the Education spec still +named P02d-3 as next, and the roadmap index lacked a sentence terminator. Both +are corrected. Education now records P02d-3 complete/unmerged and P02d-4 next. +The fix changes no backend source or test; the 2637-case execution evidence +remains applicable. Final Markdown link/fragment and diff checks pass; required +CI is rechecked against the final documentation head before handoff. + + +#### PR #24 review remediation (2026-10-03) + +The maintainer supplied two independent reviews of `8edbb032..a317d389`. +Findings were verified against current source before changes; two additional +read-only agents checked documentation scope and runtime contract claims. +No new ADR, endpoint, migration or accepted decision is introduced. + +- **B1/M1/M14:** the validator guard now follows assembly-scoped references across + every production project, including Customization Domain/Contracts and core + helpers. Planted controls cover parameter/return/generic/event attributes, + wrapped generics, constraints, catches, lambdas and state machines. A narrowed + production census mutant fails on the planted Domain helper; the wrapped + generic control failed before the IL correction. Restored source passes. +- **M2:** the old probe barrier legitimately allowed a caller to warm the other. + The test now parks both independent snapshot loaders before either fills, + proving exactly two SELECTs and complete values per caller without flakiness. +- **M3–M8:** recoverable cache faults still fall back with bounded diagnostics; + fatal process exceptions propagate. Invalid setting-token values return a + bounded failure, settings admission checks its context's enlistment, branding + uses one canonical key, redundant cached revision fields are removed and + malformed-pin comments describe the actual per-revision behavior. Internal + definition refusals use neutral `lockey_invalid_value`, not a schema-extension + message. Malformed band labels omit their entire pin and preserve neighbors. +- **D1/D2/M10–M12:** editable Scope and current-state carriers now identify the + delivered locale/accessor/fallback work, planned organization branding and + generation-driven L1 consistency. Frozen P02d-1 accepted answers and delivery + record, and dated P02d-2 closeout/readiness, remain unchanged. + +**Disposition of remaining suggestions.** The accepted registry is an explicit +server-owned value, not an additive DI-registration API; its replacement rule is +now documented rather than inventing a new extension mechanism. The Phase 04 +`blocks-v{generation}` example is a legal, explicitly unimplemented target. +Public surface enforcement remains P02d-4's G30, not a delivered P02d-3 gate. +L2/serialization, cache-fault metrics and cold-load coalescing are not claimed by +this packet. Missing-counter detection intentionally includes Draft/deleted roots; +nonpositive generations remain invalid. Test-only non-null assertions fail loudly +if required measurement commands are absent; they do not hide a skipped proof. + +**Measurement correction.** The earlier table's historical “median” values were +upper medians (the eleventh of twenty observations). The routine now averages +both middle observations. A new twenty-observation sample after warmup, from +`learnstack_app` and the same 1984-byte fixture, records: + +| End-to-end path | Minimum / median / maximum, ms | SELECT statements | +|---|---|---| +| Cold | 0.598 / 0.738 / 0.973 | 2 | +| Warm | 0.184 / 0.209 / 0.275 | 1 | +| Typed branding setting | 0.190 / 0.235 / 0.292 | 1; uncached | + +Probe/snapshot execution is 0.008/0.146 ms with 2/12 shared-buffer hits and zero +reads. These observations still prove no production percentile or latency budget. +The measurement case asserts statement/data invariants, not unstable timings. + +**Local validation:** Release build has zero warnings/errors. Unit 1586, +architecture 187, contract 1, Docker-free integration 171 and Docker integration +697 pass: **2642 cases, zero failed or skipped**, with positive TRX execution +counters checked. Full format, Markdown links/fragments and diff checks pass. +Fresh correction review rounds follow the implementation commit; PR #24 remains +unmerged. + + +**Correction review round 1 — 2026-10-03.** Two fresh read-only reviewers, +GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed `a317d38..ab2a8b3` across +architecture/test proof and runtime/documentation. Both approved with no verified +findings. They ran no builds or tests; the primary executed the checks above. + +**Correction review round 2 — 2026-10-03.** Two new read-only reviewers using +the same models/effort independently reviewed that range with the lenses +exchanged. One Minor was identified and confirmed by both: Standards 20's new +“other families” sentence still generalized L2 to no-L2/uncached families. The verified +fix now links the +canonical per-family policy instead. No further finding or backend change. +Required CI and CodeRabbit passed on reviewed code head `ab2a8b3`; there are no +unresolved review threads. Links/fragments, metadata and diff checks pass after +the wording fix. Final documentation-head CI is rechecked before handoff. +PR #24 remains unmerged. + + +#### PR #24 depth and settings correction (2026-10-03) + +The maintainer's review of `8edbb032..825e4f57` identified two valid reader +defects. Both were verified against current source and reproduced through real +PostgreSQL as `learnstack_app` before the production correction. + +- **Snapshot depth:** the accepted raw JSON limit remains 64. The SQL snapshot + adds two containers around content-type schemas and four around taxonomy band + metadata. Explicit, bounded reader limits of 66 and 68 preserve that source + contract. No schema admission, publication, tenant predicate or cache policy + changes. +- **Settings parsing:** `JsonException` and `InvalidOperationException` from the + selected registration's parser return the existing bounded `validation_failed` + outcome. An invalid organization override never falls back to the tenant value. + Existing unsuccessful results remain refusals; cancellation and unrelated I/O + failures still propagate. + +Nine new database cases cover the two reported inputs, both raw-64 boundaries, +raw-65 write refusal, unrelated cold pins, warm reads, either partial-cache +direction, malformed setting roots/fields and non-shape parser failures. Before +the correction, the four depth and three shape cases fail at the expected parser; +the two non-shape controls pass. No Accepted ADR, migration or public API changes. + +**Local validation:** Release build has zero warnings/errors. Unit 1586, +architecture 187, contract 1, Docker-free integration 171 and Docker integration +706 pass: **2651 cases, zero failed or skipped**. Positive TRX execution counters +and all nine new regression outcomes are verified. Full format, Markdown +links/fragments and diff checks pass. Two fresh independent review rounds follow +the correction commit. PR #24 remains unmerged. + +### P02d-3 merge and closeout (2026-10-03) + +The maintainer merged [PR #24](https://github.com/HodeTech/LearnStack/pull/24). +GitHub records final PR head `79d1539c681e5188ae57fb3af47bdf6f5049990a` and merge +commit `d1a47369d82f8b6d91cb325f56d4c42382ec77b6`. The merge contains that head and +has the identical tree; the JSON-depth/settings correction above is included. + +- All five required checks pass on the + [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37111808188). + CodeRabbit's check succeeds and no review thread remains unresolved. The + [merge-commit CI run](https://github.com/HodeTech/LearnStack/actions/runs/37120044890) + also succeeds. Deferred OpenAPI/Lighthouse jobs are not executed proof. +- Local Release build, format and **2651 tests** pass with zero failures/skips: + 1586 unit, 187 architecture, 1 contract, 171 Docker-free integration and 706 + PostgreSQL integration. TRX verifies positive execution, including all nine new + boundary/parser cases. The historical delivery totals above remain unchanged. +- The packet delivers internal exact-pin display reads, coherent snapshots, + generation-keyed caching, typed tenant settings and locale-carrying fallback. + Its source dependencies and approved G12/G22/G23/internal-G24 parts are complete. + No public endpoint, authentication, browser renderer or marketplace ships here. + +**Next: P02d-4 — Public read API and contract checks.** Its implementation has not +started. The [packet gate table](phase-02d-walking-skeleton.md#packets-and-decision-gates) owns the complete +prerequisite list. Its open decisions cover unresolved bands, public response and +branding projections, entitlement/attribution, canonical locale handling, the cursor, +site data/route set, HTTP cache policy, public-surface/read-only/audit fences, +eligible-row refusals and the OpenAPI/SDK drift checks. +Publication and content access remain governed by +[ADR-0050](../decisions/0050-publication-and-course-content-access.md); protected +content cannot become anonymous merely because a row is published. + +P02d-5 owns server rendering and the trusted transport; P02d-6 owns the public +renderer; P02d-7 owns the two-host demo, full-stack CI and phase exit. Phase 02d +therefore remains in progress. No new decision is accepted by this merge closeout. + +**Correction/closeout review round 1 — 2026-10-03.** Fresh read-only reviewers, +GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed the source correction +`825e4f57..79d1539`, its evidence and the closeout documents. Source review has no +findings. One Minor incomplete P02d-4 gate summary was verified and fixed by linking +the canonical packet prerequisites; both reviewers approve. They inspected the +stored execution evidence and ran no builds/tests. A second fresh round follows +the closeout commit. + +**Correction/closeout review round 2 — 2026-10-03.** Two fresh read-only +reviewers, GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed +`825e4f57..2276edf` across runtime correctness, isolation, parser boundaries, +regression evidence and document consistency. Both return Standards Pass and Code +Review Approve, with no actionable findings. They independently inspect the +stored TRX and live merge/check metadata; neither reruns builds/tests. The final +closeout documentation passes the corpus metadata, relative-link/fragment and +diff checks. Development remains the working branch; P02d-4 awaits its own +accepted decision package. + +## P02d-4 — Public read API and contract checks + +### P02d-4 decision package (2026-10-03) + +**Status: Accepted — 2026-10-03.** The maintainer approved this complete package, +ADR-0052, its two dated clarifications, the four-step review plan and the exact +sixth required-check addition. This decision pass closes only the listed gate +parts; implementation starts after the decision/carrier commit. P02d-5/6/7 gates +remain open, and no endpoint, runtime proof or external setting is delivered by +acceptance. + +#### Verified premises and document review + +Reviewed against LearnStack `100bfefd6518df879fb9121499a70d7ceb6409ef`, on +`development`. P02d-1/2/3 are merged; production public controllers, a non-empty +OpenAPI snapshot and browser consumers do not exist yet. + +- Foundation: guidance/skills, principles, vision/MVP scope, glossary, roadmap and + ADR index; this phase's register, earlier delivery records, read contract, + criteria and risks. Proposed ADR-0049/Phase 09a do not govern this packet. +- Authority: ADR-0003/0010/0017/0033/0036/0040/0044, tenant resolution and audit + rules; API/gateway/isolation architecture and standards; factory, middleware, + ambient UoW, transaction/audit behaviors and request-surface guards. +- Content: ADR-0008/0043/0050/0051, Education/Tenancy/Customization specs and + matrices; locale/fallback, profile, exact-pin projection, settings and seed code; + frontend, accessibility, errors, database, cache and performance guidance. +- Contract: ADR-0023/0024/0035, SDK source/generator/lockfile, served OpenAPI + transformers and contract fixture; CI, CONTRIBUTING and architecture catalogue. +- Entitlement: ADR-0021/0034/0045, feature/license architecture, effective feature + evaluation and Null provider. Hub's contract pointer, key and Starter/Growth + plans were checked at `6adf93638e76114eda9c18a5095d0fe3c0fd43b1`, without edits. + +The read-only review found these implementation-relevant premises: + +- Normal organization context can come from a claim on a tenant host. Preserve + host provenance independently; never replace the reconciliation matrix. +- Host mapping admission does not check Tenant/Organization lifecycle. Tenancy + must own that check through an application contract. +- The existing locale writer port collapses several failures. Its contract stays + unchanged; a typed public configuration read distinguishes valid emptiness, + unavailable scope, unsupported locale and invalid stored configuration. +- RLS has no publication/access term. Eligible-body SQL must check the parent and + `public` policy itself before loading a body. +- Existing PublicSurface tests prove names and selected audit exclusions. They do + not yet prove actual methods, Off-only registration or controller write barriers. +- SDK factories returning `{}` stop compiling when generated paths become + non-empty. Their unused placeholder authority options must not enter v1. +- The pinned generator does not implement `x-extensible-enum` unknown branches. + New policy/state enums therefore use ADR-0024's closed-set default. +- Oasdiff defaults differ from ADR-0024. Explicit policy overrides and planted + changes are required; a fail level alone is insufficient. + +No build/test run is claimed by this document review. The implementation plan +below names the runtime proof, including real database HTTP requests and plans. + +Preparation used independent authority/UoW, locale/branding and contract/CI review +tracks (GPT-6-astra and GPT-6.1-sol, xhigh). Draft rechecks verified fixes for the +Education slug owner, required-field outcomes, cursor payload, sticky rollback-only +and the first-statement ordering exception. No remaining actionable finding in +those document scopes was reported. These are preparation reviews, not the two +implementation reviews required for each step below. + +The maintainer-supplied ADR review was checked against the current implementation +and Accepted contracts. ADR-0052 now states mandatory marked dispatch, limits the +runtime barrier to the enlisted transaction and names Registered guards. A focused +independent authority recheck found no remaining actionable issue. This preparation +record precedes maintainer approval; implementation proof remains pending. + +Baseline fact corrections are separate in `cdca081`: the glossary follows ADR-0045 +Amendment 3, and frontend architecture records the delivered P02d-2/3 theme +foundation. They do not form part of the public-read decision. + +Pre-acceptance preparation validation against `100bfefd`: all eight changed/new Markdown +files +pass local link and anchor checks (975 links, 331 fragments), changed-prose +wrapping and diff hygiene. +At that preparation boundary, frozen P02d-1 records and existing Accepted ADR +files remained unchanged. Acceptance appends only the approved dated clarifications. No +runtime/build proof is substituted for the implementation evidence below. + +#### P02d-4 accepted answers + +| Gate part | Accepted answer | Decision/detail owner | +|---|---|---| +| G5 unresolved band | No pin: null level. Missing exact vocabulary/band: bounded unavailable level, never rebound or raw key text | This contract and Education public-read spec | +| G6(b) | Canonicalize the shipped bounded locale grammar before membership, lookup and cursor binding; no trimming | Locale contract below and localization owners; URL redirects remain P02d-5 | +| G10 codec | Resource-local, keyless, forward keyset cursors for catalog and outline; bounded, versioned, context-bound, without confidentiality or MAC claims | Pagination contract below and API/Education detail; no SharedKernel codec or signing secret | +| G12 response | Exact Active/Deprecated pins, allowlisted text descriptors and bounded unavailable content; no raw body/schema or revision rebinding | Public DTO contract below, ADR-0050/0051 and module detail; page states remain P02d-6 | +| G16(f/g) public part | Whole typed four-color theme or null; baseline colors independent of entitlement; effective WhiteLabelBranding removes attribution only | Theme contract below, descriptor and architecture/standards detail; existing Hub pointer authority replaces a duplicated matching note | +| G24 response | Exact Pattern A content; Pattern B display labels report actual authored locale through `{value,locale}` | Locale/display contract below and localization owner; renderer language attributes remain P02d-6 | +| G25 | Host-resolved site bootstrap plus catalog/course/lesson reads; no edge tenant-ID lookup or route/query/body host/tenancy selector; effective host remains ADR-0036's input | ADR-0052 and frontend/infrastructure detail; three page consumers delivered P02d-6 | +| G26 route/response | Dedicated public prefix, four logical reads with explicit GET+HEAD, bounded pageable outline and closed DTO allowlists | Public contract below, API/module specs and OpenAPI; slug grammar remains the accepted P02d-1 contract | +| G27 | No-store on all public-prefix successes/errors; no ETag, Last-Modified or 304; internal definition cache remains independent | Cache contract below and API/performance detail; ADR-0039 validator derivation is unchanged | +| G28 | Mandatory PublicSurface requests through ISender, Off-only classification, GET+HEAD equality, structural bypass detection and READ ONLY on the enlisted ambient transaction | ADR-0052, ADR-0040 Amendment 8 below and Registered catalogue rows before code | +| G29 | Shared explicit eligibility; hidden Education outcomes use identical masked not_found; credentials never widen public access | Eligibility contract below, ADR-0050, ADR-0036 Amendment 8 and Education spec | +| G30 | Required single query locale on Education, validation_failed vs unsupported_locale 400; headers cannot choose content | Locale/error contract below and standards; trusted-hop header transport remains P02d-5 | +| G31 | One served/committed snapshot, policy-complete pinned diff check, typed SDK/drift proof and sixth required live check | Contract/CI plan below, standards, workflow and CONTRIBUTING; Lighthouse remains G44 | + +G5/G12/G16 renderer parts, G6(c), G30 header transport and G32–G45 retain their +named later packet boundaries. No marketplace or enrollment gate is reopened. + +#### Public routes and DTO contract + +All paths are relative to `/api/v1/public`. Each explicitly supports GET and +HEAD: **four logical read contracts, eight method/path OpenAPI operations**. +Every institution public-data endpoint dispatches a `[PublicSurface]` MediatR +request through `ISender`; its data access uses the enlisted read-only ambient +transaction. ADR-0052 owns that mandatory boundary, its bypass limits and proposed +guard names. Structural controls detect bypasses; real HTTP/database tests prove +the dispatched runtime path. No direct persistence path through a controller, +minimal API handler or helper is admitted. + +| Path | Query parameters | Response | +|---|---|---| +| `/site` | None | `PublicSite` | +| `/courses` | Required `locale`; optional `cursor`, `limit` | Catalog page | +| `/courses/{slug}` | Required `locale`; optional `lessonCursor`, `lessonLimit` | Course detail and optional outline page | +| `/courses/{slug}/lessons/{lessonSlug}` | Required `locale` | Lesson detail | + +No host, tenant, organization, actor, filter, search or sort selector is published +in route, query or body. The effective host still follows ADR-0036's direct-request +and authenticated trusted-hop rules. +Unknown query parameters and repeated single-valued parameters are rejected with +bounded `400 validation_failed`. Slugs retain the accepted +[Education slug grammar](../standards/08-localization.md#education-slug-grammar): +1–160 characters, with UUID N/D spellings excluded. An invalid slug returns +`400 validation_failed` naming `slug` or `lessonSlug`; do not synthesize a slug. + +DTOs are purpose-built public contracts; never reuse seed or internal projection +DTOs. Names below also specify the serialized allowlist: + +- `PublicSite`: `displayName` (Tenant's display name), `enabledLocales`, + `defaultLocale`, `theme`, `showPlatformAttribution`. A successful bootstrap has + at least one enabled locale and exactly one enabled default. Locale order uses + configured sort then canonical tag as a deterministic tie-breaker. +- `theme`: either null or exactly `primary`, `background`, `foreground`, `muted` + from the validated typed whole value. Null means the renderer's safe CSS + defaults; do not copy another palette into backend DTO code. +- Course summary: `slug`, `title`, nullable `summary`, `contentAccess`, nullable + `level`. No root identifier, timestamp, version, scope or authoring pin is needed. +- Level: `{state:"ready",label:{value,locale}}` or + `{state:"unavailable",label:null}`. An absent optional pin gives `level:null`. +- Catalog: `{locale,items:[course summary],pageInfo}`. Use the shared PageInfo + field vocabulary, without pretending backward navigation exists. +- Course detail: `{locale,course,alternates,lessons}`. Course is the summary above. + Alternate items contain only `{locale,slug}`. Restricted courses return + `lessons:null`, with no count, title, slug, order, descriptor or truncation flag. +- Public-course outline: `{items:[{slug,title,sort}],pageInfo}`. It contains no + body, definition or count. A public course without eligible lessons has a real + empty page, distinct from restricted `lessons:null`. +- Lesson detail: `{locale,course:{slug,title},lesson:{slug,title},alternates,content}`. + Alternate items contain `{locale,courseSlug,lessonSlug}`; both translations must + exist in that enabled locale. Exclude the current locale and order consistently. +- Ready content: `{state:"ready",rendererKey,label:{value,locale},fields}`. + `fields` are descriptor-ordered `{name,label:{value,locale},value}` plain strings + from the selected supported text-card profile. Missing optional fields are + omitted; unknown body properties are omitted. Missing required fields, + non-object stored body and selected non-string values make the whole content + unavailable. Derive requiredness as internal presentation metadata from the + admitted schema's `required` list; carry it through Customization's field + projection without exposing a public required flag or evaluating JSON Schema. + No coercion or schema evaluation occurs on read. +- Unavailable content: `{state:"unavailable"}`. Missing/deleted/Draft exact pins, + malformed definitions, unsupported renderer/profile, zero presentation fields + or invalid selected values expose neither body nor descriptor, and never use + another revision. Record bounded operator diagnostics without payload values. + +Policy values `public`/`enrollment_required` and state values `ready`/`unavailable` +are closed enums. Additions and removals are breaking under ADR-0024. `rendererKey` +is a string; `default-card` is the currently supported value, not a closed future +renderer registry. Rendering an unknown key remains G41's bounded fallback. + +Recursively exclude tenant/organization/actor IDs, root IDs/versions, audit columns, +settings keys/raw JSON, JSON Schema, arbitrary body objects, taxonomy metadata, +internal pin/revision/status/generation data and unpublished translations. A cursor +is the separately documented protocol exception: it contains seek identifiers, +not exposed authority or a secrecy guarantee. + +#### Host authority, eligibility and public errors + +The normal resolved context and host ceiling both apply. A nullable immutable +`HostScope` contains host TenantId and OrganizationId, constructed only by +`TenantContextFactory` from the attempt's existing host signals after its current +agreement/membership gates. Claim-only, ambient and unresolved contexts have none. + +Every public request requires a real matching host scope. Explicit host predicates +intersect with normal EF filters and RLS: tenant host means tenant-wide rows only; +organization host means tenant-wide plus that organization's rows. An org claim on +a tenant host cannot expose org content; a platform-host claim cannot turn that +host into an institution public site. Keep the factory independent of routing. + +The API hashes the normalized effective host from `HostClassification` for cursor +binding. Only the digest enters the query's pagination input. Do not put the host +string into the resolution attempt/context, public response or retained logs. + +Tenancy's typed internal configuration contract checks Tenant and, where present, +Organization under the current announced scope, on the same connection. Serve only +nondeleted Trial/Active tenants and nondeleted Active organizations. Missing, +Suspended, Archived or deleted scope gives generic `404 not_found`. This explicitly +selects Suspended behavior for public content; it is not an existing resolver check. + +Eligible course marketing requires matching scope, published/nondeleted course, +enabled canonical locale and its exact translation. Eligible lessons additionally +require published/nondeleted child, URL-parent membership, exact translation and +parent `content_access = public` before inventory, body or descriptor reads. +The protected-body SELECT includes all those parent/access conditions itself. +READ COMMITTED does not promise linearizable revocation across later statements. + +Nonexistent, draft/deleted, wrong-parent, untranslated, sibling-org, other-tenant +and restricted lesson outcomes share one `not_found` body after masking dynamic +`instance`/`correlationId`. Hidden course outcomes likewise match a nowhere slug. +Credentials do not produce grants or unlock this anonymous contract. Preserve +existing resolver outcomes: platform host retains HTTP 404 `tenant_mismatch`, +unknown host HTTP 404 `not_found`, and assertion/claim failures are not bypassed. + +Valid no-locale/all-disabled configuration remains representable internally. It +returns bootstrap `404 not_found` because no navigable public site is configured; +every well-formed Education locale is unsupported. Do not synthesize `en`. +Malformed stored tags or enabled locales without exactly one enabled default give +generic `503 dependency_unavailable` plus bounded internal diagnostics. Missing or +invalid theme alone yields `theme:null`, not a site failure. Unexpected database +faults retain the existing exception path; do not swallow cancellation or all errors. + +Success is 200; business/input errors publish 400/404/503 as applicable. Document +framework 405/429 and the existing unexpected 500 path in the shared Problem +Details component. HEAD has identical admission, status and applicable headers +with no response body, including errors. Tests observe the documented HTTP outcomes. + +#### Locale and display applicability + +Site bootstrap takes no locale. Each Education read requires exactly one `locale` +query value. Missing, empty, repeated, malformed or longer-than-35 values return +`400 validation_failed` with `errors.locale`, before opening the ambient read +transaction. Do not trim whitespace or extend the accepted LocaleTag grammar. +Canonicalize valid case variants before membership, SQL and cursor binding. + +Well-formed absent/disabled tags return uniform `400 unsupported_locale`, including +when historical translations remain stored. Enabled but untranslated gives an +empty catalog, detail 404 and omitted outline/alternate entries. Neither `X-Locale` +nor `Accept-Language` selects content. P02d-5 owns how its transport sets headers. + +Pattern A title, summary, slug and body are exact requested-locale data; a null +summary remains null. Pattern B labels use the existing single-owner chain in +[Localization § Fallback Rules](../architecture/12-localization.md#fallback-rules), +and carry the actual authored locale. A fallback label never authorizes reading +another content translation. Resolve the validated tenant default once per request +and reuse it in batched definition reads; do not evaluate JSON Schema on read. + +#### Catalog and outline continuation + +Use resource-local keyless codecs, not a new SharedKernel codec or signing-key +lifecycle. Catalog order is `(created_at ASC,id ASC)`; outline order is +`(sort ASC,id ASC)`, matching the existing lesson invariant. Seek/fetch `limit+1` +eligible rows using PostgreSQL timestamp precision and UUID ordering. + +Both page sizes default to 20, reject malformed/non-positive/repeated input and +clamp above 100. `pageInfo` is `{nextCursor,previousCursor:null,hasNext, +hasPrevious:false}`; nextCursor exists only when an additional eligible row exists. +Outline continuation stays on the course endpoint, so every lesson is reachable. +Restricted courses never produce an outline cursor or touch lesson inventory. + +Codec version is **1**. Encode UTF-8 JSON using canonical unpadded base64url, with +at most 1024 encoded ASCII characters and 768 decoded bytes; no compression. +Catalog payload has exactly `{v,scope,createdAt,id}`; outline payload has exactly +`{v,scope,parent,sort,id}`. UUIDs use canonical lowercase D format and are nonempty; +outline sort is a nonnegative Int32. `createdAt` is a representable UTC timestamp +with exactly six fractional digits (`yyyy-MM-dd'T'HH:mm:ss.ffffff'Z'`), preserving +PostgreSQL microsecond precision. No token logs or input reflection. + +`scope` is lowercase hex SHA-256 of a UTF-8 JSON array in this exact component +order: `[1,endpoint,hostDigest,tenantUuid,organizationUuidOrNull,locale,order]`. +UUIDs/locale are canonical, null remains JSON null, endpoint is `catalog` or +`course-outline`, and order is `created_at:id:asc` or `sort:id:asc`. `hostDigest` is +SHA-256 of UTF-8 normalized effective host, represented as lowercase hex. Tagged +components avoid concatenation ambiguity. Both scopes come from the preserved +host ceiling, not a claim-selected organization. Outline `parent` must match the +resolved eligible course UUID. Page size is excluded so it can change. Decoded +identifiers are continuation data, never selectors. + +Reject noncanonical encoding, excessive length, duplicate/unexpected fields, +wrong types, unknown version, invalid UTC timestamp/order/UUID, truncated data and +fingerprint mismatch with bounded `400 validation_failed` naming `cursor` or +`lessonCursor`, never reflecting the token. Validate syntax and known host/locale/ +endpoint binding before transaction entry; check outline parent binding after the +eligible parent resolves, without loading any body or outline before refusal. + +The fingerprint is not authenticated. A deliberately edited, otherwise valid +anchor may skip/repeat within the requesting host's independently eligible set; +it cannot enlarge it. Do not promise tamper rejection, confidentiality or stable +snapshot pagination. No anchor-row lookup is required. Earlier additions are not +rediscovered, later eligible additions can appear and deletes can shorten a page. + +#### Branding, entitlement and cache boundary + +Resolve theme through the existing typed accessor; it remains tenant-wide even on +an organization host. Null/invalid whole theme uses `theme:null`, never partial +colors. P02d-6 owns safe CSS injection and the existing frontend default palette. + +Baseline validated colors apply regardless of plan. Derive only +`showPlatformAttribution = !IFeatureFlags.IsEnabledAsync(WhiteLabelBranding)`; +do not expose flags, inspect provider storage or contact Hub directly. Null provider +grants hide attribution; false/omitted/degraded effective grants show it. Existing +authoring and provider/overlay failure contracts are unchanged. + +G16's vehicle is explicitly reconciled with Hub's pointer-only contract policy: +core owns the first-consumer meaning; Hub's existing contract pointer is the +matching authority, not a second duplicated rule. Its shipped key/boolean and +Starter/Growth values need no wire or endpoint change. No sibling branch is edited. +The observed Hub degraded-summary drift is a separate existing documentation +correction owned by Hub before Phase 02c's real provider consumer, under its own +branch authorization; it neither changes current Null behavior nor blocks P4. + +Set `Cache-Control: no-store` at the public-prefix boundary before middleware can +short-circuit, including 200/400/404/405/429/503 and existing exception responses. +Do not emit ETag or Last-Modified, expose versions or honor If-None-Match/304. +No Education response or site bootstrap cache is introduced. Internal generation +cache remains independent; it cannot decide publication, access or locale admission. +API/performance standards need a scoped exception, without changing write validators. + +#### Accepted ADR clarifications + +The maintainer approved the following clarifications with ADR-0052 on 2026-10-03. +They are appended to ADR-0036 and ADR-0040; existing bodies remain unchanged. +ADR-0052 owns the new public decision and bounded read-only setup-order exception; +the amendments disclose its composition rather than authorizing it independently. + +**ADR-0036, Amendment 8 — public host provenance (2026-10-03).** +The Decision and reconciliation matrix are unchanged. P02d-4 needs to distinguish +the host's public scope from a valid context narrowed/selected by claims. Under +ADR-0052, `ITenantContext.HostScope` is nullable and immutable. Only +`TenantContextFactory` constructs it from existing `HostTenantId` and +`HostOrganizationId`, after all existing reconciliation/membership checks succeed. +Claim-only, unresolved and ambient contexts carry null. No host string, route or +new lookup enters `TenantResolutionAttempt`; no context-accessor writer or SQL +setter is added. Public query admission requires real matching host scope and +explicit host predicates intersect with normal filters/RLS. Row 7 cannot expose +organization content through a tenant host; row 14 has no institution host scope. +Claims/assertions retain their refusals and never widen the anonymous response. +Carrier updates: API/security standards, context/gateway/isolation architecture, +frontend standards, Education/Tenancy public specs, glossary and catalogue; the +phase package owns the concrete public route/eligibility contract. + +**ADR-0040, Amendment 8 — read-only public frames (2026-10-03).** +Connection/transaction ownership, shared module contexts, the tenant setter set +and default writable behavior are unchanged. ADR-0052 authorizes a bounded +public-only exception to the Decision sketch's first-statement ordering; this +amendment does not authorize it independently. ADR-0052 adds +explicit ReadOnly/ReadWrite intent to `BeginTransactionAsync`; existing callers +remain ReadWrite by default. TransactionBehavior chooses ReadOnly for PublicSurface +requests before dispatch. A physical ReadOnly owner opens READ COMMITTED, executes +and awaits `SET TRANSACTION READ ONLY`, then returns its owner frame. The existing +tenant/organization announcement follows before any data SQL or handler dispatch; +that mode-control statement is its only permitted predecessor. Default writers +retain first-statement tenant announcement. Begin cleans up its partial transaction +on setup failure/cancellation, marks rollback-only and rethrows before returning a +frame; it cannot rely on TransactionBehavior's later cleanup try block. +A same-mode join uses existing frame ownership. A +mixed-mode join is refused before invoking the inner handler and marks the unit +rollback-only even if an outer caller absorbs it. It never promotes/demotes the +existing transaction or opens a second connection. Direct application-contract +reads inherit the ambient mode. READ COMMITTED stays unchanged. Mode belongs to +one physical transaction and resets on completion/rollback/disposal; no pooled +session state leaks. This never clears sticky rollback-only poisoning: successful +read-only commit permits a later writer on the same reusable unit; owner rollback, +cancellation or mixed-mode failure requires a fresh unit/scope. Verify pooled +connection mode reset separately. Normal Off reads write no audit row; independent +rejection audits retain their sanctioned path. PostgreSQL app-role proofs and +planted guards cover EF/SQL write attempts, both nesting directions, cancellation, +rollback and a later writable transaction on a valid unit, with poisoned-unit +refusal controls. +Carrier updates: backend/database/security standards, request-pipeline/isolation +architecture, module specs and catalogue. + +#### OpenAPI, SDK and required-check plan + +Use `backend/openapi/v1.json` as the only committed v1 snapshot. Contract tests +compare it with the production composition root's served `/openapi/v1.json`, without +test probe controllers. Canonical comparison may ignore object-key order, not +arrays, schemas, paths or response content. Assert all eight operations as a +non-empty positive control, closed DTO reachability and complete Problem Details. + +Pin oasdiff **v1.33.0**, commit `322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf`, +Apache-2.0. Verify the fixed Linux AMD64 release archive before extraction/execution +against SHA-256 `43a4e328e2d13ba1552d760aa68d2485c75c5621f309f6ff64ae895188345247`, +then assert its version; no latest-tag or unpinned installer fallback. Sources: +[pinned licence](https://github.com/oasdiff/oasdiff/blob/322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf/LICENSE), +[archive/checksums](https://github.com/oasdiff/oasdiff/releases/download/v1.33.0/checksums.txt). +Use `breaking --fail-on WARN` with an explicit checked-in severity file +for ADR-0024; promote request-field removals, optional/required response-field +removals and response enum removals/additions as policy requires. Commit fixtures +for every representable ADR-0024 breaking row and nonbreaking controls; any tool +gap needs a deterministic companion check, not a silently excluded policy row. +Validator/status behavior absent from OpenAPI needs named runtime tests. Official +[severity configuration](https://github.com/oasdiff/oasdiff/blob/v1.33.0/docs/BREAKING-CHANGES.md#customizing-severity-levels) +and [release](https://github.com/oasdiff/oasdiff/releases/tag/v1.33.0) are supporting +sources, not claims that the repository has installed or run it. + +At minimum set these exact checks to `err`: `request-property-removed`, +`response-optional-property-removed`, `response-required-property-removed`, +`response-property-enum-value-added`, `response-property-enum-value-removed` and +`response-mediatype-enum-value-removed`. Pinned +[check registrations](https://github.com/oasdiff/oasdiff/blob/322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf/checker/rules.go) +make the optional field and enum-removal overrides necessary. Existing extensible +enum policy is not automatically supported by this generator/tool pair; when an +open response enum first ships, its consumer/compatibility companions must close +that gap. This packet's public response enums remain closed. + +Diff PR base SHA's snapshot against head. Push uses the push-before SHA; manual +runs use an explicit base ref. A first-baseline exception is permitted only when +the verified base has no v1 operations and no committed snapshot. Fetch/read errors, +missing snapshots after bootstrap or deleted head snapshots fail. Failure artifacts +include both specs, SHAs, tool/version/policy and readable/machine reports. + +Regenerate from that file through `LEARNSTACK_OPENAPI`; keep the lockfile's +openapi-typescript 7.13.0. The SDK root exports generated types only. Replace the +unused `/server` stub with a thin typed public GET transport accepting an injected +Fetch-compatible transport; operation/request/response types derive from generation. +The supplied transport resolves relative SDK URLs; there is no global-fetch default +or implied working server hop. Parse errors as unknown, validate Problem Details +and project them into the existing closed AppError union including its unknown +branch, ignoring unrecognized extension members rather than trusting an unchecked +cast. Fake-transport tests cover the four-route inventory, encoded parameters, +absence of authority headers, success/errors, unknown codes and malformed bodies. +Remove unused `/client` factory/export. Do not add a runtime client library, tenant +ID option, header authority, hop secret or frontend request-header lookup here. +G35 selects the trusted server adapter/options in P02d-5. + +Provide four logical GET wrappers and a typed success/Problem Details envelope; +malformed JSON, transport failures and caller cancellation stay distinct from a +valid API error. Tests cover exact URL/query construction and generated typing. +P4 proves SDK operation coverage and drift; P5 supplies the first server consumer; +P6 proves every logical GET has a public-page consumer. HEAD is the HTTP companion, +not an invented browser JSON consumer. The phase's consumer criterion follows +this split. + +Replace the deferred CI placeholder with always-running **`openapi diff`**, removing +ENABLE_OPENAPI_DIFF and its deferred suffix. Add snapshot-based SDK regeneration/ +scoped generated-file drift to the required frontend job. Keep Lighthouse under G44. +After a real job runs, add `openapi diff` with GitHub Actions attribution (15368) to +live `main` protection, preserving the five current checks, strict=true and all +other settings. The maintainer approved this exact external setting change on +2026-10-03; +verify it by API read-back and record the date/list, without claiming an edit here. + +#### Implementation steps and two-round review loop + +First commit the Accepted decision records and carrier updates. Then implement on +`development`, without another branch or worktree: + +1. **Authority and read-only foundation.** Factory host provenance, public admission, + explicit UoW mode/setup/nesting/reset, pipeline selection and non-vacuous + structural companions. Validate factory/matrix controls, existing writer/audit + behavior and app-role READ ONLY EF/SQL refusal with writable/mixed-mode controls, + mode active when Begin returns and setup failure/cancellation cleanup. +2. **Public site and HTTP boundary.** Tenancy configuration contract, live-scope and + locale/configuration decisions, typed theme/effective attribution, site endpoint, + explicit HEAD, no-store and shared Problem Details. Validate production middleware + plus real database, safe fallback and swapped-provider controls. +3. **Education reads and continuation.** Central eligibility, three queries, exact + translations, catalog/outline cursors, descriptor-ordered lesson projection and + alternates. Add internal requiredness to Customization presentation fields; + prove optional omission, required absence and non-object/non-string refusal + without a schema validator. Validate all leakage/masking/locale/pagination cases + with positive controls; inspect real app-role EXPLAIN plans for consumer query + shapes and record representative cold/warm measurements with their limits. +4. **Contract/SDK/CI and closeout.** Snapshot equality/allowlist, breaking-policy + mutation fixtures, generated types/typed transport/drift, CI activation and + approved protection update; final documentation and required PR evidence. + +For **each** step: implement and commit; first independent multi-dimensional agent +review; verify findings, fix and commit; second fresh review; verify/fix/commit. +No empty fix commits. Choose model/effort by risk: authority, UoW, isolation and +policy reviews use the strongest available deep reviewer; contract, tests and +corpus get an independent implementation/docs reviewer. Re-review material fixes. +Proceed automatically to the next step unless a new approval boundary blocks it. + +Required packet evidence includes Release build/format, unit/architecture/contract, +Docker-free and Docker integration with no empty selection/skips; frontend checks; +snapshot regeneration/SDK drift; policy companions; changed-document link/anchor +checks and diff hygiene. Record actual counts/results only after execution. + +The behavioral inventory includes lifecycle/no-locale/invalid-default outcomes; +locale casing, 35/36 bounds, whitespace/newlines, repeated/missing/disabled values +and header invariance; exact fallback locale; parent/child policy/publication/ +deletion and cross-host/org masking; zero protected reader invocations; full catalog +and outline walks/ties/deleted anchors/restart/scope mismatch; GET/HEAD/error/no-store +and If-None-Match; zero normal audit writes; warm-cache policy controls; served +snapshot extra/removed operations and recursive forbidden fields. Use distinct +allowlisted fixture values when public IDs are intentionally absent. + +#### Acceptance carrier actions and authorization + +Acceptance updates the following owners together, before code: + +- ADR-0052/index and approved dated ADR-0036/0040 amendments; this register/status, + packet-specific criteria and Registered catalogue obligations. Preserve frozen + P02d-1/2/3 decisions and delivery history. +- API, backend, database, security, frontend, localization, error, performance, + infrastructure and architecture-test standards/index; derive changed nontrivial + rules from the accepted ADRs. Distinguish Registered proofs from implemented ones. +- Frontend, request pipeline, tenant isolation, localization, gateway, feature flags, + hybrid licence and customization architecture; replace public edge-ID lookup, + clarify query locale, exact display applicability, attribution and no-store. +- Education/Tenancy/Customization spec, audit/permission matrices and glossary; + public descriptors are separate from internal read/seed DTOs. Fix stale + ADR-0048-only access language and premature public-ID/consumer criteria. +- CI/CONTRIBUTING/SDK detail: record approved activation and later execution; do not + label a proposed job, transport, endpoint or required setting delivered. + +Maintainer approval covers this package, ADR-0052, the two appended clarifications, +four-step implementation/review plan and the exact sixth-check protection addition. +The gates listed above are now Accepted; later packet parts retain their owners. No new +schema, infrastructure adapter, +marketplace direction, protected learner access or renderer decision is implied. + +**Acceptance validation — 2026-10-03.** Against `cdca081`, 39 changed/new Markdown +files pass 2576 local-link and 538 fragment checks. Frozen P02d-1/2/3 decisions and +delivery records are unchanged; the existing ADR-0036/0040 bodies are byte-identical +after removing the two appended clarifications. Five CorpusConsistencyTests pass +in Release with zero failures/skips; diff hygiene is clean. Independent security, +locale/branding and contract/corpus checks found no decision change needed; +verified wording/table findings were corrected. This is acceptance validation, +not implementation delivery or either review round of an implementation step. + +#### P02d-4 Step 1: authority and read-only foundation + +**Implementation — 2026-10-03.** Factory-only immutable HostScope retains the +host tenant/organization independently of claim-selected scope. Public admission +requires matching real provenance; existing unmarked origins and resolution +inputs retain their contract. An explicit transaction mode defaults existing +callers to ReadWrite. PublicSurface selects ReadOnly before dispatch; mode setup +completes before Begin returns. Same-mode joins preserve ownership; mixed-mode +attempts poison the outer unit before handler invocation. Partial setup failure +or cancellation cleans up immediately. Physical completion resets mode, while +rollback-only remains sticky and successful read-only completion permits reuse. + +The HostScope construction guard has mutable/public/second-site planted controls. +Real app-role PostgreSQL cases exercise EF/raw SQL refusal, identical writable +controls, same/mixed-mode nesting, setup faults/cancellation and successful/fresh +scope reuse. The existing HTTP isolation probe now proves the read-only barrier; +a separate writable frame retains WITH CHECK refusal and an own-tenant positive +control. No production endpoint, eligibility reader or public response is shipped +in this step; Steps 2–4 retain those obligations. + +**Pre-review verification.** Release build has zero warnings/errors. All 2672 +.NET tests pass with zero failures/skips: 1598 unit, 189 architecture, one contract, +171 Docker-free integration and 713 Docker integration. Format and changed-document +link/anchor checks pass. At this pre-review boundary both review rounds were +pending; completion is recorded below. + +**Review round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers +examined `f79e4a4..77b13f5`. Neither found a production defect or Blocker/Major. +Verified Minor findings: two editable current-state carriers still described +Step 1 as pending, and the driver-log fault injection ran before Npgsql sent BEGIN. +Carrier wording now separates delivered foundations from Steps 2–4. The original +pre-send cases remain, with corrected wording; two additional cases observe server +read-only mode and inject fault/cancellation from the driver's safe ReaderClosed +callback before Begin returns. They assert cleanup before DI-scope disposal and +sticky poisoned-unit refusal. The pinned-driver reflection seam exists only in +tests and fails loudly if its members change. No production test hook is added. + +**Round 1 fix verification.** All nine transaction-mode cases pass with zero +failures/skips, including both post-server setup failures. Five corpus consistency +cases pass. A clean CI=true rebuild (rather than an incremental cached build) +exposed CA1852 on the deliberately unsealed planted offender. Its narrow, explained +test-only suppression preserves that offender; the clean Release rebuild then +passes with zero warnings/errors. Production code is unchanged by these fixes. + +**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers +examined `f79e4a4..1020611`. No Blocker/Major was found. A double-marked request +could pass unresolved admission without HostScope; no production request uses +that combination. PublicSurface now refuses that combination under unresolved +context, with a planted unit control, preserving ordinary provisioning and the +existing tenant_mismatch refusal. The HTTP isolation class summary now separates +its read-only refusal from the writable WITH CHECK controls. All 21 focused +admission unit cases pass with zero failures/skips. The contracts reviewer also +independently ran a clean Release build (zero warnings/errors), 189 architecture, +63 focused units, nine mode cases and the changed HTTP control on `1020611`, all +passing with zero failures/skips. A fresh GPT-6-astra xhigh focused review of +`1020611..248b5e3` found +no remaining actionable issue. Step 1 and both review rounds are complete. + +#### P02d-4 Step 2: public site bootstrap + +**Implementation — 2026-10-03.** The internal typed Tenancy configuration port +checks live tenant/mapped-organization lifecycle on the announced/enlisted +read-only transaction. Valid locale emptiness stays distinct from invalid stored +configuration. Site GET/HEAD dispatch a marked Off query through ISender; they +project only the approved display name, sorted enabled locales, default locale, +whole validated theme or null and effective attribution. No caller scope selector, +new permission, generic settings route or palette is added. + +An early public-prefix response policy covers successes and all errors, including +routing, rate limiting and exception handling: no-store, no validators and no HEAD +body. Structural Off, independent action dispatch/method and transitive controller +persistence guards include offending and clean controls. A production-composition +HTTP fixture uses real writer seeds and the application database role; it observes +server read-only mode and non-bypass role before each configuration read. Cases +cover lifecycle withdrawal after warm host resolution, locale order/emptiness, +invalid configuration, uncached whole-theme/null, attribution provider outcomes, +query refusal before data, no normal audit rows, exact endpoint inventory and +GET/HEAD error/no-store behavior. Education and contract/SDK/CI remain Steps 3–4. + +**Pre-review verification.** A clean CI=true Release build with --no-incremental +passes with zero warnings/errors. All 2710 .NET cases pass with zero failures/skips: +1599 unit, 195 architecture, one contract, 171 Docker-free integration and 744 Docker +integration. TRX counters retain each suite separately and agree with the runner. +After strengthening token/case/action-suffix route discovery and its controls, the +clean build and all 195 architecture cases pass again; all 29 focused site HTTP +cases pass. Formatting, diff hygiene and 1540 local links/400 fragments across the +15 affected Markdown files pass. Existing ADR-0052 text and frozen P02d-1–3 records +remain intact. At this implementation boundary both review rounds were pending. + +**Review round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers +confirm the production site behavior and identify two structural guard gaps. +The dispatch check independently found a marked construction and a Send call; +it now verifies the actual directly constructed argument, permits exactly one +Send and refuses unverifiable origins. Discarded marked, mixed-send and variable +controls fail. The persistence walk now follows production implementations of +reachable interfaces and abstract helpers; planted independent-connection +helpers fail through both shapes. The testing standard's endpoint status is +aligned. The clean Release build has zero warnings/errors; all six focused +public guard cases pass. A fresh second round follows the correction commit. + +**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers find no +production site defect. Their probes expose generic helper references that +compare closed instances against open definition keys, and a clean direct Send +followed by an unmarked helper Send. The walk normalizes generic definitions and +refuses sender acquisition in reachable non-controller helpers. Safe-return +interface and abstract probes now isolate implementation traversal, including +closed generic and clean controls. The helper-Send regression fails before the +fix and passes afterward. Generated action state machines remain part of their +owner instead of separate sender-acquiring helpers; an initial full-suite run +caught that false positive and the subsequent correction restores the clean +production control. Lambda extra-Send controls also fail. Current theme and +performance carriers record Step 2 delivery. A fresh focused review checks these +final corrections. + +**Focused fix verification.** The fresh review identifies an additional private +controller method that sends after the clean marked action. A controller-wide +Send census now equals the approved HTTP action count, while each action still +proves its actual marked argument. A planted private helper fails the control. +The follow-up control also gives the private helper a GET attribute: private +methods are not MVC actions and cannot offset an extra Send. This regression +fails before the public-method filter and passes afterward. A fresh GPT-6.1-sol +xhigh reviewer approves `6b8e743`: clean production GET/HEAD pass, ordinary and +decorated private sends fail, and removing only IsPublic in a temporary assembly +restores the decorated bypass. No actionable correction remains. The final clean +Release build has zero warnings/errors and all 195 architecture cases pass with +zero failures/skips. Step 2 and both independent review rounds are complete; +Education implementation proceeds in Step 3. + +### P02d-4 Step 3: public Education reads + +**Implementation — 2026-10-04; both review rounds complete.** Education serves all three +GET/HEAD pairs through marked audit-Off queries and the read-only pipeline. The +source store intersects immutable host scope with normal EF filters and RLS. +Published/nondeleted exact-locale marketing is separate from public-parent +inventory/body eligibility; the body SELECT requires its eligible public parent +and exact URL relationship in the same SQL statement. Restricted courses retain +marketing with a null outline; hidden content has the same masked not_found. + +Purpose-built DTOs expose ordered string fields and authored label locales only. +Customization carries admitted `required` metadata through the internal display +contract; no read evaluates a JSON Schema. Optional missing fields are omitted, +unknown properties are omitted and malformed selected/required content yields a +whole unavailable state. Missing exact pins/bands remain bounded without rebinding. +Enabled content locales are exact, while display fallback remains Pattern B. + +The bounded v1 cursor codec checks canonical unpadded base64url, exact JSON members, +version, lower-case scope/UUIDs and UTC microsecond timestamps or nonnegative sort. +Scope binds normalized host digest, host tenant/organization, canonical locale and +endpoint/order; page size is excluded. Syntax/known-scope checks precede the data +transaction; an outline's parent is checked after eligible course lookup and before +inventory/definition loading. PostgreSQL tuple seeks preserve timestamp/sort ties. + +A new no-schema-evaluation architecture guard inspects all four public handlers +and follows production helpers/implementations, with direct, concrete and generic +interface offenders plus a clean control. Controller guards retain all previous +planted bypasses. The persistence walk distinguishes a value object's declared +identifier interface from acquisition of an injected identifier-interface service; +clean metadata, direct domain-ID and hidden service implementations are controls. +Approved read methods are explicitly enumerated in the aggregate-write census; +key-only writes remain visible. The route census covers all eight GET/HEAD actions. + +HTTP/database cases cover exact locale and alternate URL pairs, nullable values, +source lifecycle withdrawal after warmed definition reads, hidden draft/restricted/ +foreign/sibling/wrong-parent content, body/definition corruption, cursor boundaries, +claim/host narrowing, scope hatches, transaction admission and no normal audit rows. +Fixture mutations assert affected rows and announce their explicit write scope; +owner-only satellite corruption is setup, never the observed public connection. +Public execution is proved as non-superuser/non-BYPASSRLS learnstack_app, READ ONLY. + +**Local measurement.** The actual production SELECTs are captured and explained +with ANALYZE/BUFFERS as the application role, without forcing indexes. The tiny +seed uses the course live-key and translation indexes; both outline and body plans +also use `ix_lessons_tenant_id_course_id_sort_id`. The catalog ordered partial index +is available but not selected at this cardinality; no representative large-data or +production p95 claim is made. Captured catalog/marketing/outline queries fetch no +lesson body, and the body query includes access/publication/scope/locale predicates. + +A local Docker sample records a first HTTP request, one warmup and ten observations +per Education route and tenant. Catalog/course/lesson warm medians in one run are +4.16/6.57/6.17 ms for English and 7.65/7.70/7.18 ms for Yoga. Payloads are respectively +551/415/479 and 733/504/662 UTF-8 bytes. Full plans and timing ranges are test output; +these six local medians are neither a production p95 nor a rendering budget proof. +OpenAPI snapshot, SDK/drift and required-check activation remain Step 4. + +**Pre-review verification.** The final clean CI=true Release build has zero +warnings/errors. All 2831 .NET cases pass with zero failures/skips: 1643 unit, +198 architecture, one contract, 171 Docker-free integration and 818 Docker +integration. The final architecture run follows the production-census control; +TRX counters preserve all five suite results. Disabling only transitive helper +walking or implementation walking makes the new planted guard controls fail; +both deliberately broken variants are restored before the final clean run. +Formatting verifies zero changed files and diff hygiene passes. The link/anchor +sweep and unchanged P02d-1–3 delivery records/ADR-0052 prefix are verified. +Both independent review rounds follow this implementation commit. + +**Round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers inspect +`b1bff6f..b5c3be2`. The security pass finds no additional isolation, eligibility +or cache issue. The protocol pass finds a malformed-Unicode cursor exception: +JSON strings materialize lazily, outside the original parse exception boundary. +A compiled production probe independently reproduces the unexpected exception. +The fix strictly decodes UTF-8 and refuses escaped-surrogate materialization +failures in both codecs. Unit and real GET/HEAD cases prove bounded 400 before +data access, including property-name corruption and a valid escaped-string control. +The review's coverage limits are closed too: masked 404 fields are checked in +full, and real database cases prove deleted-anchor continuation and current-row +restart for both catalog and outline. The clean Release build and 33 protocol, +198 architecture and 81 Education database/HTTP cases pass with zero skips. +Formatting and diff hygiene pass; a fresh second review follows the fix commit. + +**Round 2 and step closeout.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers +independently approve `b1bff6f..6c09888`, including the Unicode refusal fix and +stronger HTTP/pagination proofs. Both run the 45 protocol/display unit cases; +the protocol reviewer also runs 13 public-surface/aggregate-write architecture +cases. All pass with zero failures/skips; neither reviewer mutates files. No +verified finding remains. Step 3 is complete after both review rounds; Step 4 +continues with the approved OpenAPI, SDK and CI contract. + +### P02d-4 Step 4: contract, SDK and CI + +**Complete — 2026-10-04; PR #25 awaits maintainer review and merge.** +The production +OpenAPI transformer documents manually parsed locale/cursor/page parameters, +shared Problem Details, closed enums and bodyless HEAD. The sole committed v1 +snapshot matches the actual production composition. Contract controls assert all +four paths/eight operations, exact status/query inventories, required public fields, +recursive schema/CLR leaves and complete error shape. Planted missing operations, +parameters/statuses, reordered arrays and nested private/raw fields fail. + +The SDK root exports generated types only; `/server` implements four generated +GET contracts through an injected transport. Encoded paths/queries, no authority +options, allowlisted success shapes and validated Problem Details have fake +transport controls. API errors project into Standards 09's closed AppError union; +unknown extensions are ignored. Malformed JSON, invalid response shape, transport +failure and caller cancellation remain separate. The unused client export is gone. +P02d-5 still owns the configured trusted server adapter and first consumer. + +The always-running `openapi diff` workflow installs checksum-verified oasdiff and +uses the explicit severity policy. Sixty mutation/control fixtures cover +representable ADR-0024 rows and verified placement/type-direction tool gaps. +A deterministic companion traverses reachable request/response schemas and local +object/schema references. It enforces type changes, closed enum additions and +open enum closure/removal, normalizing only matching open enum lists. A combined +open addition plus another breaking change still fails. Current public enums stay +closed; this does not claim an open-enum generator/consumer has shipped. + +PR base SHA, push-before SHA and explicit manual base ref select verified git +snapshots. Missing/deleted heads or failed ref/read/proof fail. Only an actual +operation-free base production composition with no snapshot permits bootstrap; +the verified phase-entry base was built and served with zero v1 operations. Eight +snapshot-admission controls accompany this proof. Artifacts retain original and +normalized specs, refs/hashes, pinned tool/policy and readable/machine reports. +Required frontend CI regenerates the committed SDK and refuses scoped drift. +The approved live sixth check is applied only after the real job runs; no settings +mutation is claimed by this implementation note. + +**Full-suite fixture correction.** The first complete Docker run exposes test +host lifetime leakage: disposed clients retain child hosts and their independent +Npgsql pools until collection teardown. PostgreSQL reports SQLSTATE 53300, and a +new three-client control observes connections rising from one to four. Client +ownership now disposes the private child host and pool too. This changes the test +harness, not the production read contract; targeted and complete regression +results are recorded after execution. + + +**Pre-review verification.** Clean CI=true Release build: zero warnings/errors. +All 2843 .NET cases pass with zero failures/skips: 1644 unit, 198 architecture, +four contract, 171 Docker-free integration and 826 Docker integration. The new +client-lifetime control fails against the original fixture (four connections +instead of one), and passes after host ownership; the combined 102 public HTTP +cases and full Docker run pass. Frontend typecheck/lint/build and all 66 Vitest +cases pass (53 SDK, 13 web). Twenty-three real pinned-tool policy controls and +eight snapshot-admission controls pass. The actual base Program bootstrap has +zero v1 operations. Formatting, actionlint, diff hygiene and changed-document +links/anchors pass. Served snapshot and generated SDK are refreshed from the +current production composition. Both independent review rounds follow this +implementation commit; live check registration follows the real CI job. + +**Round 1 and verified fixes.** Independent GPT-6-astra and GPT-6.1-sol xhigh +reviewers inspect `5d72c2f..5f49f62`. They reproduce three Major contract/policy +findings and two Minor SDK/documentation findings; no Blocker. Actual pinned CLI +probes show root closed-enum additions, referenced open-enum closure and numeric +type changes passing the original gate. The companion now enforces these ADR-0024 +rules in both request and response positions, including local object references; +nine added controls cover root, array, reference and request/type directions. +All 32 pinned-tool controls pass (22 breaking, ten nonbreaking), alongside eight +snapshot-admission controls. The original root-enum reproduction now fails the +policy even though the underlying tool still reports no break. + +Problem Details parameter values now match the existing string-valued +`LocalizedMessage` carrier in served OpenAPI, snapshot, generated types and SDK +parsing. Contract controls compare the nested schema with CLR and actual factory +serialization; empty/number/object schemas fail. SDK controls refuse numeric, +object and null parameters. Lazy URL construction keeps ill-formed surrogate +paths within an `invalid-request` result; already-aborted calls stay `cancelled` +without transport. The sibling frontend standard no longer treats G31 as open. + +The complete .NET suite is repeated: all 2843 cases pass with zero failures/skips +(1644 unit, 198 architecture, four contract, 997 integration, including 826 Docker +cases). SDK typecheck/lint and all 58 cases pass. These fixes change the +schema/SDK/policy, not database read behavior. +Fresh Round 2 review follows the fix commit. + +**Round 2 and verified fixes.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers +inspect `5d72c2f..db9bab6`, independently rerunning 32 policy controls, eight snapshot +controls, 58 SDK and four contract cases; the SDK reviewer also runs the client +disposal control. All pass, but review reproduces three additional policy defects +and two Minor SDK/test gaps. Per-occurrence local reference materialization and +immutable analysis now prevent an open enum normalization from erasing a closed +consumer; both object-key orders have controls. Effective operation parameters +honor inheritance/overrides and the CLI explicitly flattens parameters. Parameter +and header schema/content forms are mirrored into temporary policy-only bodies +with source-location metadata, so the pinned tool checks their fields/validators. +The runtime snapshot is unchanged by this comparison normalization. + +The shared-owner reproduction now refuses even where the raw tool already reports +the break. Inherited tightening/removal/requiredness and relocated type changes +refuse; equivalent relocation remains compatible. Content-form property removal +and request-validator tightening refuse. A response minimum-length increase is +kept as a compatible stronger output guarantee, rather than misclassified as an +input rejection. Fifty real CLI controls pass (36 breaking, fourteen nonbreaking) +with eight snapshot controls. The SDK refuses exact dot segments before dispatch; +all 60 SDK cases/typecheck/lint pass. Added method and path mutants fail the +eight-operation contract control; all four contract cases pass with zero skips. +A fresh focused review verifies these final policy/SDK corrections before closeout. + +**Focused verification and recursive fix.** A fresh GPT-6-astra xhigh reviewer +independently verifies all 50 controls, eight snapshot cases, 60 SDK cases and +four contract cases. It confirms the earlier bypasses are closed, then reproduces +a recursive open-enum addition wrongly refused at an untouched component cycle +edge. Recursive edges now point to private effective schema copies, identified by +stable declaration locations so documentation changes do not alter identity. +Analysis/normalization reach these cycle copies while preserving closed consumers. +Six added controls cover open addition, unchanged recursion, documentation edits +and mixed open/closed schemas in both orders. All 56 real CLI controls pass +(39 breaking, seventeen compatible), with all eight snapshot controls. + +**Final recursive verification fix.** A fresh GPT-6-astra xhigh reviewer verifies +all 56 controls and 27 additional probes, then reproduces an unchanged inline +recursive schema crashing the normalizer. The same occurs inside a Response +component. Stable declaration identity now applies to every local schema location, +rather than only Schema components; four added real CLI controls cover unchanged +and open-addition cases in both placements. Fresh independent verification at +`ef5c4d8` approves: all 60 real CLI controls pass (39 breaking, 21 compatible), all +eight snapshot cases and 27 additional probes pass, and all four original +reproductions return compatible. Both Step 4 review rounds and focused fix review +are complete. No verified finding remains. + +**Pre-PR closeout.** All four implementation steps and their two independent +review rounds are complete on development. Final frontend validation passes +typecheck, lint, build and all 73 cases (60 SDK, thirteen web). Complete .NET +regression remains 2843 passed, zero failed/skipped, as recorded above; the later +compatibility fixes change scripts/fixtures only, and the final operation mutants +pass all four contract cases. Formatting, actionlint, link/anchor and frozen-record +checks pass. Live CI and sixth required-check API read-back follow PR creation; +packet exit is not yet claimed. P02d-5 is next, with its decision pass not started. + +**Live CI and approved check rollout — 2026-10-04.** +[PR #25](https://github.com/HodeTech/LearnStack/pull/25) opens from development to +main. At head `0a14c7474f7cb383a789adf1966d28e67dbc3954`, all six jobs pass in +[the real PR run](https://github.com/HodeTech/LearnStack/actions/runs/37188555958): +backend, Docker integration, frontend, meta, secret scan and `openapi diff`. +Lighthouse is the sole deferred job, owned by P02d-6/G44. Backend TRX artifacts +confirm 2017 Docker-free cases and 826 Docker cases, with zero failures/skips. +The Linux OpenAPI artifact confirms pinned oasdiff 1.33.0, all 60 controls +(39 breaking, 21 compatible), verified base +`d1a47369d82f8b6d91cb325f56d4c42382ec77b6` and actual operation-free baseline +composition; the comparison passes. + +After that successful `openapi diff` job, the approved PATCH adds only its GitHub +Actions context (`app_id=15368`). Fresh full protection read-back proves the five +existing contexts remain, all six have Actions attribution, strict up-to-date +checking remains true, and every other protection field is identical. This includes +zero required approvals and admin enforcement off under the existing maintainer +deferral; no unrelated protection is changed. +[CONTRIBUTING](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) owns +the current list. All six live contexts match the successful PR check rollup. + +P02d-4 implementation and rollout are complete; maintainer review/merge remains. +The final documentation commit reruns the same six jobs before handoff. P02d-5 +owns the next decision pass, trusted server transport and first consumer. P02d-6 +owns pages/rendering; P02d-7 owns the two-host demonstration and full-stack exit. +No browser delivery, marketplace commerce or production p95 is claimed. + +**Final external documentation review.** All six required jobs also pass at +`ddc96a566cd5babf2af3779314471aac33642b95` in +[the final documentation run](https://github.com/HodeTech/LearnStack/actions/runs/37189085766). +CodeRabbit then reports three Minor documentation comments. Current code confirms +cursor/bootstrap delivery and implemented endpoint/write-refusal controls; the +standards now reflect them. ADR-0040 Amendment 9 adds dated frame-delivery evidence +without rewriting its acceptance-time status. The catalogue identifies the table +parser’s actual limit: row method cells remain manual, while the separate endpoint +census mechanically enforces exact GET/HEAD. No production code changes. + +**External review remediation — 2026-10-05.** Findings against `1d938388` are +verified against current code. ADR-0036 Amendment 9 and ADR-0050/0051 Amendment 3 +record delivered provenance, access enforcement and presentation. ADR-0052 +Amendment 12 adds current-delivery navigation. All acceptance statements and +earlier amendments remain unchanged; dated Status disclosures identify them as +history. Browser rendering and authenticated grants retain their named owners. + +Unavailable catalog levels now emit one count-only Warning per summary batch, +rather than one per row. A 100-row regression proves the bound and absence of +private diagnostic fields. The nullable-default refusal remains defensive: +a broken reader contract is refused, as a focused unit case demonstrates. +Cleanup proofs now inspect a fresh live writable transaction on the same +connection after both pre/post-activation setup faults, while the poisoned unit +still refuses another frame. Injected Npgsql logging uses the shared application +data-source guard; direct and transitive bypass-role cases exercise its logged +overload with restored-role positive control. + +The suggested common provenance refactor introduces no correctness fix and is +not bundled. The Education spec explicitly records the controller/helper guard's +scope and independent handler-connection residual risk already accepted by +ADR-0052; current handlers use their approved read ports. The pre-existing +membership-reader DI backstop is outside this PR, rather than a P02d-4 defect; +production still registers the deny-all reader. + +Local verification: clean Release build with zero warnings/errors, format and +link/anchor checks pass. Full .NET regression is **2847 passed, zero failed or +skipped**: 1646 unit, 198 architecture, four contract and 999 integration. The +four added cases are two display/configuration facts and two logged role-guard +theory cases. Contract tests again verify the production-served v1 document; +the committed OpenAPI/SDK contract is unchanged. Live main protection still +requires all six Actions contexts with strict checking; no settings are changed. + +**Remediation review closeout.** Two fresh independent rounds review +`1d938388..ef86f64`: Round 1 code and documentation reviewers both Approve; +Round 2 code and documentation reviewers both Approve. No actionable finding +remains. Both documentation reviewers independently verify preserved ADR history, +delivery claims, phase ownership and all 590 relative links/anchors in the six +changed Markdown files. The complete local regression above verifies the code +fix; this closeout adds delivery evidence only. + +### P02d-4 merge and closeout (2026-10-08) + +The maintainer merged [PR #25](https://github.com/HodeTech/LearnStack/pull/25) at +2026-10-08 15:25:18 UTC. GitHub records final PR head +`f8adb110ff7fca2a15bbd3f87c1546c62852dc4c` and merge commit +`b83175538cf6f9c5415294a8f77dadd9c82588dd`. The merge's second parent is that +head, and both commits have the identical tree. Development remains the working +branch; the fetched main ref verifies the merge without changing branches. + +- All six required checks pass on the + [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37794924088). + Downloaded TRX artifacts confirm **2847 passed, zero failed or skipped**: + 1646 unit, 198 architecture, four contract, 171 Docker-free integration and + 828 Docker integration. Frontend CI passes typecheck, lint, build, SDK drift + verification and **73 tests** (60 SDK, thirteen web). +- All six required checks also pass in the + [merge-commit run](https://github.com/HodeTech/LearnStack/actions/runs/37800631591). + Independently downloaded merge-run TRX confirms the same 2847 passing cases + and zero failures/skips. Its OpenAPI artifact matches the merge SHA and + snapshot hash. Read-only protection verification confirms all six Actions + contexts with `app_id=15368` and `strict: true`; no setting is changed. +- OpenAPI artifacts match the final head, verified base and committed snapshot + hash. All **60 policy controls** pass (39 breaking, 21 compatible). The final + workflow correction adds six actual-event selection controls to the eight + admission/bootstrap controls: **14 Python tests** pass locally and in CI. + Four local selector mutants fail. Zero-before pushes select the head's parent; + ordinary push, PR and manual refs retain their existing contracts. +- The final review corrections retain unchanged ADR decisions and align delivery + navigation. Two fresh focused reviewers approve each final follow-up + (`7e07613..7ad4b91` and `7ad4b91..f8adb11`). CodeRabbit succeeds at the final + head; all five inline threads are resolved. The four implementation steps' + two-round review records above remain unchanged. + +**P02d-4 is closed.** Host-scoped anonymous site/catalog/course/lesson GET/HEAD, +physical read-only frames, exact enabled-locale/access eligibility, bounded public +projections and cursors, the served OpenAPI baseline, typed SDK and compatibility +gate are delivered. No database migration is added by P02d-4. + +**Next: P02d-5 — Server-rendering path.** Its implementation and decision pass +have not started. The [packet gate table](phase-02d-walking-skeleton.md#packets-and-decision-gates) owns its +complete prerequisites; the [decision register](phase-02d-walking-skeleton.md#the-decision-register) still +leaves development transport/hosts, trusted-hop topology and rate limiting, +server SDK transport, middleware/locale entry, rendering/cache policy and the +frontend test/skip fence open. P02d-4 supplies the completed API prerequisite; +it does not accept those later decisions. + +P02d-6 owns the three public pages, text-card renderer, safe theme injection, +language attributes and accessibility. P02d-7 owns `make demo`, the two-host +full-stack evidence and phase exit. G44 retains the Lighthouse activation +decision. Phase 02d remains in progress; no browser delivery, authenticated +learner grants or Course Marketplace commerce is claimed by this closeout. + +**Documentation-only closeout validation.** Five local corpus-consistency tests +pass with zero failures/skips. The seven changed Markdown files pass the local +relative-link/fragment audit (825 link occurrences, 342 fragments), added-prose +width and diff checks. ADR-0052 changes are insertion-only; previous P02d-4 +delivery notes and the P02d-1 suffix remain byte-identical. No production code +changes or new decisions are introduced. + +## P02d-5 — Server-rendering path + +### P02d-5 decision package (2026-10-08) + +**Accepted — 2026-10-08, verified against development `88f52c4`.** The maintainer +approved ADR-0053 and this package before implementation. P02d-4 is merged; +[ADR-0053](../decisions/0053-trusted-public-server-rendering.md) owns the bounded +replacement rules. Only the named P5 gate parts below close; delivery remains +separate from acceptance. + +#### Baseline and document review + +The preparation baseline is development `88f52c4`. Three independent read-only +reviews cover trust/topology/limiting, frontend/runtime semantics and governance. +Their conclusions are checked against source, not accepted as instructions. + +- P02d-4 supplies bootstrap, Education GET/HEAD, public DTOs, READ ONLY, no-store, + cursors, a served snapshot, typed injected SDK and required diff/drift checks. +- SDK Vitest tests and AppError parsing are already delivered. G38(a)'s older + missing-script premise and G35's implied missing parser are historical premises. +- Middleware still forwards client headers, writes host into `x-tenant-id`, invents + `en` and refuses production requests with `503`; no configured caller exists. +- Installed Next 15.5.18 preserves a supplied `x-forwarded-for` when adding socket + metadata. Middleware cannot turn it into reliable visitor identity. +- API limiting is 60 calls/minute per socket peer. Forwarded-header middleware is + unwired; reading the connection feature alone does not protect a mutated peer. +- API startup permits both hop lists empty in every mode, refuses partial lists, + invalid CIDRs and blank/secrets shorter than 32 characters. ADR-0053 explicitly + adopts that policy in place of ADR-0036's older non-Development/byte wording; + a dated ADR-0036 Amendment discloses it without rewriting the Accepted body. +- Standards 07's delivered injected SDK contradicts ADR-0036's older exact file + chosen to set hop headers. The new decision must disclose its replacement. +- Standards 07 and Architecture 14 still prescribe cached public rendering under + open G37; a changed ongoing rule requires an ADR, not a quiet code exemption. +- The route skill's obsolete P4 stub description is corrected during preparation. + Frozen P1–P4 delivery records and Accepted ADR bodies remain unchanged. + +The reviewed carrier families are CLAUDE/README, vision/MVP, roadmap timing and this +phase; ADR-0009/0035/0036/0040/0050/0051/0052 and the ADR index; architecture +09/12/14/30; standards 03/04/06/07/08/09/10/11/12/13/15/16/20/21; the route, +local-dev, seed and test workflows; current API/SDK/web/compose/CI source. Future +renderer decisions G39–43 are inputs, not accepted by this package. + +#### P02d-5 accepted answers + +| Gate part | Accepted answer and authority | +|---|---| +| G6(c) | Canonical enabled locale prefixes; `308` for enabled noncanonical spelling, `307` for default-locale entry, masked `404` for malformed/disabled/unknown prefixes. Exact matrix below | +| G20: exemptions | Demo identity literals only in `SeedData`, seed/development launch/configuration, operational docs and test-owned assertions/fixtures. No host/domain-specific branch in middleware, transport, renderer or modules; a generic host normalizer is not a demo exemption. P6 decides renderer subjects, P7 implements the complete Registered guard | +| G21: cookies | Public entry neither sets nor uses cookies; no Authorization/session forwarding. Preserve P2's no new remote subresource contract. Phase 02b owns session cookies; Secure-cookie TLS proof here is a test-owned transport control, not authentication implementation | +| G30: headers | Native ingress verifies captured host/peer provenance; middleware rebuilds private context; one configured server adapter emits the closed API-hop set in ADR-0053. Education locale is query-only; no tenant/organization assertions | +| G32 | [Accepted — 2026-10-08](#local-setup-and-ingress-details): local hosts and TLS | +| G33 | [Accepted — 2026-10-08](#local-setup-and-ingress-details): local topology, shared source and ingress | +| G34 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#api-hop-and-anonymous-budgets): authenticated visitor and peer budgets | +| G35 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#configured-caller-and-rendering): configured caller/deadlines; [Frontend Observability](../standards/10-observability.md#frontend-observability) owns Phase 11 logger/Sentry/web-vitals | +| G36 | [Accepted — 2026-10-08](#public-entry-matrix): membership-first entry and redirects | +| G37 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#configured-caller-and-rendering): dynamic no-store renderer policy | +| G38(a) | Vitest covers normalization/stamps/header stripping, locale/entry matrix, configured origin/header construction, errors, deadlines/body/cancellation and tracing; production-build/socket fixtures cover runtime boundaries. SDK tests remain inherited | +| G38(d) | Extend existing non-skippability rule to tested frontend workspaces. Fail skipped/todo, empty/unreadable reports and discovered test packages without an execution script; planted actual runner cases prove failure | +| G44: whether | Activate full-stack Lighthouse in P02d-7, after P6 pages and G45's shared demo harness. P5 updates live deferred-job ownership carriers; it does not audit placeholders. P7 still selects tools, URLs, assertions/budgets and status promotions before harness code | + +This acceptance closes only the named P5 parts. G38(b,c), G39–43, G44's harness +details and G45 remain with P6/P7. No market, auth, CMS, media or grant decision moves. + +#### Local setup and ingress details + +Keep the two hosts already declared in `SeedData`; do not create a second hardcoded +host registry in production code. The explicit workstation step adds those names +to `127.0.0.1` in the hosts file and creates a leaf certificate with their exact SANs +and `localhost` for readiness. The documented tool is mkcert (BSD-3-Clause); its CA +trust/install step is performed explicitly by the developer. No script edits hosts, +installs system trust, ignores TLS errors or shares the CA private key. Leaf/key +paths live under gitignored `.data/`; examples contain paths, never key material. + +The ingress owns port 3000 on IPv4 loopback and delegates requests/upgrades to Next's +supported custom-server interface. It strips inbound forwarding/internal/framework +override headers before minting the single provenance envelope specified by +[ADR-0053](../decisions/0053-trusted-public-server-rendering.md#ingress-and-provenance). +Middleware verifies it before bootstrap, rebuilds downstream request headers from +the allowlist, and the server caller verifies it again before SDK use. Direct stock +`next dev/start` is unsupported and must fail closed if callers forge plain carriers; +a valid production-build control proves the supported launcher actually works. + +One ignored local source provides a freshly generated 32-byte random ASCII-encoded +hop secret to both processes. API networks and secret list arrive together through +launch configuration; do not commit a network-only Development default. The native +launcher/Next caller use the same private source for domain-separated ingress MACs. +`.env.example` owns the variable vocabulary; the web example documents its narrow +projection and matching/conflict checks. The loader must not shell-evaluate env +values or echo credentials. Empty/malformed renderer configuration refuses startup; +ordinary no-hop API startup and existing Development fixtures continue to work. + +P5 tests use isolated certificates and trusted test roots, never disabled certificate +verification. Browser TLS/Secure-cookie checks are evidence to obtain, not claims +already proved on this workstation. P7's CI harness uses isolated per-run roots, +host resolution and secrets; it never installs a permanent developer CA. + +#### Public entry matrix + +The fixed public section name is `courses`; section-name localization remains +Phase 06. After bootstrap, enabled-locale membership takes precedence over every +shorthand or scaffold name. No locale is rejected just because its grammar-valid +name is `courses`, `studio` or `portal`. +For a well-formed request, bootstrap runs before locale/redirect decisions. Unknown +or platform host, unavailable live scope and valid empty locale configuration return +masked `404`. Dependency/invalid stored configuration or transport failure returns +bounded `503`; API `429` remains `429` with validated Retry-After. No body embeds +provider errors, host IDs or internal headers. P6 owns localized page-state rendering. + +| Input on a bootstrapped live host | Answer | +|---|---| +| `/` | `307` to `/{defaultLocale}/courses` | +| `/courses`, `/courses/{slug}`, `/courses/{slug}/lessons/{lessonSlug}`, when `courses` is not an enabled locale | `307` to the same path with the configured default prefix | +| `/{enabledCanonicalLocale}` or its one trailing slash | `307` to `/{locale}/courses` | +| Enabled noncanonical locale prefix on a supported public path | `308` to its canonical prefix; only after enabled membership succeeds | +| Canonical enabled prefix on a supported public content path | Continue with verified host/peer and canonical route locale; P6 supplies pages | +| Exact current `/studio` or `/portal` scaffold root on a live host, when that name is not an enabled locale | Continue to the existing scaffold without a public locale or authentication claim; no prefix-wide exemption | +| Malformed, disabled, unknown or overlength locale prefix; unknown section/path | Masked `404`, no fallback and no content request | +| Malformed/missing Host, socket provenance or ingress signature | Refuse before bootstrap; never use a forwarded/default host | + +Locale parsing matches the shipped LocaleTag grammar, canonicalization and +35-character bound without trimming. First validate/canonicalize the first segment +and check enabled membership; only on a nonmember consider the exact scaffold +roots or the `courses` shorthand. Otherwise it is an unsupported/malformed prefix, +so `en_US` never becomes a default-locale resource path. Percent-encoded locale +prefixes are refused rather than decoded into another locale identity. No +`Accept-Language`, cookie or `?locale=` overrides the path. Explicit query locale on +Education calls always comes from that path. + +When `courses` is enabled, `/courses` is its locale root and `/courses/courses` its +catalog; `/courses/{slug}` shorthand is intentionally unavailable on that host. +Its full localized `/{locale}/courses/{slug}` path remains available. Default and +nondefault `courses`/`studio`/`portal` fixtures must prove terminal redirects and +normal localized admission. P6/Phase 02b's future static/auth routes must preserve +these public paths rather than shadow them; those packets own their distinct UI +namespaces. No known-locale registry or locale-writer restriction is introduced. + +Redirects use the successfully bootstrapped normalized visitor host with the +configured HTTPS scheme/ingress port and a local computed path. They never use +`request.url`'s possibly substituted origin, forwarding headers or a query redirect +target. Preserve query bytes as inert query data; bound/validate request targets, +reject authority/encoded separator or traversal ambiguities and test those cases. +Disable implicit pre-middleware slash/URL redirects where they bypass this policy. +Every tenant-bearing redirect/refusal is no-store; no cookies are emitted. + +The matcher excludes Next assets/HMR, exact `/api/healthz` and favicon. It does not +exclude `studio`/`portal` prefixes: enabled locale paths need normal admission. +Health remains live without a tenant bootstrap; native ingress sanitation still +applies. The exact scaffold-root continuation above requires successful live-host +bootstrap and grants no API or authentication authority. Platform/unknown hosts +still receive `404`. Future BFF/auth routes require their own Phase 02b contract; +P6/G40 decides the product behavior of the remaining scaffold screens. + +**P02d-6 entry extension — Accepted 2026-10-09.** In addition to the delivered +P5 matrix above, exact `/{enabledCanonicalLocale}/status/not-found` continues +through live admission with middleware HTTP `404`. Noncanonical enabled prefixes +canonicalize under the same rule; sibling/extra status segments remain masked +`404`. This status route carries no Education authorization. P6's decision package +owns the original content request's 307→404 navigation chain. Implementation is +not claimed by this acceptance note. + +#### P02d-5 implementation plan + +The first commit accepts this package and ADR-0053, records the bounded ADR-0036 +replacement/navigation and updates the ongoing carriers below. +Then every implementation step is committed, reviewed by fresh agents twice, and +each confirmed correction is validated/committed before the next step. + +1. **Native ingress and local topology.** Implement the mandatory launcher, private + configuration/stamp protocol, TLS path/readiness, fixed loopback bindings and + shared-source launch recipe. Update web scripts/config, environment examples, + README/local-dev/seed workflows. Prove missing/forged/bypassed ingress refusal, + valid production-build startup, no-env API startup, TLS and secret containment. +2. **API visitor admission and budgets.** Add strict trusted visitor metadata, + canonical IP partitioning, peer ceiling and pre-lookup refusal. Keep network + plus secret checks and forwarded-header ban. Add actual socket and HTTP/Postgres + positive/negative/flood controls as `learnstack_app`, preserving no-store/DTOs. +3. **Configured caller and public entry.** Implement the single server-only + transport, narrowly scoped fetch-lint exemption, Node middleware/bootstrap, + locale matrix, origin-safe redirects and dynamic/no-store policy. Prove slow + bodies, decoded-size bounds, cancellation, redirect secret containment, + trace-ID agreement and every + malformed/disabled/noncanonical entry case with a non-English default. +4. **Mechanical frontend fences and closeout.** Enforce server/cache/header + boundaries and frontend skip/todo refusal with clean/planted controls. Complete + production-build integration evidence, update all current carriers, run relevant + suites and both final reviews; open the P5 PR for maintainer review. + +P5 production-build fixtures use test-owned routes importing the real ingress, +middleware and caller against the real public API; no diagnostic route enters the +shipped app. Entry/bootstrap runtime evidence is distinct from P6's catalog/course/ +lesson UI and P7's two-host browser demo. Where a phase-level criterion requires +those pages, its evidence owner stays P6/P7; P5 cannot mark it complete with a fake +transport. API-only proofs remain named separately. + +#### Acceptance carriers and validation + +Acceptance updates ongoing rules; delivery updates each owner with its enforcing +implementation: + +- ADR index and current packet register/navigation; append-only ADR-0036 note for + the bounded limiter/setter replacements and mode-independent startup policy. + Name it a dated Amendment under ADR-0041/Standards 13, with source/history evidence + and carrier disclosure; the new ADR owns changed rules, not an in-place correction. +- Standards 04/11 rate limits; 07/15 dynamic rendering/caller; 08 path entry; 10 and + Phase 11 frontend observability ownership; Architecture 09/12/14/30 as applicable. +- Existing Standards 21 hop/peer/non-skippability entries, plus Registered proof + names only when selected; claims become Implemented with actual enforcing tests. +- Route/local-dev/seed/test skills; root/web environment examples; web scripts, + Next configuration, README Quickstart and Makefile launch help where introduced. +- Phase 02b G12/G14 re-verification handoff; Phase 06 redirect/cache inheritance; + CI/CONTRIBUTING/test-skill Lighthouse ownership explicitly P02d-7/G44. Historical + shipped records are not rewritten to disguise the transition. + +Validation includes Release/format, architecture/unit/contract and relevant Docker +integration suites; all frontend workspace typecheck/lint/build/tests and SDK drift; +real production-build/socket/TLS cases; actual skip/todo/import/cache mutants; changed +Markdown relative links/anchors, width/residual checks and ADR-history preservation. +No test count, browser observation or CI success is claimed until it is run. + +**Preparation verification — 2026-10-08.** Two fresh proposal-review rounds +checked security/runtime and corpus/decision completeness. The confirmed locale +name collision was corrected with membership-first entry; both second-round +reviewers approve the revised proposal. Two fresh focused reviewers also approve +the external-review corrections to secret cardinality, provenance carriers and +Amendment/standard ownership. The existing `CorpusConsistencyTests` pass 5/5, +with zero failures/skips. The six preparation files have 683 relative link +occurrences and 321 fragment targets, all resolving; added prose wrapping, +`git diff --check` and Accepted-ADR/historical-body preservation checks pass. +These are document-preparation results, not P5 implementation or browser evidence. + +#### Approval boundary + +The maintainer approved the exact ADR/package on 2026-10-08: the native custom +launcher, existing names with manual local TLS, dynamic public rendering and the +explicit 60/IP plus 600/peer API budgets. Automatic trust-store modification is not +authorized. Implementation now proceeds on development through the four steps and +two fresh review rounds per step; acceptance alone marks no delivery criterion done. + +### P02d-5 delivery record + +#### P02d-5 Step 1 — Native ingress and local topology + +**Implementation delivered — 2026-10-08; review rounds pending.** The mandatory +native Node launcher binds HTTPS to `127.0.0.1:3000`, validates the private source +and delegates requests/upgrades to Next 15.5.18. It captures the real socket peer, +canonicalizes IP identities, validates exactly one Host and bounded request target, +strips incoming private/forwarding/framework carriers, then mints the HMAC envelope. +Verification binds host, peer, method and raw target and refuses forged/repeated or +noncanonical envelopes. No ingress code resolves tenant/organization authority. + +`make public-env` generates an ignored 32-byte random ASCII-encoded secret without +hosts/trust changes. `make public-api` supplies only runtime database credentials, +fixed loopback network and matching secret; `make public-web` and `pnpm dev/start` +use the native launcher. Root/web environment examples and README/local-dev/seed +workflows describe explicit mkcert trust, leaf creation and manual hosts aliases. +The API's ordinary no-hop startup remains unchanged. + +The old middleware's tenant-header placeholder and invented `en` fallback are +removed. Its interim Node admission returns no-store `503` after valid provenance +and masked `404` otherwise. Health/assets are excluded from tenant entry, but all +requests pass native sanitation. Step 3 replaces the interim refusal with real +bootstrap and locale entry. Next implicit URL/slash redirects and Server Component +HMR caching are disabled. P6 pages and P7's demo remain separate delivery scopes. + +**Validation.** The frontend suites pass 128 cases (60 SDK, 68 web), including 55 +ingress/config/socket cases; workspace lint, typecheck and production build pass. +The production companion verifies test-root TLS readiness, private-header stripping, +no carrier/secret in responses or retained fixture diagnostics, and stock-Next +forged-carrier refusal. Existing API hop-configuration tests pass 5/5 with zero +failures/skips, preserving empty-hop mode-independent startup. TLS controls use +isolated trusted roots and a test-only Secure-cookie response header; no browser +cookie acceptance or local CA installation is claimed. + +**Step 1 round 1 — confirmed corrections (2026-10-08).** Independent security +and quality reviewers identify two boundary failures in the committed foundation. +The production companion reproduces a valid raw query returning `404` because Next +serializes its search parameters and removes `_rsc`; it also reproduces an interior +repeated slash causing a pre-middleware redirect. The fix preserves the signed raw +target, compares only its explicit pinned-Next projection at middleware admission, +and rejects repeated pathname slashes before delegation. Ten focused cases and +production controls cover query rewriting, terminal `?`, RSC query stripping, +method/path/query substitutions and no-store refusal without an implicit redirect. +OpenSSL prerequisites and the paired/API-only restart guidance are clarified. +The corrected frontend suite passes 138 cases with zero failures/skips; +production TLS/query/bypass controls, typecheck, build, native/config lint and +changed-link/history checks pass. Second-round review remains pending. + +**Step 1 round 2 — closeout (2026-10-08).** Fresh GPT-6-astra xhigh and +GPT-6.1-sol xhigh reviewers inspect the cumulative implementation. Confirmed +corrections remove all pinned-Next internal routing/resumption/revalidation +headers at native admission and prevent Next's automatic upgrade listener from +receiving rejected inputs. The supported `httpServer` option registers that +listener on a non-listening sink; native TLS admission alone delegates upgrades. +Real production controls reject duplicate Host before Next, admit one sanitized +upgrade, and fail when the sink option is removed. An isolated development fixture +receives `101` for admitted HMR and no delegation for its rejected control. + +The companion also recognizes children already terminated by signal, observes +exit before signaling and bounds forced cleanup. Real already-exited, running and +SIGTERM-resistant controls pass. The corrected 138 frontend cases, production +TLS/query/upgrade/bypass controls, production build, typecheck and lint pass with +zero failed/skipped cases. Both reviewers approve the corrected scope; Step 1 is +complete and Step 2 follows. No workstation-browser proof or P6 page is claimed. + +#### P02d-5 Step 2 — API visitor admission and budgets + +**Implemented — 2026-10-08; independent reviews pending.** The API captures one +request-local visitor identity through the existing network-and-secret hop +predicate. Its bounded IP parser rejects abbreviated/integer IPv4, ports, lists, +zones and whitespace; IPv4-mapped IPv6 shares the direct IPv4 namespace. Unknown +peers retain one fixed fallback partition. No header selects a tenant. + +Chained fixed-window limiters apply 600 calls/minute per physical peer first, +then 60 calls/minute per canonical visitor IP, without queues. This ordering +prevents exhausted peers from creating additional visitor partitions. Missing, +malformed and repeated trusted metadata consumes fallback quota, then receives +masked `404` before host classification; untrusted forwarding metadata is ignored. +Existing `429` Problem Details and `Retry-After` remain authoritative. + +**Validation.** The 28 new identity cases and 18 existing hop/configuration cases +pass. Fifteen new real-Kestrel/PostgreSQL cases and both existing anonymous HTTP +controls pass, with zero failures/skips. Positive public reads reach the production +reader as `learnstack_app`, with READ ONLY and no superuser/BYPASSRLS privileges. +Controls cover shared direct/hop quotas, independent visitors, canonical IPv6, +rotation, repeated raw headers, novel-host bounds and both budget ceilings. +Invalid metadata and over-budget requests do not call the host resolver. The +initial API Release build passes with zero warnings/errors. Steps 3–4 remain open. + +**Step 2 round 1 — confirmed corrections (2026-10-08).** Independent +GPT-6-astra xhigh and GPT-6.1-sol xhigh reviews identify premature physical-peer +exhaustion and a quota-test oracle gap. ASP.NET retries a refused synchronous +acquisition asynchronously; re-running the peer-first fixed-window chain charges +its earlier peer permit twice. A real-Kestrel regression fails on request 331 +after 60 accepted and 270 refused calls. A request-local no-queue wrapper preserves +the first refusal and its metadata without repeating the acquisition; each +framework attempt owns a separate lease. Peer-first ordering remains unchanged. + +The corrected mixed-traffic control admits the remaining allowance through actual +request 600 and refuses 601 before lookup. Independent assertions fix the accepted +60/IP, 600/peer and one-minute values. All 18 focused HTTP controls and 47 +identity/hop/configuration cases pass with zero failures/skips. The pre-correction +full regression passed 2,890 cases but did not cover this newly reproduced boundary; +it is not evidence for the corrected head. Second-round review follows. + +**Step 2 round 2 — lifecycle correction (2026-10-08).** Fresh GPT-6-astra +xhigh and GPT-6.1-sol xhigh reviewers confirm the corrected quota behavior and +identify incomplete limiter shutdown. The framework chain does not own its child +budgets; the wrapper's asynchronous path and the options registration also lacked +ownership. DI now owns the wrapper, which disposes both budgets exactly once on +synchronous and asynchronous shutdown. Four focused lifecycle cases pass. +Both reviewers independently verify the correction, including actual provider +shutdown, completed child timers and refusal after disposal, and approve. + +The independent security probes also confirm that rotating visitor metadata after +peer exhaustion creates no further visitor partitions, while an already-cancelled +acquisition creates none. These are test-owned probes, not production telemetry. +Both review rounds are complete. The final corrected Release build has zero +warnings/errors; **2,896 backend cases** pass: 1,679 unit, 198 architecture, +four contract and 1,015 integration, with zero failures/skips. The nonempty-run +check covers all four assemblies. The two changed Markdown files pass the local +link/fragment audit (552 links, 295 fragments), added-prose width and diff checks. +Frozen P1–P4 history and Accepted ADR bodies remain unchanged. Step 2 is complete; +Steps 3–4 follow automatically under the approved plan. + +#### P02d-5 Step 3 — Configured caller and public entry + +**Complete after both review rounds — 2026-10-08.** One server-only +adapter supplies the four injected SDK GETs with private origin and a closed +authenticated hop. It re-verifies the envelope and derives locale only from the +canonical signed route. Redirects are refused; caller cancellation is distinct +from the ten-second total header/body deadline. Decoded response bytes are counted +while consuming, up to 8 MiB; oversize is a transport failure without truncation. +Cleanup does not wait indefinitely for stream cancellation or late fetches. + +Node middleware verifies before request-local live bootstrap, then applies the +accepted membership-first entry matrix. Non-English default, disabled/malformed +prefixes and default/nondefault `courses`/`studio`/`portal` locale collisions are +covered. Redirect authority comes from the bootstrapped captured host and fixed +HTTPS port, preserving signed raw query bytes. Continuation rebuilds request +headers and emits no cookie or ordinary provenance response header. The public +layout is dynamic with zero revalidation and force-no-store fetches. + +**Validation.** All **280 frontend cases** pass: 220 web and 60 SDK, zero +failures/skips. The 39 adapter controls include real loopback HTTP gzip expansion, +exact decoded size, redirect credential containment, caller cancellation and a +ten-second deadline spanning delayed headers and body. Eighty-two entry and 21 +middleware cases cover admission, raw queries, error mapping and request isolation. +Workspace lint/typecheck and the production build pass. The production TLS +companion exercises the real middleware/caller against a test-owned bootstrap +server, proving live redirects, raw-query retention and stock-Next refusal before +bootstrap. It does not replace Step 4's real-API integration or P6 pages. +The real-Kestrel/PostgreSQL trace control also passes: the API's Problem Details +uses its own span with the adapter's propagated trace identifier. The HTTP test +disables the test HttpClient's ambient trace injection so it observes the intended +wire header; the production caller itself remains unchanged. + +**Step 3 round 1 — harness failure cleanup (2026-10-08).** Independent +GPT-6-astra xhigh approves the security/runtime boundary. GPT-6.1-sol xhigh +reproduces an asynchronous fixture-listener assertion bypassing the outer cleanup, +leaving a Next child and temporary tree alive. The listener now records refusal +without printing credential values; the awaited outer flow raises the failure +where cleanup owns all resources. A source-planted wrong-path control runs the +real production harness, exits red and verifies its child and tree are gone. +The unmodified production TLS companion also passes. No API/entry policy changes. + + +**Step 3 round 2 and closeout (2026-10-08).** Fresh GPT-6-astra xhigh +approves security and runtime behavior, including both production companions and +no-store scaffold continuation. Fresh GPT-6.1-sol xhigh reproduces a test-oracle +gap: a 36-letter locale already fails primary-subtag grammar, so removing only +the 35-character guard leaves the entry suite green. Grammar-valid 35/36-character +controls now isolate the bound; the reviewer verifies all 84 cases pass and the +removed-guard mutant fails exactly the 36-character case. Production policy is +unchanged. Both independent rounds and fix verification pass; Step 4 follows. + + +#### P02d-5 Step 4 — Frontend fences and production integration + +**Implemented — 2026-10-09; independent reviews pending.** Two reserved frontend +rules now name actual Vitest assertions with a nonempty production TypeScript +census. AST analysis follows runtime imports/reexports and constant dynamic imports, +with alias/computed fetch and header, server-only, raw-authority, layout-policy and +cache controls. Request-local React cache remains allowed. Arbitrary eval, runtime +reassignment and external implementation bodies are outside the structural claim; +actual production/socket proofs remain separate. + +The root frontend runner discovers test packages from the workspace declaration, +including ones pnpm would otherwise skip. It refuses missing scripts, missing or +invalid/empty reports, failures, skipped/todo cases and omitted discovered files. +Actual isolated Vitest clean/skip/todo/missing-script/report/omission controls prove +refusal. The existing frontend CI context uses this runner and executes the native +production TLS/failed-listener cleanup companions after build. + +`PublicServerRenderingTests` compiles a disposable app with test-owned routes that +import the real ingress/middleware/caller and SDK against real Kestrel/PostgreSQL. +Both seed hosts render the same locale/slug in cold/interleaved HTML and RSC without +cross-host values. The fixture proves exact lesson projection, non-English default +redirect, stock-Next forgery refusal before any API/database bootstrap, nonempty +client asset and native/API log containment, and next-request publication freshness +in the same native process. Its real API reads use `learnstack_app`, physical READ +ONLY frames and the existing isolation observer. Only test setup mutates owner rows, +with restoration in `finally`; it is not the role used to prove isolation. + +A real Client Component import of the configured caller fails with the server-only +diagnostic; deleting that test-owned route yields a clean production build. Private +runtime configuration is supplied only after compilation. Bootstrap/page reads +share one valid trace identifier for supplied, missing and malformed incoming +contexts; the middleware creates a request-local context before either caller. +No trace or private carrier is emitted to the browser. + +Pinned Next streams RSC not-found with HTTP 200 and its exact +`NEXT_HTTP_ERROR_FALLBACK;404` digest, while the document response is 404. The +fixture requires the real API's parsed 404, the digest and absence of previous +content; other API/transport failures fail the proof. It stays below the existing +60-call visitor budget and owns only isolated ports/certificates/build trees. +Backend integration CI receives Node/pnpm and frozen frontend dependencies; no +required check name or branch-protection setting changes. + +Test-owned routes are P5 transport/runtime evidence. Public catalog/course/lesson +product UI is P6; browser demo and Lighthouse remain P7/G44/G45. This step adds no +production diagnostic route, page UX, auth, CMS or database migration. + + +**Step 4 pre-review verification (2026-10-09).** Release build has zero +warnings/errors; format verification passes. All **2,898 backend cases** pass: +1,679 unit, 198 architecture, four contract and 1,017 integration, with zero +failures/skips. Every assembly passes the nonempty-run checker and direct TRX +counter comparison. The complete guarded frontend run passes **381 cases**: +321 web and 60 SDK, zero failures/skips/todos. Workspace lint/typecheck and the +production build pass. Focused production integration also passes independently; +normal native TLS and planted listener-cleanup controls pass. Both `pnpm test` +and `make test-frontend` route through the guarded runner. SDK snapshot drift and +the final per-step review evidence are recorded below when complete. + +**Step 4 round 1 — proof repairs (2026-10-09).** Independent GPT-6-astra +xhigh runtime/security review approves the production boundary. It reruns the real +API fixture and verifies that compiled shared-result and credential-log mutants +fail their intended isolation/containment assertions; owned listeners and build +trees are cleaned on failure. GPT-6.1-sol xhigh quality/standards review identifies +three proof gaps: the missing-report control fails before reaching report parsing, +namespace aliases can hide Next caching, and destructured headers can hide raw +authority reads. Each gap is independently reproduced before repair. + +The report control now runs a successful script without a report and requires +`ENOENT`; empty and unreadable reports have separate reason assertions. Source +analysis follows namespace variable/import/reexport aliases and object-binding +headers, including a transitive barrel control. All 77 source controls and 26 +runner controls pass, and the complete guarded frontend run passes **388 cases**: +328 web and 60 SDK, with zero failures/skips/todos. Web typecheck/lint pass. Three +workflow skills now describe Accepted G25/G36/G37/G44 instead of their prior open +questions; no accepted decision or production behavior changes in these repairs. +The quality reviewer independently confirms all three fixes and passes 127 focused +source/runner/middleware cases. Both first-round reviewers approve the corrected +tree; second-round review remains pending. + +**Step 4 round 2 — source and cleanup repairs (2026-10-09).** Fresh +GPT-6-astra xhigh security/runtime and GPT-6.1-sol xhigh quality/standards reviewers +verify the current implementation independently. The confirmed source gaps are +awaited header collections, named/default/star/namespace export aliases, private +environment bindings and exported global fetch. Reused constant expressions need +path-local cycle detection, and explicit runtime exports must shadow star exports. +All original counterexamples fail before their fixes; dirty and clean controls now +separate these cases without interpreting function bodies or runtime reassignment. + +The final source suite passes **104 cases**. The quality reviewer independently +executes 28 additional in-memory controls over the production census: all 20 dirty +cases are detected and all eight clean cases are accepted. The complete guarded +frontend run passes **420 cases**: 360 web and 60 SDK, with zero failures/skips/todos. +Workspace lint/typecheck pass. Focused-test instructions use the package command; +the guarded root runner deliberately accepts no filters. Stale App Shape, SSR risk +and text-card projection status clauses are synchronized without changing decisions. + +Owned test process groups can outlive their leader, so both native fixtures share +bounded group cleanup. Only an absent group closes the proof; transient Darwin +`EPERM` counts as present, and persistent refusal fails at the deadline. Five clean +and planted cleanup cases pass. The security reviewer independently passes four +consecutive native runs, the failed-listener companion and the real-API production +rendering fact in Release with `CI=true`, with zero failures/skips. The helper's ESM +declaration uses the existing shared typed ESLint parser. No production trust rule +changes in this round. Both second-round reviewers approve the corrected tree; +Step 4's two independent rounds and fix verification are complete. + +#### P02d-5 packet closeout (2026-10-09) + +**Implementation-complete, unmerged.** All four planned steps and two fresh +independent review rounds per step are complete. Confirmed findings are repaired +and committed; no verified P5 issue or maintainer decision remains open. The native +ingress, authenticated visitor budgets, configured server caller, live locale entry, +dynamic/no-store policy and their mechanical/runtime proof surfaces are delivered. + +Local verification: + +- Release build: zero warnings/errors; format verification passes. +- All **2,898 backend cases** pass: 1,679 unit, 198 architecture, four contract and + 1,017 integration, with zero failures/skips; direct TRX counters and the nonempty + assembly checks agree. After the final cleanup repair, the independent security + reviewer reruns the real-API production rendering fact successfully. The final + architecture rerun also passes 198/198. +- The final guarded frontend run passes **420 cases**: 360 web and 60 SDK across two + tested packages, with zero failures/skips/todos. Workspace typecheck/lint, + production build and regenerated SDK snapshot drift checks pass. +- Native socket/TLS, failed-listener cleanup, actual skipped/todo/missing-report + controls and production Client Component import refusal pass. HTML/RSC separation, + eligibility freshness, trace continuity and secret containment use the real API; + they are transport evidence, not a shipped product-page or browser-demo claim. +- Manual changed-document file/fragment validation, added-prose wrapping, + `git diff --check`, strict commit messages and Accepted-ADR/P02d-1–4 history + preservation pass. CI's existing link check covers files, not fragment targets. + +These local runs use Node 22.23.1 and .NET SDK 10.0.302; they do not claim the pinned +CI Node 20.11.0/.NET SDK 10.0.112 run. The P5 PR's actual checks establish that +separate evidence before maintainer handoff. No live protection setting or required +check name changes. This packet adds no database migration or public OpenAPI/SDK +contract change. + +**Next: P02d-6 — Public renderer.** Re-verify G5/G12/G16/G20/G38/G39–G43 against +the delivered transport, then accept its page/state, text-card, theme and +accessibility contracts before implementation. P6 consumes the configured SDK and +preserves uncached rendering and live eligibility. P7 still owns `make demo`, the +two-host browser harness, Lighthouse and phase exit. Phase 02d remains in progress; +P5 does not complete the full walking skeleton or deliver authentication, CMS, +enrollment grants, commerce or production ingress/distributed quotas. + +**CI lint preflight correction (2026-10-09).** The first P5 PR run exposes a +clean-checkout dependency: native launcher lint resolves generated +`.server/ingress.js` before the later build step emits it. Existing local output +hid this ordering gap. Removing that owned output reproduces the precise import +refusal; the web lint command now compiles ingress first, then retains all lint +rules. The staged-web hook follows the same preflight. Full workspace lint passes +from absent generated output; no runtime policy or test count changes. +Two fresh GPT-6.1-sol high reviewers independently approve this narrow correction; +shell syntax, failure propagation, ignored output and staged-file isolation pass. + +**PR handoff — 2026-10-09.** +[PR #26](https://github.com/HodeTech/LearnStack/pull/26) proposes development into +main for maintainer review. Main synchronization uses a normal merge on development +and preserves the validated tree; no branch switch or history rewrite occurs. +The PR's actual required-check rollup owns pinned CI evidence separately from the +local runs above. P02d-5 remains unmerged; P6/P7 delivery is not claimed. + +**Review evidence clarification — 2026-10-09.** The Step 4 and packet-closeout +counts above describe `e580444f0dbaf11151bf008a06a75688f2bd6e4a`: 104 source cases +and 420 frontend cases (360 web + 60 SDK), confirmed by +[CI run 37852875524](https://github.com/HodeTech/LearnStack/actions/runs/37852875524). +The subsequent `5db8daedfd93f816ef23e545b8741ee54395e2f8` remediation adds four +compiler-erasure controls: inline type-only imports/reexports retain runtime edges, +while declaration-level type-only forms are erased. Both inline controls fail +before the guard fix. Two fresh independent reviewers approve the correction. +That tree passes 108 source cases and **424 frontend cases** (364 web + 60 SDK), +with zero failures/skips/todos. All six required checks pass in +[CI run 37855253417](https://github.com/HodeTech/LearnStack/actions/runs/37855253417); +TRX counters confirm 2,898 backend passes, including 846 Docker cases and the +real-API production renderer. These named runs qualify the earlier dated evidence; +they do not rewrite it as a claim about every later commit. + +**Review sanitation correction — 2026-10-09.** Client-supplied `next-url` is +removed from both native header collections and the middleware's downstream +allowlist under ADR-0053's existing client-carrier sanitation boundary. The +middleware control first reproduces its prior forwarding; the real TLS control +checks parsed/raw header removal while retaining successful native admission. +Next uses this carrier for interception routes, which P5 does not implement; +normal RSC/navigation protocol headers remain available. + +The other suggestions do not identify current failures. Port 3000 is the Accepted +local topology; Phase 11 owns its replacement. ADR-0052 limits the API to GET/HEAD, +and the configured caller exposes only those reads; a blanket web-method rule +would also govern scaffold and future Phase 02b BFF/auth paths. The caller consumes +only API origin and secret, never its computed TLS paths; the native launcher alone +reads certificate/key files, resolved against the repository root. + +### P02d-5 external-review remediation (2026-10-09) + +**Current status — Complete and merged (2026-10-09).** The +maintainer approved ADR-0054 and all five correction steps on development. +Runtime, proof and corpus corrections complete both fresh independent review +rounds and verified fixes. Step 5 records full local validation. The +[merge closeout](#p02d-5-merge-and-closeout-2026-10-09) records PR #26's final +head, six required checks and merge verification. Original delivery, proposal and +review notes below remain historical; P6/P7 scope remains separate. + +Review reports are evidence to verify. The triage below compares their claims with +`07016405`, installed Next 15.5.18/.NET 10 behavior and owned isolated reproductions. + +#### Decision package + +[ADR-0054](../decisions/0054-bounded-public-renderer-admission.md) is Accepted — +2026-10-09. It replaces only these ADR-0053 contracts: + +1. Refuse an exhausted known visitor before peer debit; keep unknown visitor + creation peer-gated. Own the actual visitor limiters and coordinate acquisition, + idle retirement and request-result replay. Preserve 60/IP, 600/peer, fixed + windows, no queue, the direct/hop shared namespace and pre-lookup enforcement. + Retain a 600-per-window peer-debit/allocation cap, not a total refusal-traffic + cap. One process-local owner lock serializes acquisition and bounded cleanup + batches; Phase 11 owns contention measurement and upstream protection. +2. Admit GET/HEAD on the current native public/scaffold surface; give other methods + masked no-store `404` before Next. Close all production upgrades; development + retains only required validated HMR. Future BFF/auth routes require explicit + admission in Phase 02b. No public API method or authentication rule changes. + The native rule covers every HTTP path, including middleware-exempt health and + assets; future Phase 06 Server Actions/write routes need their own admission. +3. Preserve inert query values, duplicates and ordering in redirects, allowing the + supported serializer's equivalent percent encoding. Stop promising identical + raw query bytes. Keep raw signed route identity and pinned framework projection. + +The current peer-first order is explicit in ADR-0053 Amendment 3, so this is a +bounded supersession, not a false-when-written correction. Dated navigation is +appended to ADR-0053/0036; this record explicitly replaces G34's accounting order +and G36's query-byte promise only. Their original accepted answers remain +historical; membership-first precedence and P6/P7 open parts remain unchanged. No +new global quota, distributed limiter, database migration, transport-suffix route +alias or schema/API contract is introduced. + +Keep existing valid traceparent continuation. Sampling participation, IPv6-prefix +aggregation and production tracing policy remain Phase 11; they are not tenant +authority. Keep the existing local HMAC key distribution/wire format. Fix diagnostic +containment now; freshness/nonces or a process-specific key require separate +production trust/distribution evidence, owned by Phase 11. + +#### Verified current findings and actions + +| Finding group | Verified result | Action in this PR | +|---|---|---| +| Shared peer budget, B1 | One visitor's 600 requests admit 60 and refuse 540 while exhausting the peer; a fresh visitor is then refused. Bare reversal allocates unknown visitors after peer exhaustion | Implement Accepted ADR-0054; prove refusal fairness, bounded work per refusal and peer-gated allocation independently. Retain the admitted-call/allocation cap; total refusal traffic is outside it | +| Framework endpoint retry | Current global-only wiring charges once. Adding an endpoint policy reproduces a second global debit after success | Save successful and refused request outcomes in the new owner; test actual endpoint-policy retry now | +| Next URL projection, M1 | Valid query values ending `.rsc` are changed by the adapter's full-URL normalization and rejected by the current verifier | Mirror pinned adapter processing, while retaining the signed raw target for route/locale identity. Test query cases and unrelated routes; add no suffix aliases | +| Proxy header sanitation, M2 | Native parsed/raw headers retain `x-real-ip`, bare `x-forwarded` and vendor authority spellings. Current downstream/API allowlists prevent authority escalation | Strip the explicit forwarding/authority carrier set from both collections; prove mixed-case controls and unchanged signed socket identity | +| Framework debug output | Installed Next logs full request headers under `DEBUG=next:*`, including the signed envelope | Refuse/suppress unsafe framework diagnostic configuration before request handling; prove containment with an enabled-debug canary | +| Methods/upgrades | TRACE/TRACK can fail before user middleware. Unmatched production upgrades can remain open because Next expects another WS consumer | Apply the Accepted native GET/HEAD and production upgrade rule; retain proven development HMR, no-store and bodyless HEAD | +| Redirect bytes | Literal apostrophe query values become `%27`; meaning is retained | Apply the Accepted equivalent-encoding contract; test actual runtime Location, not only the helper | +| Authority/source guard, M4 | `new Headers(request.headers)` and `Object.fromEntries(request.headers)` reads escape tracking, including spread of the converted object | Add bounded constructor/conversion tracking, named planted/clean controls and a census of supported tsconfig aliases; fail unsupported local mappings | +| Compiler evidence, M7 | Existing tests measure tsc verbatim emission. Installed Next SWC erases inline type-only imports/reexports | Keep the conservative graph policy; label the tsc proof accurately and add pinned SWC evidence with value/mixed-edge positive controls | +| Ingress fixture lifecycle, M6 | Setup occurs before try/finally; interruption leaves detached children/temp material | Put setup under one idempotent resource owner; cover setup failure, SIGINT/SIGTERM and parent/control-pipe closure | +| Fixture readiness | Ingress readiness can accept a stale 3011 listener; the real-API fixture already preflights its ports | Preflight both owned fixed ports, require owned-child bind/readiness and child liveness. Fail clearly on collision; do not attach to or kill an existing server | +| Fixture TLS/log proof | Ingress inherits TLS/debug overrides and can forget a leak after 64 KiB of later output | Allowlist child environment, explicitly verify TLS, and scan before truncation with chunk overlap and sticky verdicts | +| Renderer cleanup | Broken stdout can raise unhandled EPIPE before finally; ordinary stdin/signal cancellation is already handled | Route output-pipe errors through idempotent cleanup; prove an owned broken-pipe case | +| Upgrade/build containment evidence | Client-side timeout can masquerade as server closure; IPC is not synchronized. Secretless build only proves its declared secretless path | Make timeout fail, await owned IPC observations, add actual closure controls and a nonempty configured-build canary for private asset/diagnostic exclusion | +| Fixed-window tests | Exact accounting over 600 sequential HTTP requests assumes no minute rollover | Add deterministic owner/factory/sweep seams and barrier controls, plus retained real-framework/HTTP proof. Keep production window/limits unchanged | +| Hook/CI/DX | Hook omits `.mts/.cts`; SDK lint claim exceeds invocation; root config/generated-file selection differs; `.server` is formatted | Align explicit lint subjects/parser handling, cover SDK lint, exclude generated output, and add representative failure controls | +| Runtime support | Node 20 is EOL; CI still pins 20.11.0, while local P5 evidence uses 22.23.1 | Pin supported Node 22.23.1 across current tool/configuration carriers, then rerun actual CI. Historical Node 20 evidence stays historical | +| Narrow evidence/consistency | HttpClient merges repeated secrets; `v1.` substring is overly broad; favicon matcher has an unescaped dot; some guard assertions are only nonempty | Add raw-wire repeated-secret and mapped-peer controls, structural token matching, exact favicon matching and named guard assertions | +| Corpus and workflows, M3 | Current owner/status prose and route/seed launch guidance lag delivered G31–38/G44 | Align current documents and skills with accepted ownership; preserve P6/P7 open parts and immutable records | +| ADR disclosure guard | First nonempty Status line is a blockquote in ADR-0052, so CI's current awk misses its Accepted lifecycle | Parse the lifecycle line within Status, ignoring banners; plant Accepted-with-banner controls. Preserve original status/history | + +The Node support finding is verified against the +[official release schedule](https://github.com/nodejs/Release#release-schedule): +20.x reached EOL on 2026-04-30; 22.x remains Maintenance LTS through 2027-04-30. +The [22.23.1 archive](https://nodejs.org/en/download/archive/v22.23.1) identifies +the selected local-tested patch. No particular HTTP-parser CVE/exploit is claimed. + +Ongoing corpus fixes in this preparation cover Architecture 04/05/14/25, +Standards 03/06/07/11/12/15/index, glossary placement and frontend entry READMEs. +G32–37 answer links now point to their actual detail owners. Security Standards +carry the accepted private carrier, five API-hop headers, 10-second/8-MiB bounds, +secret/client/log exclusions and the narrow local Node configuration exception. +Remaining route-skill/seed/hook/CI edits ship with their corresponding code/tests. + +#### Rejected, qualified and later-owned claims + +| Claim | Disposition and reason | +|---|---| +| IPv4-mapped peers fail `IPNetwork.Contains` | Refuted on current .NET 10; the loopback IPv4 network contains mapped loopback. Add a pinning test, no parser workaround | +| Invalid visitor metadata violates an “only 600” rule | Refuted: existing policy specifies two budgets and peer-IP fallback. Clarify both debits; the proposal changes only exhausted-visitor accounting | +| Direct `.rsc`/segment paths must become public aliases | Not established for the supported non-minimal Node mode; segment cache is not enabled. Fix the valid query bug without broadening route identity | +| Plain `{...request.headers}.host` is a Next authority escape | Refuted for WHATWG Headers; it does not create a string host property. Converted plain-object spread remains a real guard gap | +| TRACE's ordinary framework 500 lacks no-store | Refuted by installed Next error rendering. Native refusal still avoids unsupported-method framework dispatch | +| Fixed 3000 is an accidental product port | Refuted: Accepted local topology. Test collision must fail rather than reuse a foreign listener. Phase 11 owns production topology | +| `make demo` is falsely claimed shipped | Refuted: README assigns it to P7. Do not add P7's target as a P5 repair | +| OpenSSL is undocumented; every PEM needs a global ignore | Refuted/scoped: prerequisites name OpenSSL and `.data/` protects accepted private certificate paths. Broad PEM ignores could hide public fixtures | +| All parent-death cleanup/TLS/log scanning is absent | Overstated: the real-API harness already watches stdin/signals, allowlists environment and scans before truncation. Fix its verified EPIPE path and the separate ingress deficiencies | +| Slowloris waits forever | Not reproduced; default Node timeout closes the reported case. Keep production timeout/topology tuning in Phase 11; enforce bounded fixture waits now | +| PID reuse warrants skipping every exited group leader | Rejected fix: surviving descendants require group cleanup. Reduce stale handles after confirmed group absence and retain the surviving-descendant control; no unrelated-group kill was reproduced | +| Envelope has no replay expiry | True protocol fact, not a supported-listener replay bypass. Submitted envelopes are replaced; Step 2 addresses the verified debug leakage. Phase 11 owns production replay/key lifecycle | +| Restart every visitor trace, change sampling, aggregate IPv6 prefixes | New observability/rate policies, not demonstrated P5 defects. Preserve accepted continuation; Phase 11 owns these choices | +| New static/auth/robots/sitemap paths must already bypass admission | P6/G40 and Phase 02b own their explicit namespaces. Existing exact exclusions remain; correct only the favicon regex defect now | +| Bootstrap reuse / Link prefetch already required in P5 | No current product pages exist. P6 owns request-local consumption/prefetch choices before page code, including call-count evidence; no caching or shared bootstrap is authorized | +| SDK response-parser/body/Retry-After notes | SDK is inherited from P4 and outside this PR's changed transport. P5's configured caller already bounds decoded bytes/deadline; re-verify SDK contracts with P6 consumers rather than change them speculatively | +| PlatformAdmin is required by `make public-api` | Refuted: optional credential is copied only when present; composition registers its lazy guarded source and boots without it. Public reads use the app role. Prove launch without it; do not grant public paths bypass access | +| Merge versus squash blocks remediation | Neither changes the code contract. Maintainer chooses merge mode; dated source/CI references remain scoped evidence, not a demand for a merge strategy | +| CLAUDE status length / model diversity proves a runtime bug | No. Keep task-specific current state honest and evidence scoped; broad guidance restructuring and unsupported transcript claims are not corrective production changes | + +Historical ADR-0053 delivery amendments remain intact. Acceptance appends the +bounded supersession note and clarifies ADR-0036's existing navigation wording +through dated navigation, preserving old text. CI currently checks relative +file targets, not anchors; keep manual anchor evidence labeled honestly. No new +required check or protection weakening is proposed. + +#### Implementation and review sequence + +Maintainer approval on 2026-10-09 authorizes these five correction steps on +development. The current status above and per-step records below own progress. +For each: +implement and validate, commit, run two fresh independent review rounds, validate +and commit confirmed fixes, then proceed automatically. Preserve main and unrelated +local work; do not rewrite the branch or merge PR #26. + +1. **Coordinated anonymous admission.** Implement the owned visitor limiter and + cleanup/retry semantics; deterministic accounting, parallel last-permit/creation, + safe retirement, endpoint-retry, selected Retry-After, cancellation/disposal and + real HTTP controls. Replace the named peer-refusal accounting test identified in + ADR-0054, retain admitted-traffic controls, and prove bounded per-refusal work, + non-overlapping/eventually complete sweeps and shutdown/acquisition safety. +2. **Native ingress and URL boundary.** Fix pinned projection, header sanitation, + debug containment, method/upgrade admission, query wording/Location proof, + powered-by and exact matcher. Retain real HTML/RSC, valid TLS and development HMR + controls; verify protocol headers through the actual middleware path. +3. **Fixture reliability and containment.** Resource-own setup/termination/EPIPE, + synchronize owned readiness/upgrades, enforce TLS/env allowlists and sticky + scanning, add configured-build canary and structural-token controls. Mutants for + omitted cleanup, early leaks, disabled TLS checks, stale listeners and unclosed + upgrades must fail with an independent clean control. +4. **Source/runner/tooling proof.** Close constructor/conversion and alias gaps, + make compiler claims exact, align lint/hook/formatter subjects and Node pins, + fix lifecycle parsing and strengthen narrow evidence controls. Keep every guard + falsifiable; an empty production client-component census is not bundle evidence. +5. **Corpus and PR closeout.** Update current skills/seed/setup/standards/catalogue + and ADR navigation with actual enforcement. Run applicable full Release suites, + lint/typecheck/build, production socket/TLS/rendering fixtures, SDK drift, + Markdown links/anchors/width, immutable-history and strict commit checks. Push + development, verify all six required checks on the exact new head and update + PR #26's description/evidence for maintainer review. + +No remediation acceptance or passing-test count is inferred from the earlier +`07016405` CI run. Preparation checks and independent document reviews are recorded +after they actually run; implementation evidence belongs to the five steps above. + +#### Remediation Step 1 — Coordinated anonymous admission + +**Complete — 2026-10-09; both independent review rounds passed.** The API owns actual +visitor fixed-window limiters, serialized acquisition and bounded periodic +retirement. Exhausted known visitors return their unchanged refusal metadata +before peer debit; peer refusal prevents unknown visitor allocation. Successful +and refused HTTP outcomes are copied into independent request-local leases, +including ASP.NET's retry after an endpoint policy refuses. Teardown closes +admission, joins active sweeping and disposes children outside the owner lock. + +Focused controls cover both final-permit races, single creation, both-budget +Retry-After selection, cancellation, replay/lease independence, more than two +sweep batches, non-overlap, full-quota idle retirement, actual .NET automatic +replenishment and concurrent teardown. Real HTTP accounting freezes only test +budget replenishment, retaining actual fixed-window implementations, so minute +rollover cannot invalidate exact accounting. The application-role/read-only +controls retain their original runtime path. No incoming-traffic or production +throughput bound is claimed. + +**Validation — 2026-10-09.** Strict Release solution build passes with zero +warnings/errors. All 2,922 .NET tests pass without failures/skips: 1,702 unit, +198 architecture, four contract, 172 Docker-free integration and 846 Docker +integration. The focused accounting/lifecycle set passes 27 cases; the real +endpoint-retry proof and 17 trusted-visitor HTTP cases pass. TRX execution/zero-skip +checks and changed-source format verification pass; the format workspace loader +reports a warning without a formatting violation. Corpus consistency is rechecked +at 5/5 after the status edits. + +**Review round 1.** Fresh GPT-6-astra xhigh runtime/security review approves the +implementation; fresh GPT-6.1-sol high proof/corpus review identifies one confirmed +test gap: eventual traversal did not constrain lock-batch size. The strengthened +300-entry control blocks the first outside-lock disposal, observes exactly 128 +idle inspections, admits another request before release and verifies complete +exact-once traversal. An actual `int.MaxValue` batch mutation fails the intended +128-versus-300 assertion; restored-source focused tests pass 27/27 with zero +skips. The production limiter is unchanged. The correction is committed as +`a107df5`, following implementation commit `208d64f`. + +**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high +proof/corpus reviewers approve the corrected tree. Their independent runs pass +56 focused unit cases and one endpoint-retry integration case, and 27 focused +accounting/lifecycle cases plus the endpoint retry respectively, with zero skips. +The remaining current-sequence status sentence is aligned in this closeout; +no additional production change is needed. Step 1 is complete; Step 2 starts next. + +#### Remediation Step 2 — Native ingress and URL boundary + +**Complete — 2026-10-09; both independent review rounds passed.** Native HTTP admission +accepts GET/HEAD before Next on every callback path; other callback methods receive +masked no-store 404. Node retains parser-level refusals, including TRACK, and no +CONNECT tunnel is admitted. Production closes every upgrade. Development permits +only exact validated GET HMR, bounds its initial 101 handshake and closes missing, +failed or ignored delegation while retaining established HMR connections. + +The launcher disables framework DEBUG before importing Next, including later +framework dotenv loading. Forwarding/authority carriers are removed from both +parsed and raw headers. `poweredByHeader` is disabled; the favicon matcher uses a +literal dot. URL verification applies pinned Next's full-URL `.rsc` normalization +before parsing and `_rsc` removal, then returns the signed raw context. Route and +locale admission still refuse suffix aliases. Redirect proofs compare actual +Location authority, path and ordered decoded query pairs, including apostrophes. + +Flight protocol preservation is tested through the real adapter and middleware; +the direct middleware mock no longer claims to exercise adapter-hidden headers. +The disposable route emits only named booleans, and its five GET probes plus HEAD +must produce exactly six live API bootstrap calls. No product route is introduced. + +**Validation — 2026-10-09.** All 469 frontend cases pass through the workspace +outcome guard (409 web, 60 SDK), with zero skips/todos. Lint and typecheck pass; +production build passes. The real API/PostgreSQL production-rendering case passes +1/1, including the six protocol/bootstrap calls and existing tenant isolation, +trace, freshness and containment. The actual native TLS fixture passes all-path +method/HEAD, matcher, query, production closure, DEBUG and retained development +HMR controls; its original planted cleanup control also passes. Corpus consistency +passes 5/5 and diff checks are clean. + +The DEBUG canary caught a pinned-library detail during implementation: an empty +DEBUG is deleted by debug initialization. The final nonempty `-*` exclusion is set +before importing Next, survives initialization/dotenv and is exercised with enabled +process and dotenv canaries. Next development route discovery also requires a +fixture-owned source copy, whereas production uses its existing compiled output. +These are verified fixture/runtime corrections, not new product contracts. + +**Review round 1.** Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol high +proof/corpus reviewers approve implementation commit `458a1dd` without verified +findings. Independent focused runs pass 257 and 218 frontend cases respectively; +the runtime reviewer also compares ten targets with the installed Next adapter. + +**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high +proof/corpus reviewers approve the same tree without verified findings. Focused +runs pass 125 and 218 frontend cases; the latter also passes all five corpus +consistency cases. These reviewers inspect the committed fixed-port fixture +proofs without rerunning them. Step 2 is complete; no corrective runtime commit +is required. Fixture ownership/containment and source/tooling remediation remain +Steps 3–4. + +#### Remediation Step 3 — Fixture reliability and containment + +**Implemented — 2026-10-09; independent reviews pending.** Test fixtures share +resource ownership, positive environment construction and bounded sticky output +scanning. Setup occurs inside cleanup ownership; signals, explicit parent control +closure and broken output pipes join the same cleanup before exit. Children stop +before private trees are removed. Process handles coalesce repeated cleanup and +retire permanently after confirmed absence; exited leaders still require cleanup +of surviving descendants. This narrows stale-handle exposure without claiming an +atomic POSIX process-identity signalling API. + +Both fixed ports are preflighted. Readiness requires evidence from the actual +owned child before accepting a healthy response; a foreign listener is neither +reused nor stopped. HTTPS, raw TLS and WebSocket clients explicitly verify trust. +Wrong-CA and wrong-name controls fail before bootstrap. Private-output verdicts +remain sticky after truncation and across chunk boundaries; structural envelope +checks distinguish ordinary API/version text from private wire values. + +The real renderer builds with nonempty private configuration and an actual +public-only Client Component. A successfully compiled secret-leaking component +fails emitted-asset scanning; the restored component builds cleanly with nonempty +client output. The API observes no request during compilation. Existing SDK, +host/trace isolation, six Flight/bootstrap calls, same-process freshness and stock +launcher refusal remain covered. Actual stdin closure and EPIPE controls require +exit 1 and removal of the owned temporary build tree. + +**Validation — 2026-10-09.** The guarded frontend runner passes 491 cases +(431 web, 60 SDK), with zero skips/todos; workspace lint and typecheck pass. +`PublicServerRenderingTests` passes 15/15: the real production path, twelve +structured-log controls and two actual parent-pipe cleanup cases. The strengthened +pipe controls also pass a focused rerun. Release integration build reports zero +warnings/errors; changed-source format verification passes with a workspace-load +warning. The shared scanner/environment/owner and process-handle controls pass +27/27. Corpus consistency passes 5/5 with zero failures/skips, and ADR-0054's +change is insertion-only. + +The real ingress source-mutant matrix passes 18/18: early OpenSSL failure, +asynchronous bootstrap refusal, setup/omitted cleanup, both signals, explicit IPC +closure, EPIPE, secure environment/TLS and disabled-TLS rejection, benign large +output and early split leaks, stale/bind failures, and upgrade closure/refusal. +Each intended failure is checked by its own oracle; cleanup rescue runs only +after the absence verdict and never re-signals a saved PID after confirmed absence. +Independent normal native/TLS/HMR verification remains the clean control. + +**Review round 1.** Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol high +proof/corpus reviewers inspect `e2f92b7`. Three verified findings are corrected: +failed child cleanup now retains the private tree, final child output drains +before shutdown containment, and token boundaries at chunk ends wait for a real +delimiter or EOF. A shutdown-only source mutant and split malformed-MAC controls +prove the fixes; the early-output control now includes an actual delimiter. +Focused helpers pass 31/31, the real ingress matrix passes 19/19 and the guarded +frontend runner passes 495 cases (435 web, 60 SDK), with zero skips/todos. +Changed-source lint passes. The original implementation counts above remain +historical. The real API/PostgreSQL renderer rerun also passes 15/15. + +**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high +proof/corpus reviewers approve `131a933` without actionable findings. The runtime +reviewer independently passes 31 helper/process-group cases, the normal real +native ingress and all 19 source-mutant controls. The proof reviewer independently +passes 31 helpers and five Release corpus cases. Step 3 is complete after both +rounds and verified fixes. Source/tooling and final closeout remain Steps 4–5. + +#### Remediation Step 4 — Source, runner and tooling proof + +**Complete — 2026-10-09; both independent review rounds passed.** Bounded AST tracking +covers global Headers constructors, converted records, constant aliases, +destructuring and converted-record spread, with named clean/dirty controls and +real public-entry mutations. Plain WHATWG Headers spread stays inert. Effective +inherited tsconfig paths and workspace exports are checked against the resolver; +unsupported production module extensions fail explicitly. Real pinned Next SWC +and TypeScript verbatim emission are separate proofs; the conservative graph +keeps inline type-only edges even where SWC erases them. No production Client +Component is invented to make the census appear nonempty. + +Web CI and staged lint share one source/script/root-config census, with generated +output/declarations excluded explicitly. Native `.mts`/`.cts` parsing is explicit; +the hook also invokes SDK/UI lint. Root Tailwind configuration now participates +in typecheck; its shared preset declares the existing Tailwind peer dependency. +The lock changes only that importer, without changing a resolved package version. +CI, `.nvmrc`, engine minimum and current setup guidance use Node 22.23.1. Generated +`.server` output is excluded from Prettier. Test discovery refuses symlinked +workspace packages or sources rather than silently skipping them. + +The ADR disclosure job reads the lifecycle declaration inside Status, ignoring +banners and consuming the complete input. A real workflow-block control rejects +an undisclosed Accepted-with-banner edit and accepts its dated disclosure. The +original Accepted ADR status/body/history remains unchanged. + +Raw HTTP proves two actual secret fields reach Kestrel, spend the exhausted +socket-IP fallback and bypass no lookup; one valid field then admits a fresh +visitor. Mapped-peer and noncanonical dotted-tail controls pin .NET behavior. +The actual public-local API launcher starts with only the application credential, +an empty owned user-secret root and no local env fallback, then serves both seeded +hosts through the trusted hop without PlatformAdmin. It uses a dynamic API port; +the accepted fixed renderer topology is unchanged. + +**Validation — 2026-10-09.** The guarded frontend run passes 557 cases (497 web, +60 SDK), with zero skips/todos. Focused source-boundary cases pass 157/157; +lint-tooling/runner controls pass 39/39. Workspace typecheck/lint and frozen offline +installation pass. Seven Python lifecycle/workflow controls pass. The focused +backend units pass 45/45; trusted visitor and real local-launch integration pass +18/18, with zero skips. Release solution build reports zero warnings/errors; +owned backend formatting and diff checks pass. Both fresh review rounds remain +pending; final full regression, real CI and PR closeout belong to Step 5. + +**Review round 1.** Fresh GPT-6-astra xhigh source/security review identifies two +confirmed static-alias gaps: destructured global constructors and separately +bound header iterators escaped the authority guard. Fresh GPT-6.1-sol high +tooling/backend review approves its scope after seven lifecycle controls, +39 tooling/runner cases, 45 unit cases, two real integration cases and web lint. +The correction follows verified global destructuring and gives header iterators +a distinct origin, consumed only by conversion/clone operations. Four planted +violations fail before the fix; named shadowed/inert/iterator controls and both +real render-helper mutations pass afterward. All 171 focused boundary cases and +571 guarded frontend cases (511 web, 60 SDK) pass with zero skips/todos; +workspace typecheck/lint pass. No production consumer exploits either gap. +**Review round 2.** Fresh GPT-6-sol xhigh source/security review confirms the +first-round fixes, then identifies the same static-constructor gap in the +separate API-hop-header setter fence. The correction reuses the verified global +constructor predicate; qualified/aliased/bound setters and a real helper mutation +are refused, while inert/shadowed constructors and the adapter exemption stay +clean. The before-fix run exposes all three setter escapes, the helper escape and +the old shadowed-constructor false positive. All 178 focused boundary cases and +578 guarded frontend cases (518 web, 60 SDK) pass afterward with zero skips/todos; +workspace typecheck/lint pass. Fresh GPT-6.1-sol high tooling/backend review +approves after seven lifecycle, 39 tooling/runner, 45 unit and 18 real integration +cases, web lint and diff checks. The source reviewer independently verifies +`ced7911`: all three setter escapes change from missed to flagged, shadowed/inert +controls stay clean and all 178 boundary cases pass. Step 4 is complete after both +rounds and verified fixes; Step 5 owns final corpus/CI/PR closeout. + +#### Remediation Step 5 — Corpus and PR closeout + +**Local closeout complete — 2026-10-09; both independent review rounds passed.** +Current architecture/security prose and Phase 02b G14 now reflect delivered +ADR-0054 behavior. CLAUDE, README and the ADR/roadmap indexes link this current +record instead of maintaining separate remediation-step status lists. Original +Accepted ADR bodies and dated delivery evidence remain unchanged; ADR-0054's +new delivery navigation points here. + +Route guidance identifies the API as tenant/organization authority and marks the +Keycloak/session example as Phase 02b work requiring explicit ingress admission. +Seed output points to manual hosts/CA/leaf preparation and the paired public +launchers, without claiming P6 pages or P7's demo. Setup/test guidance distinguishes +random Testcontainers PostgreSQL ports from fixed renderer ports, and current +deployment-mode defaults from the Phase 02c Hub adapter. The seed-role diagnostic +correctly distinguishes FORCE RLS ownership from a privileged bypass credential. + +**Final local validation — 2026-10-09.** Strict Release solution build reports +zero warnings/errors. All 2,940 .NET cases pass: 1,705 unit, 198 architecture, +four contract, 172 Docker-free integration and 861 Docker integration, with zero +failures/skips. Actual TRX counters and the nonempty/no-skip runner are checked. +All 578 guarded frontend cases pass (518 web, 60 SDK), with zero skips/todos. +Workspace typecheck/lint/build and regenerated SDK drift checks pass. Native +HTTPS/Next verification and all 19 independent failure controls pass; the full +Docker suite includes real production HTML/RSC, configured-build containment, +parent-pipe cleanup and the actual app-only API launcher. + +Seven ADR lifecycle/workflow and 14 OpenAPI CI controls pass. Both compose +projections validate with and without the gated profile using the public example +configuration. Full backend format verification passes with a workspace-loader +warning and no formatting violation. Post-acceptance ADR changes are insertion-only. +The strict commit hook, changed-document relative links/fragments, added-prose +wrapping, corpus consistency and diff checks pass after the closeout edits. +Fragment verification is a manual local audit; CI's link job checks file existence. +All six live required checks and strict protection remain configured. [PR #26](https://github.com/HodeTech/LearnStack/pull/26) +records their execution on the final published head and the final PR description; +these local checks do not imply a successful remote run. + +Remaining scope is unchanged: P6 owns product pages, request-local bootstrap reuse, +prefetch decisions and accessibility; P7 owns the browser/demo/Lighthouse harness. +Phase 11 owns distributed/edge limits, contention/load evidence, production +topology, replay/key lifecycle and tracing participation. These corrections add no +API schema, database migration, tenant resolver, authentication flow or Hub crossing. + +**Review round 1.** Fresh GPT-6-astra xhigh corpus/governance and GPT-6.1-sol high +DX/evidence reviewers verify `2b5b6ac` against current source and actual reports. +One confirmed Minor finding is fixed: a second mutable step-status sentence still +said Step 4 reviews/Step 5 were pending. It now points to the section's current +status and per-step records. Whole-PR added-prose verification also wraps two +long standard/catalogue lines. Both reviewers approve after the verified +correction; no production change is needed. Round 2 and exact-head CI remain pending. + +**Review round 2.** Fresh GPT-6-sol high corpus/governance and GPT-6.1-sol high +DX/evidence reviewers approve `869145e` without actionable findings. They +independently confirm the real TRX/frontend/native-control results, append-only +ADR history, current API authority, local TLS/port behavior and P6/P7/Phase 11 +ownership. Link/fragment, prose, strict commit and diff checks pass; the five +Release corpus cases pass with zero skips. The later 578-case workspace report +is the frontend evidence; the earlier 557-case run remains historical. +Both rounds and verified corrections are complete. Development is the only +working branch; PR #26's final head/checks and description own remote closeout. + +**Preparation verification — 2026-10-09.** Independent GPT-6-astra xhigh security +and GPT-6.1-sol xhigh corpus reviews find no remaining major issue in the proposal. +Confirmed wording/header/ownership corrections are applied. Release +`CorpusConsistencyTests` pass 5/5, with zero failures/skips. Manual inspection of +all 18 changed/new Markdown files resolves 1,226 relative links and 441 fragment +targets; added prose wrapping and `git diff --check` pass. Existing Accepted ADR +files are unchanged. These are proposal/document checks, not runtime remediation +or new CI evidence. + +**Second independent proposal review — 2026-10-09.** Fresh GPT-6-sol xhigh design +and GPT-6.1-sol high corpus reviewers approve `d8d540a` for maintainer decision +approval with no remaining actionable findings. The design review independently +checks zero-permit framework behavior and actual redirect value/order preservation. +This closes the two proposal-review rounds; ADR-0054 remains Proposed and dependent +implementation still requires the maintainer's explicit approval. + +**External ADR review clarification — 2026-10-09.** All six findings are verified +against the current limiter, HTTP tests, native launcher and app route census. +ADR-0054 now distinguishes the admitted-call/allocation budget from total refusal +traffic, names the test whose peer-debit expectation must change, and specifies +the process-wide lock, refusal metadata precedence and lifecycle proof obligations. +It records native admission across middleware exemptions, separate identification +control and the missing carrier/reference links. The app currently has GET health +and no POST handler or Server Action; real launcher controls remain implementation +obligations. Prior reviews/counts remain historical. ADR-0054 stays Proposed; +these documentation clarifications accept no decision and deliver no runtime fix. +Release `CorpusConsistencyTests` pass 5/5, with zero failures/skips. The two changed +Markdown files resolve 456 relative links and 283 fragment targets in a manual +audit; added prose wrapping and `git diff --check` pass. All phase text outside +this remediation section and every Accepted ADR file remain unchanged. + +**Clarification review closeout — 2026-10-09.** Two fresh independent rounds review +`1a7c6fd`: GPT-6-astra xhigh / GPT-6.1-sol high first, then GPT-6-sol xhigh / +GPT-6.1-sol high. Both rounds report no actionable design or corpus findings after +checking the changed contract against source, existing tests and pinned framework +behavior. This approves the revised proposal for maintainer decision review; +it does not accept ADR-0054 or establish runtime remediation/CI evidence. + +### P02d-5 merge and closeout (2026-10-09) + +The maintainer merged [PR #26](https://github.com/HodeTech/LearnStack/pull/26) at +2026-10-09 15:45:36 UTC. GitHub records final PR head +`f09a4edf3e00e7043f6775642e10e40024ab9393` and merge commit +`863f5c1b0051c318a0326357c2fb65dded75afca`. The merge's second parent is that +head, and both commits have the identical tree. Development is fast-forwarded to +the verified merge without changing branches or rewriting history. + +- All six required checks pass on the + [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37943884658). + Downloaded TRX confirms **2,940 passed, zero failed or skipped**: 1,705 unit, + 198 architecture, four contract, 172 Docker-free integration and 861 Docker + integration. Frontend CI confirms **578 passed** (518 web, 60 SDK), zero + skips/todos, and successful typecheck, lint, production build and SDK drift. +- Native HTTPS/Next verification and all **19 failure controls** pass in CI. + Real API/PostgreSQL HTML/RSC, build containment and parent-pipe cleanup proofs + remain part of the Docker suite. These are transport/runtime proofs, not P6 + product-page or P7 browser/Lighthouse delivery. +- The final review correction isolates fixture Git/hook environments from inherited + `GIT_*` variables and reconciles README/catalogue status. Eleven tooling and + seven ADR workflow cases pass locally under both invalid inherited Git settings + and the normal environment, with typecheck, lint, format and link checks clean. + The original four steps and five remediation steps retain their recorded + independent review rounds and verified fixes. +- Read-only branch-protection verification confirms the same six required Actions + contexts and `strict: true`; no protection setting changes. + +All six required checks also pass in the +[merge-commit run](https://github.com/HodeTech/LearnStack/actions/runs/37954123158). +Independently downloaded merge-run TRX confirms the same 2,940 passing .NET cases +with zero failures/skips. Frontend logs confirm the same 578 guarded cases and +19 ingress controls. Both runs use the delivered Node 22.23.1 pin; the deferred +Lighthouse job remains owned by P02d-7. + +**P02d-5 is closed.** The trusted native ingress, fair known-visitor accounting, +bounded configured caller, live-host/locale entry, uncached rendering policy and +source/runtime controls are delivered under ADR-0053/0054. No database migration, +public API schema change or authentication/Hub flow is added by this packet. + +**Next: P02d-6 — Public renderer.** Its decision pass has not started. Re-verify +G5's unavailable-band behavior, G12's page states, G16's rendering part, G20's +subjects, G38(b,c) and G39–G43 against the delivered API and transport before +implementation. The packet owns catalog, course-detail/outline and lesson pages, +UI messages, ordered text-card rendering, safe theme injection, language/SEO +metadata, page/error/empty/locked states and accessibility checks. Request-local +bootstrap reuse and prefetch policy must also be settled before page consumers. + +P02d-7 owns `make demo`/stop behavior, the two-host browser/full-stack harness, +Lighthouse activation and phase exit. Phase 11 owns production/distributed limits, +load evidence, ingress topology, replay/key lifecycle and tracing participation. +Phase 02d remains in progress; neither remaining packet nor Course Marketplace +commerce is delivered by this closeout. Earlier dated records remain unchanged. + +**Documentation-only closeout validation.** Five local Release corpus cases and +seven ADR lifecycle/workflow controls pass, with zero failures/skips. The eight +changed Markdown files resolve 901 relative links and 393 fragments in the local +audit; prose wrapping and diff checks pass. ADR-0053/0054 changes are insertion-only; +earlier dated delivery records and P02d-1's decision/scope suffix are byte-preserved. +This closeout changes no production code or accepted decision. + +## P02d-6 — Public renderer + +### P02d-6 decision package (2026-10-09) + +**Accepted — 2026-10-09, re-verified against `2d821c4`.** P02d-1–5 are complete +and merged. The maintainer explicitly approved revised +[ADR-0027](../decisions/0027-frontend-i18n.md), all gate answers and the status/URL +tradeoff below. The decision commit precedes implementation and claims no product +page or dependency delivery. Earlier preparation/review records remain historical. + +#### Reviewed inputs and verified premises + +The documentation pass covers the platform vision and MVP boundary; Principles; +the glossary and decisions index; ADR-0008/0009/0018/0035/0036/0040/0042/0043/ +0050/0051/0052/0053/0054; Localization, Frontend Architecture and Tenant +Customization Model; Standards 03/06/07/08/09/11/13/15/16/21; Phase 02d and its +Phase 04/05/06/07 consumers. The `implement-task`, `add-frontend-route`, +`add-i18n-key`, `write-adr` and commit workflows are included. + +Code verification covers the public SDK DTOs/results, native ingress and verified +entry, configured caller, middleware, root/public layouts, CSS tokens, renderer +registry, frontend source fences, guarded runner and real API/Next fixture. +In particular: + +- Four public GET operations and their eligible alternates already exist. Pages + need no new endpoint, write method, entity, migration, tenant id or Hub call. +- The only implemented lesson presentation is ADR-0051's ordered plain-string + `default-card`. The larger registry does not implement additional renderers. +- Public theme DTO validation currently checks string shape, not color grammar. + Safe HTML injection must validate the complete four-token value again. +- Middleware consumes and discards live site bootstrap. `React.cache` can share + RSC work within a render, not between middleware and RSC execution. +- The production fixture currently injects a disposable transport-probe page. + It proves P5 transport, not the actual P6 product pages. +- Root HTML still has fixed English/platform metadata. No UI catalogue/runtime + is installed. Existing seed inventory does not fill a normal 20-item page. + +The pass corrects current mutable carriers that prematurely claim product pages, +leave the delivered G12 interface open, or require an outbound URL sink in this +plain-text packet. Accepted ADR bodies and shipped delivery records are unchanged. + +#### P02d-6 accepted answers + +| Gate / part | Accepted answer | +|---|---| +| G5, G12 page states | Preserve public DTO eligibility and exact pins. Omit a null level; localize an unavailable level. Unavailable content has a bounded placeholder, never raw JSON or another revision. Distinguish empty catalog, empty public outline, restricted outline, empty ready content and unavailable content. | +| G16(g) | Render the complete safe tenant palette independently of plan. The effective `showPlatformAttribution` value alone controls platform attribution; no plan inference in the renderer. | +| G20 subjects | Census production frontend TS/JS and JSON, including renderer/message values, against the exact decoded seed identity literals from G20(a). Preserve the accepted platform-built-in and development/test exemptions, without a blanket catalogue exemption. P7 implements the existing registered rule across backend and frontend. | +| G38(b,c) | Vitest covers synchronous views and pure mappings; real production HTML/RSC tests cover async pages. Extend the existing required Docker integration fixture to unchanged product pages while preserving the isolated P5 transport probe. P7 still owns shared demo/browser/Lighthouse activation. | +| G39 | ADR-0027 is Accepted at first use: exact next-intl 4.14.9, server-first configuration using shared verified request admission, app-local `src/i18n/messages/{en,tr}/public.json`, dotted feature UI keys and one checked ICU catalogue contract. Backend `lockey_*` remains a separate wire namespace; the web app owns closed page-outcome mapping, not the SDK. No i18n routing middleware or preference cookie. | +| G40 | Three fixed content routes, minimal tenant chrome, both opaque pagination surfaces, exact-locale metadata and explicit page states. The maintainer explicitly approved the status/navigation choice below. | +| G41 | Render only the API's ordered plain-string fields through app-local synchronous components in `apps/web/src/components/public/`. Unsupported renderer or unresolved presentation renders the bounded fallback. No HTML, Markdown, linkification, authored URL sink or new primitive. | +| G42 | Emit a server-generated style element containing only four fixed `--ls-*` color properties after atomic `#rrggbb` validation. Null or malformed theme retains the entire existing CSS default palette. No per-token merge, style attribute, URL, font or organization override. | +| G43 | Enforce applicable jsx-a11y rules at error severity with actual-config planted controls; assert visible semantics/languages/titles. Catalog → course → lesson is a critical flow requiring keyboard, focus, reflow, contrast and a real screen-reader smoke record. Status promotion occurs with enforcement, not acceptance. | + +UI catalogue fallback is not content fallback. An enabled language without an +authored UI catalogue remains admissible; UI groups and API-resolved labels carry +their actual language. Document language/direction follow the admitted route as +specified by ADR-0027. A test-owned enabled RTL locale and eligible content prove +document direction and English UI fallback language independently, without +rewriting the historical seed or promising an Arabic UI catalogue. No tenant +identity selects markup, translations or fields. + +#### G40 status and navigation decision + +Pinned Next **15.5.18** was exercised in an owned disposable production fixture, +without modifying this repository. These are planning experiments, not passing +product tests: + +| Strategy | Observed initial document | +|---|---| +| `notFound()` below a loading boundary | Streamed HTTP 200 with not-found digest | +| Await resource outside child loading, then `notFound()` | HTTP 404, but generic error HTML without visible localized fallback or root `lang`/`dir`; fallback text exists only in Flight | +| Remove loading entirely | The same generic HTTP 404 error document | +| Local Suspense / access-fallback boundary | Visible fallback with HTTP 200, not a hard 404 | +| Await lookup, redirect to an explicitly admitted fixed error page; middleware supplies its 404 status | Local HTTP 307 followed by visible localized HTML 404 with root language/direction and no-store; HEAD is bodyless | + +The maintainer accepted the last strategy, **including its URL/status tradeoff**. +Root/route admission awaits the request-cached resource +before emitting a document shell. A missing/hidden resource redirects to the +same host's fixed `/{locale}/status/not-found` page, which middleware admits only +after live host/locale validation and marks HTTP 404. That page is ordinary +server rendering, not a thrown `notFound()`. It echoes no original slug, query, +cursor or failure detail. Its title/robots are localized and noindex; it has a +catalog recovery link and the same safe theme/chrome. It never queries Education. + +The original request is **307, followed by 404**, and the browser URL changes. +This is not a claim that the original document returns a direct 404. The +acceptance commit updates G40's completion criterion to name that exact chain and +adds this error namespace to the entry matrix and route skill. Middleware's +existing masked +unknown-host/provenance refusals remain direct, neutral responses. No new signed +data carrier, shared bootstrap cache or outbound header is introduced. + +Returning a localized HTTP 200 error as though it were a 404 is rejected. A +middleware content preflight followed by another content read is also rejected: +it costs a fourth call on every success and still races the later read. A new +authenticated DTO-transfer protocol is not justified for this packet. Preserving +the original URL with a branded direct 404 would require a separately designed +response-ownership change; it is not silently promised by this decision. + +Metadata, layout and page use the same request-local resource loader. Layouts do +not serialize child execution, so each page honors the loader result itself. +Required `loading.tsx`/`error.tsx` files remain, but no loading boundary may flush +the document before redirect admission. Loading UI is not promised during that +initial pre-admission wait. Unexpected framework errors retain the framework's +pre-stream 500 / post-stream 200 behavior; `error.tsx` cannot set arbitrary status. + +Known content-call failures use controlled, translated, noindex page states: +invalid cursor → explanation and a relative reset link; 429 → retry-later state; +transport/invalid response/unavailable API → unavailable state. These are ordinary +HTTP 200 representations, not claimed HTTP 400/429/503 responses. Bootstrap +refusals retain middleware's real 404/429/503 and bounded Retry-After. A fresh +bootstrap failure on the error-route request remains that neutral refusal rather +than inventing a tenant theme or configuration. A closed mapping selects owned UI +keys for supported outcomes; unknown codes/failures use the unavailable state. +No Problem Details message key, title, field error or parameter becomes a lookup +identifier or visible copy. + +#### Routes, pagination, metadata and chrome + +- Keep `/{locale}/courses`, `/{locale}/courses/{slug}` and + `/{locale}/courses/{slug}/lessons/{lessonSlug}`. Fixed section names remain until + Phase 06; the platform placeholder leaves the public product path. Existing + exact `/studio` and `/portal` scaffolds remain without invented authentication. +- Use ordinary same-host relative anchors for product navigation, including + pagination: no automatic prefetch and no reliance on retained client Router + Cache. A new document request re-reads current API state. +- Parse only owned pagination parameters from the verified raw signed target; + observed Next `searchParams` is not their authority. Refuse duplicate, empty, + malformed or oversized owned values. Cursors stay opaque and are never decoded + by the renderer. Catalog uses `cursor`/`limit`; outline uses + `lessonCursor`/`lessonLimit`, with the API's bounds and a default page size 20. +- Show restart/next links as applicable; do not fabricate a previous cursor. + A test-owned inventory above the page bound proves both pagination surfaces; + do not reduce the product page size or rewrite the historical seed inventory. +- A restricted course shows marketing metadata and a translated access notice, + with no lesson count, lesson link, purchase/login/enrollment control or body. + An empty public outline is distinct. Missing optional text is omitted. +- Minimal chrome contains tenant display name, catalog navigation, skip link and + conditional platform attribution. Full menus, logo/media, authored errors, + preview, organization theme overrides and Studio editing remain Phase 06. +- Canonical and Open Graph URLs use only the verified live host, existing HTTPS + listener convention and validated local segments. Course/lesson hreflang uses + the API's actual eligible alternate slugs, never the current slug substituted + into another locale. Catalog uses enabled locales. Paginated views are noindex + with the cursor-free first-page canonical; error states are noindex with no + misleading resource alternates. Metadata shares the same data read as the page. + +#### Rendering, theme and accessibility detail + +Course lists use semantic lists; ordered outlines use ordered lists; field cards +use definition lists with authored order and language-bearing labels. Each page +state has one main, one descriptive h1, sequential headings, a skip target and +visible keyboard focus. Long unbroken strings wrap and logical CSS supports RTL. + +Strings resembling scripts, HTML, `javascript:`, `data:` or HTTP URLs remain +escaped, inert text. Absent optional fields render nothing. Unknown composites +and unavailable content emit only bounded placeholders and at most one diagnostic +per request containing a count/state, not field values, keys or private context. +The original G41 candidate's integer/boolean/enum/taxonomy expansion is not +authorized by ADR-0051; those richer primitives remain Phase 04/05 and Phase 06. + +The theme emitter admits the complete four-color grammar before producing fixed +CSS. Foreground/muted text retains its 4.5:1 background requirement. Primary has +only a 3:1 background guarantee, so normal text links use foreground plus an +underline; do not assume white text on primary is accessible. Primary may supply +non-text focus/border accents where its contrast is sufficient. CSP delivery +remains Phase 11; output must be safe without it. + +Manual evidence names commit, environment, both hosts/locales, keyboard path, +focus, 320 CSS px reflow/zoom, long strings, contrast and the screen reader used. +DOM assertions do not replace that assistive-technology smoke. If it cannot be +performed, the record stays pending and packet completion is not claimed. +Full Playwright/axe remains Phase 06; Lighthouse activation remains P02d-7. + +#### Request accounting and validation + +Normal content document: middleware bootstrap + request-local RSC bootstrap + +one shared content operation = **three API calls**. A missing document followed +to the accepted error page adds two bootstrap calls = **five total**. Repeated +metadata/layout/page consumers must not add calls; the next incoming document +must re-read. No retry or shared validated-DTO cache is added. + +The existing 60-call visitor and 600-call peer windows therefore give theoretical +ceilings of 20/200 successful three-call documents before other calls, not page +throughput promises. No limiter number, deadline, byte cap or partition changes. +Phase 11 owns production/distributed capacity and measured optimization triggers. + +The actual-page fixture must retain learnstack_app, RLS/read-only transactions, +native HTTPS ingress, closed hop headers and existing containment/failure controls. +Keep the synthetic P5 probe in a separate mode so its catch-all cannot shadow +product routes. Assert visible HTML/DOM separately from Flight strings: status, +language/direction, headings, theme, attribution, both hosts/locales, cross-tenant +absence, overlapping concurrent requests across both hosts/locales, freshness in +one process, controlled failures, pagination, exact schema swaps and inert values. +Verify the 307→404 chain and no direct internal bypass. +These HTTP/RSC proofs are not a browser end-to-end claim. + +#### Accepted implementation steps + +0. **Decision commit.** Accept approved ADR/gate parts; reconcile every normative + carrier and the changed G40 status criterion before writing implementation. +1. **Localization and document foundation.** Install/pin i18n, author complete + catalogues and ICU controls; verified request-local loaders, language/direction, + safe theme/chrome and controlled state components. Establish status-route + admission with production regression, preserving all P5 controls. +2. **Catalog and course.** Implement actual list/detail/outline pages, both + pagination surfaces, restricted/empty states and metadata from shared loaders. +3. **Lesson presentation.** Implement ordered default-card fields, unavailable + fallbacks, language attribution, schema-swap and inert-value proofs; complete + semantic/focus/lint controls across all page states. +4. **Product proof and closeout.** Complete the real product fixture, no-leak and + request-count/freshness controls, manual accessibility evidence and all carrier + updates. Validate, then open the implementation PR for maintainer review. + +Every numbered implementation step is committed, then reviewed by fresh agents +in two independent rounds. Verify each finding against current code, commit +confirmed fixes, rerun affected checks and only then advance. Reviewer model and +effort follow criticality; security/runtime and proof integrity have separate +review lines. No branch/worktree change; all commits remain on `development`. + +Validation comprises the guarded frontend suite, typecheck, lint, production +build/native verification, relevant Release backend architecture/contract/unit and +real Docker integration suites, formatting, diff checks and relative-link/anchor +audits. Record actual passing counts only after execution. Browser/assistive +technology observations are reported separately from automated test evidence. + +#### Approval boundary and acceptance carriers + +The maintainer approved these together on 2026-10-09: + +1. ADR-0027's library, pin, catalogue home and UI/content-locale separation. +2. G40's explicit local 307→404 error-route behavior and URL change, three-call + normal path/five-call missing path, plain-anchor navigation and controlled + HTTP 200 noindex API-failure states. The original direct-404 wording is not + claimed as implemented by this plan. +3. The remaining gate answers, four implementation steps and mandatory manual + accessibility proof above. + +The acceptance commit updates the decisions index; Standards 03/06/07/08/09/16/21 +and index; +Localization/Frontend/Customization architecture; Phase 04/05/06/07 inheritance; +glossary terms where introduced; the frontend route/i18n/block and test skills; +and this register, +renderer scope/completion criteria and decision record. Only implemented tests +may be labelled Implemented. Accepted ADR-0053/0054 remain unchanged: this selects +their delegated page composition, without another authority carrier or budget. +If review finds an Accepted decision must change, draft its replacement and seek +approval before dependent code. P02d-7 and Phase 11 ownership remains unchanged. + +#### Acceptance validation (2026-10-10) + +The acceptance-only reconciliation passes five Release corpus-consistency cases +and seven ADR-status workflow cases, with zero failures/skips, plus added-prose +wrapping, relative-link/fragment and diff checks. A fresh independent acceptance +review confirms Registered proof statuses, unchanged previously Accepted ADR bodies +and the pending implementation boundary. Its confirmed stale block-skill carrier +is reconciled before the decision commit. No dependency or runtime is delivered. + +#### Preparation review and validation + +Two independent draft-review rounds complete: GPT-6-astra high and +GPT-6.1-sol high review runtime/corpus first; fresh GPT-6-sol high and +GPT-6.1-sol high review the corrected package second. The separate i18n review +also checks the pinned package evidence. Confirmed fixes add a complete message +key example, ICU formatting in the selected UI language, callsite-to-catalogue +coverage with planted controls, and overlapping host/locale request proofs. +Both final round-two reviews report no actionable issue; maintainer acceptance +is still required. + +Documentation-only validation: five Release corpus cases and seven ADR +lifecycle/workflow cases pass, zero failures/skips. Local relative-file/fragment +audits, added-prose wrapping and `git diff --check` pass across the ten changed +Markdown files. ADR-0027 parses as Proposed. No Accepted ADR file or production +code is changed; no frontend/product, browser or accessibility test is claimed +passing by this preparation record. + +#### External i18n draft review reconciliation (2026-10-09) + +The review of `64eefe8` is checked against the SDK, current entry/caller and +mutable documentation. Its six finding groups are addressed: general UI keys +use dotted feature names in the proposal; backend `lockey_*` resources remain +intact; the false SDK translation-map claim is removed. Standards 09, the glossary +and the key skill now distinguish wire-message data from consumer-owned copy. +Acceptance explicitly reconciles Standards 03/07/08/09 and the catalogue sketches. + +ADR-0027 now names the shared verified admission source for request configuration, +whole-catalogue fallback versus missing-key build failure, the future Standards 21 +section, actual repository dependency pins and test-owned RTL inventory. The +review's prefix claim is qualified: `lockey_` is a backend invariant, not a blanket +ban on frontend error resources. No Accepted backend localization contract is +removed. No gate is accepted and no implementation or dependency is added. + +Fresh first-round runtime/corpus reviews use GPT-6-astra high and GPT-6.1-sol +high; an independent second round uses GPT-6-sol high. All report no actionable +finding in the corrected proposal. Maintainer acceptance remains required. + +Five Release corpus cases and seven ADR workflow cases pass with zero failures or +skips. Relative-file/fragment, added-prose wrapping and diff checks pass. These are +documentation checks; no product-runtime or accessibility proof is claimed. + +### P02d-6 Step 1: Localization and document foundation + +**Foundation implemented — 2026-10-10; both independent review rounds complete.** +Work stays on `development`. This record covers the foundation only; +actual catalog/course pages remain Step 2 and lesson presentation remains Step 3. +It does not close P02d-6 or any product/manual accessibility criterion. + +#### Delivered foundation + +- Exact `next-intl` 4.14.9 dependency/lockfile, App Router plugin and server-only + request configuration, with complete app-local English/Turkish `public` + catalogues. ICU/key/argument and production-callsite census controls include + planted missing-key, absent-from-all, misspelled-callsite, malformed-ICU and + argument-mismatch failures. Formatter failures select bounded translated copy. +- Shared server-only request-local admission and content loaders re-verify ingress, + read live site configuration and take content locale/route/pagination identity + from the signed target. The request loader imports neither next-intl nor + messages. UI fallback and runtime direction selection preserve content identity. + A private weak identity memo keyed only by Next's exact request-store headers + object retains same-request admission/content work across error rendering; no + header value, host or envelope keys a representation cache. `getPublicUi` uses + React cache only to reuse selected messages/translators inside an RSC render; + it does not own admission or content-read deduplication. +- Root document language/direction, atomic validation of all four color slots + before fixed style-element emission, and tenant chrome with one main/skip + target, catalog anchor and effective conditional platform attribution. Null or + malformed themes retain the entire existing CSS default palette. +- Closed translated state views, loading and unexpected-error boundaries. The + interactive retry boundary receives bounded labels only. The admitted fixed + status page supplies localized title/noindex metadata and a catalog recovery + link, echoes no original target and performs no Education read. Shared resource + admission selects the approved local 307→404 path for missing content. + +The production fixture adds a separate foundation-consumer mode while retaining +P5's isolated transport probe. The temporary consumer exercises foundation code; +it does not deliver or prove unchanged catalog/course/lesson product pages. +The real production fixture verifies three API calls for a normal document, +three again on its next request and five across the missing-resource redirect +chain. Parallel status requests, bodyless HEAD, renewed host/locale refusals and +canonical redirects pass. Enabled `ar`, `tr` and `tr-TR` coverage checks visible +localized status HTML/metadata, content direction and labelled English fallback +without an Education read. The historical seed remains unchanged. + +#### Verification and review boundary + +The guarded frontend run passes **817 tests: 757 web and 60 SDK**, with zero +skips/todos. All **198 Release architecture cases** pass. The production build +passes with the dynamic status route and root language/theme injection; the real +fixture checks that building performs no API prerender calls. Workspace lint and +typecheck pass. The focused real-API production integration run passes **16 cases, +zero failures/skips**, retaining the separate P5 transport and cleanup controls. +Native ingress regression verification passes TLS, method/upgrade admission, +query redirects, production containment and development HMR. Missing static assets +are refused before tenant bootstrap even when Next invokes the root fallback. +No unchanged content-page, +browser E2E, Lighthouse or manual accessibility pass is claimed here. + +All five P02d-6 architecture-test rules remain **Registered** until their complete +named proof obligations are verified; a foundation test alone does not promote the +broader page-state or accessibility rule. Accessibility remains **Adopted**. + +#### Step 1 review round 1 (2026-10-10) + +Fresh GPT-6-astra xhigh and GPT-6.1-sol xhigh sessions review `c14ecf2..568ecc2` +independently. Runtime/security has no confirmed finding; the proof/corpus review +finds one stale live packet-table cell. It is verified against the delivered code +and corrected to link this foundation record and distinguish the remaining steps. +No production change is required by this round. + +Independent verification includes 216 focused runtime cases and 360 focused proof +cases; the proof reviewer also reruns all 817 guarded frontend cases with zero +skips/todos. Both reviewers approve the Step 1 scope. They inspect the production +fixture but do not rerun its native/Docker execution; the root's validation above +owns that evidence. Product/manual accessibility work remains Steps 2–4. + +#### Step 1 review round 2 (2026-10-10) + +Fresh GPT-6-astra xhigh and GPT-6.1-sol xhigh sessions independently review +`c14ecf2..73b9d53`. Runtime/security has no confirmed finding. Proof/corpus review +confirms two Minor workflow-document issues: stale installation status in the +i18n/route skills, and a route example whose narrowed translator namespace does +not match the implemented callsite census. Both are corrected against the shipped +foundation; the reviewer verifies the resulting skill diff. No production code +change is needed. + +The runtime reviewer passes 374 focused cases across ten files and verifies the +pinned Next/React CSS ordering with a no-port render. The proof reviewer passes +269 focused cases, five Release corpus cases and seven ADR workflow cases. +Both report zero failures/skips; +neither reruns native/Docker fixtures or claims browser/manual accessibility. +The root checks all 30 relative links/fragments in the two changed skills and +`git diff --check`. Both independent rounds are complete; Step 2 follows. + +### P02d-6 Step 2: Catalog and course pages + +**Implementation — 2026-10-10.** The actual catalog and course routes consume the +shared verified resource loader independently in page and metadata. The obsolete +platform placeholder is removed; live middleware retains default-locale entry. +Synchronous server views expose semantic course/outline lists, distinct empty and +restricted states, actual label language and independent opaque next/restart links. +Restricted marketing never emits lesson counts, links or access-purchase controls. + +Canonical/Open Graph URLs use the verified live host, fixed HTTPS listener and +validated local segments. Course alternates use actual eligible translated slugs; +catalog alternates use enabled locales. Cursor pages are noindex with first-page +canonicals; controlled failures are localized noindex states without resource +alternates. No metadata/page consumer adds another content read or client cache. + +The foundation fixture now copies actual catalog/course routes unchanged and +keeps the isolated P5 transport probe. A separate pagination mode uses test-owned +inventory above 20 items and a fresh unchanged visitor budget; historical seed +declarations stay unchanged. Lesson presentation remains Step 3; full product and +manual accessibility closeout remains Step 4. + +**Validation — 2026-10-10.** The root passes 981 guarded frontend cases (921 web, +60 SDK), zero failures/skips/todos, workspace typecheck/lint and production build. +Both product routes are dynamic; the build reports about 103 kB First Load JS, +which is a local build observation, not a Lighthouse or production performance +claim. All 198 Release architecture cases and seven ADR workflow controls pass, +with zero failures/skips. The solution Release build has zero warnings/errors. +Native ingress verification passes TLS, method/HEAD admission, redirects, +production closure, DEBUG containment and development HMR. + +All 17 focused Release `PublicServerRenderingTests` cases pass, zero failures/skips. +The actual foundation mode observes exactly 52 API calls; the independent default- +pagination mode observes 18. Both stay within a fresh unchanged 60-call visitor +budget. Positive host-scope assertions derive from the seed declaration: Yoga's +mapped host includes tenant-wide and its own organization's published marketing, +while excluding the other organization. These are HTTP/RSC proofs, not browser +or manual accessibility evidence. Formatting, local links/fragments, added prose +and diff checks pass. Review closeout precedes Step 3. + +**Step 2 review round 1 — 2026-10-10.** Fresh GPT-6-astra xhigh runtime/security +and GPT-6.1-sol xhigh proof/corpus agents independently reviewed +`785c8c5..917f9f8`. Both approve with no actionable findings. The runtime reviewer +ran 283 focused frontend cases; the proof reviewer ran the 166 new view/metadata/ +path cases, fixture syntax and diff checks. Both traced adjacent admission and +resource loaders, approved metadata/pagination boundaries and real fixture +accounting. Neither started a build, server or Docker fixture; their pure checks +supplement the implementation validation above. Round 2 remains pending. + +**Step 2 review round 2 — 2026-10-10.** Fresh GPT-6-astra xhigh runtime/security +and GPT-6-sol xhigh proof/corpus agents reviewed `785c8c5..86f8ea1`. Both +independently confirmed a missing course hreflang self-reference: the real API +excludes the current locale from its alternate list, unlike the unit fixture. +The fix explicitly uses the current validated canonical, preserves other eligible +API slugs and refuses a supplied self alias. The corrected DTO fixture and actual +production HTML assert self/translated/reciprocal URLs. Protected-content absence +canaries now derive from seed lesson titles, slugs and values, with a nonempty +control and full HTML/Flight checks. Two current architecture-tree comments now +acknowledge delivered catalog/course views. + +Both reviewers inspected and approve the focused fixes, with no remaining +concrete finding. The root passes 284 focused frontend cases, workspace typecheck, +targeted lint, fixture syntax, scoped formatting and diff checks. All 17 focused +Release production-rendering cases pass again, zero failures/skips, with the +unchanged 52/18 call accounting and new real metadata/containment assertions. +Local links/fragments and added prose checks pass. Step 2 is complete after both +independent review rounds; Step 3 follows. + +### P02d-6 Step 3: Ordered lesson presentation + +**Implementation — 2026-10-10; both independent review rounds complete.** The actual +lesson route consumes the shared verified resource loader in page and metadata, +without a separate content read. Its synchronous view renders the API's ordered +plain-string fields as definition pairs, preserves present empty strings, and +attributes each resolved label's language/direction independently of the content +and UI locales. The course backlink uses the admitted request locale. No field +name, raw body/schema, active URL, HTML or richer primitive becomes visible. + +Empty ready content differs from unavailable/unknown presentation. Unsupported +renderers short-circuit before reading their descriptors and emit at most one +request-local bounded count/state warning; API-reported unavailable definitions +retain their own existing diagnostic. Lesson canonical/Open Graph and eligible +hreflang URLs use validated current and actual translated course/lesson slugs. +Unavailable/unknown presentation is noindex with its eligible canonical preserved. + +All 31 active recommended jsx-a11y rules are blocking through the actual app +configuration. A literal census and per-rule dirty/clean controls detect missing +rules, downgraded severity and vacuous subjects. Synchronous view and page-dispatch +units supplement the production fixture; they do not claim async Server Component +DOM support. Full product/manual accessibility closeout remains Step 4, and the +Accessibility standard stays Adopted. + +**Validation — 2026-10-10.** The guarded frontend suite passes 1,059 tests +(999 web and 60 SDK), zero failures/skips/todos. Workspace typecheck and full web +lint pass. All 18 Release production-rendering cases pass, zero failures/skips. +The new presentation mode observes exactly 46 API calls; foundation and pagination +retain 52 and 18 respectively, each in a fresh unchanged visitor budget. + +Actual English and Yoga lesson HTML/RSC proves ordered text, resolved label +languages, eligible translated metadata and tenant absence. A test-owned successor +revision first leaves the deprecated exact pin unchanged, then changes descriptors +only after switching the lesson pin. Inert script/markup/URL strings, absent +optional fields, empty ready and unavailable content are exercised in one running +process. Setup restores the original body, pin, lifecycle and generation. Both +cross-host and protected lesson requests follow the localized 307→404 chain: +original path segments may occur in Next's redirect routing tree, while private +content stays absent and the final status document omits even the original slug. +Native ports, fixture directories and containers are clean after completion. + +Workspace production build passes with all three content routes dynamic; its +about 103 kB First Load JS is a local observation, not a Lighthouse result. +All 198 Release architecture cases and seven ADR workflow cases pass, zero +failures/skips. Local relative links/fragments, added-prose and formatting checks +pass. Native verification passes TLS, method/HEAD admission, redirects, production +closure, DEBUG containment and development HMR. The solution Release build passes +with zero warnings/errors. No browser or manual +accessibility pass is claimed; full product/manual proof remains Step 4. + +#### Step 3 review round 1 (2026-10-10) + +Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus agents +review `c250677..0be38e8` independently. No Blocker/Major is found. The runtime +review confirms a misleading recovery destination: the translated catalog anchor +reloads the failed lesson. The lesson route and the adjacent course route now +send unavailable/rate-limited recovery to the admitted locale's catalog; invalid +cursor reset retains its original route. Dispatch controls render the synchronous +state and assert translated label and destination together. + +The proof reviewer independently confirms a stale narrow ADR-0051 catalogue row. +It now names the delivered component and actual presentation fixture as +Implemented, with its published counts reconciled. The five broader P6 rules stay +Registered +and Accessibility stays Adopted pending Step 4. Each reviewer passes 164 focused +frontend cases, zero failures/skips; neither runs native/Docker or manual checks. +The root passes 167 focused frontend cases, five Release corpus cases, workspace +typecheck and diff checks after the fixes. A fresh second round follows before +Step 4. + +#### Step 3 review round 2 (2026-10-10) + +Fresh GPT-6-astra xhigh runtime/security and GPT-6-sol xhigh proof/corpus agents +review `c250677..3ac4ee1` independently. Runtime approves with no actionable issue +and passes 173 focused frontend cases. Proof/corpus confirms one defensive recovery +edge: a lesson API validation failure selects cursor reset although lessons have +no cursor. The closed mapping now reserves cursor failure for HTTP 400 catalog/ +course reads; lesson and other-status validation failures select unavailable. +The result matrix tests both boundaries without displaying backend diagnostics. +This is a defensive case, not a reproduced admitted normal-path API failure. + +Both reviewers approve the focused mapping fix with no new concrete finding. The +root passes 176 focused frontend cases, zero failures/skips/todos. Final typecheck +requires the negative test DTO's mandatory empty `fieldErrors`; it is corrected, +and all 53 resource cases and workspace typecheck pass. Diff checks pass. Both +independent rounds are complete; Step 4 follows. +Actual product RTL/fault/concurrency and manual accessibility obligations remain +explicit. + +### P02d-6 Step 4: Product proof and accessibility closeout + +**Complete — 2026-10-10.** The unchanged product routes now +have dedicated `product-isolation` and `product-freshness` modes in +`PublicServerRenderingTests` / `verify-public-rendering.mjs`. P5's synthetic +transport mode and the foundation, pagination and presentation modes remain +separate and mandatory. This step adds proof inventory; it changes no production +route, API, rate budget or historical seed declaration. + +Test-owned Arabic translations use the same ASCII course/lesson slugs on both +hosts, with each course's original organization scope. A four-target content +barrier admits both hosts × English/Arabic before continuing the real API pipeline; +HTML and Flight checks reject opposite-tenant and protected authored markers. +Actual document direction, authored content and independently labelled fallback +UI are observed. Both seeded four-color palettes and effective attribution are +checked independently; one malformed theme must fall back atomically to the +whole local default palette, then recover after restoration. + +Freshness runs in one native server process. Publishing state changes remove the +course from the catalog and send course/lesson detail through the approved local +307→fixed localized 404 chain; restoring publication restores eligible content +without changing the other host. A naturally invalid cursor reaches the real +API. Strict one-shot exact host/locale/path content-boundary faults exercise +429 and 503 page states while bootstrap still uses the real application role and +read-only pipeline. These two faulted Education requests intentionally stop at +the test-owned API boundary; they do not claim production handler execution. + +Known content failures expose bounded translated HTTP 200/noindex views and +accurate cursor-reset/catalog recovery. Next may retain the request's own cursor +in its private Flight routing tree; the visible state/title and recovery link do +not echo it. Problem details and private provider copy stay absent from the +complete response. Fixture mutations restore locales, translations, theme and +publication in `finally`; every mode uses a fresh unchanged visitor budget. + +**Validation and reviews.** The guarded frontend run passes 1,065 cases +(1,005 web, 60 SDK), zero failures/skips/todos. All 20 focused Release +production-rendering cases pass, zero failures/skips. +The new isolation/freshness modes observe exactly 43/52 API calls; the earlier +foundation/pagination/presentation modes retain 52/18/46. Full backend regression +passes as recorded below; both review rounds are complete after their fixes. +Automated checks do not establish manual accessibility. The dated walkthrough +below records keyboard, focus, 320 CSS px reflow and contrast observations; +the maintainer's subsequent VoiceOver confirmation closes the remaining +screen-reader check in the packet closeout below. + +#### Step 4 review round 1 (2026-10-10) + +Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus agents +review `e2b8de4..e073075` independently. Neither finds a Blocker/Major. Both +independently reproduce a narrow containment-test false negative: the injected +Problem Details type URI uses a different marker from the other private fields. +The URI now includes the common private sentinel; both reviewers confirm that a +type-only leak is rejected and a clean response remains accepted. No production +leak is demonstrated. The proof reviewer also confirms stale scaffold-only +wording in README; it now distinguishes implemented public pages from the +Studio/portal scaffolds. Related mutable roadmap, frontend setup and contributor +carriers are aligned without claiming completion or browser evidence. + +The root passes the full Release Docker integration suite: 866 passed, zero +failures/skips. After rebuilding the one-line fixture fix, both product modes +pass again (2/2); exact 43/52 request counts remain unchanged. Earlier current +Release results are 1,705 unit, 198 architecture, four contract and 172 Docker-free +integration cases, all passing with zero skips. TRX counters for the newly run +suites are inspected directly. Reviewers run read-only helper probes, syntax and +link checks; neither claims independent full-suite or manual execution. Both +fresh second-round reviews follow the fix commit. Manual accessibility remains +an explicit packet-completion requirement. + +#### Step 4 review round 2 and automated verification (2026-10-10) + +Fresh GPT-6-astra xhigh runtime/security and GPT-6-sol xhigh proof/corpus agents +review `e2b8de4..b86e20d` independently. No production defect is demonstrated. The +proof review identifies two assertion gaps: the malformed-theme check only sees +primary-token style elements, and fixed-status containment only checks `p6-` +requested slugs. The first now rejects any of the four color-token declarations +in style elements or style attributes. The second rejects every requested course +and lesson slug on the final fixed 404, including historical seed slugs. Own +requested route segments remain permitted in Next's 307 Flight tree, as already +recorded in Step 3; private content remains forbidden on both responses. + +Both reviewers independently verify the fixes with extracted real helpers and +clean/planted controls. The root's ten planted violations are all rejected; +both real product modes then pass again, zero failures/skips, preserving exact +43/52 API call counts. Current-state documents distinguish implemented automated +product proof from pending manual observation. ADR-0027 Amendment 2 is insertion +only and changes no accepted decision. The optional suggestion to revisit the +original faulted resource after catalog recovery is not required: the accepted +G40 catalog-navigation contract is directly exercised and passes. No automatic +retry or broader recovery guarantee is introduced. + +Full Release backend verification totals 2,945 distinct passing cases: 1,705 unit, +198 architecture, four contract, 172 Docker-free integration and 866 Docker +integration. There are zero failures/skips; recorded TRX counters are inspected. +The architecture suite is rerun after the current-status documentation changes. +Guarded frontend verification passes 1,065 cases (1,005 web, 60 SDK), zero +failures/skips/todos. Workspace lint/typecheck, JavaScript syntax, Prettier and +the seven ADR workflow tests pass. Production build evidence remains the earlier +Step 3 build; the review fixes change proof assertions and documentation only. +A local audit checks 2,194 relative links and 666 fragments across 33 changed +Markdown files against `origin/main`, excluding one explicit catalogue-link +template placeholder. No target is missing. This manual script audit does not +claim that CI's file-only link job enforces fragments. Added prose respects the +88-column rule and `git diff --check` passes. + +#### Manual accessibility handoff (2026-10-10) + +A temporary production fixture is prepared from `b86e20d`, with the real API, +`learnstack_app`, read-only frames, actual public routes and test-owned Arabic +long-string content. A separate Brave window opens both institution hosts. The +browser refuses the temporary test certificate before any product page loads; +the computer-use policy requires the user to pass that security interstitial. +The requested handoff is pending. No keyboard, focus, 320 CSS px reflow, contrast +or screen-reader pass is claimed. The temporary server and its owned children +are stopped cleanly before the automated rerun; ports 3000/3011 are free and no +test container remains. Existing developer services are untouched. + +Resume the actual manual walkthrough after the browser handoff, record its +commit/environment/hosts/locales/assistive technology and fix any observed issue +before closing P6 or promoting Accessibility and the five registered P6 rules. +The packet remains in progress; P02d-7 and its Lighthouse job have not started. + +#### Manual browser observations and remaining AT check (2026-10-10) + +The fixture is restarted and both product pages load after the user handles the +temporary certificate interstitial. The tested production routes are unchanged +at `180dde0`; the disposable fixture adds Arabic translations and a 240-character +unbroken `W` value. Observation uses Brave 154.1.96.61 on macOS 27.0.1, with the +real API/application role and native HTTPS ingress. The manual fixture uses the +default entitlement provider; the distinct attribution branches are proved by +the automated product-isolation mode, not by this walkthrough. +The tested hosts are `english.localhost:3000` (`en`, `ar`) and +`yoga.localhost:3000` (`tr-TR`, `ar`). + +- Keyboard-only English catalog → English foundations → Present simple and + Turkish Yoga catalog → Stüdyo temelleri → Ağaç duruşu navigation succeeds. + The skip link becomes visible on first Tab, Enter moves to main content and + subsequent links follow content order. Blue/green focus outlines are visible. +- DevTools explicitly reports a 320 CSS px viewport. English and Turkish + catalogs, the Turkish course and lesson, and both hosts' Arabic lessons reflow + without observed horizontal clipping or overlapping text. The long unbroken + value wraps; scrolling reaches the subsequent labelled fields. Arabic authored + content remains right-to-left while fallback UI/definition labels remain + left-to-right. This is a desktop responsive-viewport observation, not a mobile + device or zoom-conformance claim. +- At 320 CSS px, the English invalid-cursor view has readable status text and a + visible focused reset link; Enter opens the query-free catalog. A missing Yoga + lesson arrives at `/tr-TR/status/not-found`; the Turkish branded status and + focused catalog recovery link fit, and Enter returns to the catalog. HTTP + status/noindex assertions remain automated evidence. + +Contrast is calculated from the exact four-color palettes separately from the +visual observations, using WCAG relative luminance. Ratios against each theme's +background are: + +| Palette | Foreground | Muted text | Primary focus outline | +|---|---|---|---| +| English | 17.740:1 | 7.557:1 | 6.702:1 | +| Yoga | 14.628:1 | 7.357:1 | 6.876:1 | +| Local defaults | 17.853:1 | 4.759:1 | 4.634:1 | + +These exceed 4.5:1 for the text pairs and 3:1 for the focus pair. They do not +constitute a full WCAG audit. Normal viewport/zoom are restored after observation. + +**Real screen-reader evidence is still pending.** VoiceOver is initially off; +its caption-panel preference is already on. Enabling VoiceOver through System +Settings changes the switch to on, but the native app inventory still reports +VoiceOver as not running; no speech or caption output is observed. Direct +VoiceOver app access times out; VO navigation produces no observed output. +The switch is restored to off without changing the caption preference. +Accessibility-tree inspection is not substituted for an +actual screen-reader pass. The maintainer is asked to perform the remaining +English/Turkish catalog → course → lesson screen-reader smoke. P6 and standards +promotion remain pending that evidence; no production defect is demonstrated. + +The maintainer explicitly leaves the real screen-reader check pending on +2026-10-10; this does not waive the accepted completion requirement. The +temporary fixture stops cleanly with child exit 0, ports 3000/3011 are free and +its disposable test container is gone. Existing developer services remain +untouched. Resume this final check in a fresh manual fixture before packet +closeout, standards promotion or the completed-implementation PR handoff. + +#### P02d-6 packet closeout (2026-10-10) + +The preceding pending notes record earlier attempts. The manual fixture is +restarted from unchanged production routes at `180dde0`, using the same +Brave/macOS environment recorded above, real API/application role, read-only +transactions and native HTTPS. The maintainer performs the actual VoiceOver +smoke and explicitly confirms both checks: + +- English (`english.localhost:3000/en`): catalog → English foundations → + Present simple passes without an observed issue. +- Yoga (`yoga.localhost:3000/tr-TR`): catalog → Stüdyo temelleri → Ağaç duruşu + passes without an observed issue. +- On both flows, headings, links, skip navigation and lesson field label → value + order are understandable. The maintainer also confirms reading the missing-page + and invalid-link messages and following their catalog recovery links. + +This is maintainer-reported real VoiceOver evidence, separate from the agent's +earlier keyboard, focus, 320 CSS px desktop reflow and calculated contrast checks. +It does not claim a full WCAG audit, mobile-device test, zoom-conformance result +or Arabic screen-reader pass. The owned fixture stops cleanly with child exit 0; +ports 3000/3011 are free, its disposable container is removed and existing +developer services remain untouched. + +All four implementation steps and both fresh review rounds per step are complete. +The automated totals and scope remain those recorded above: 2,945 passing backend +cases and 1,065 passing guarded frontend cases, zero failures/skips/todos. +The manual closeout permits Accessibility Standards to become Active and the +five P6 catalogue entries to become Implemented; the automated checks named by +those entries are already present. The closure change updates documentation only. +Final corpus/link validation and two fresh documentation review rounds complete +before the implementation PR is handed to the maintainer, as recorded below. + +Closeout validation passes all 198 Release architecture cases, including the +corpus guards, with zero failures/skips, and all seven ADR-workflow tests. A local +inline-link audit, excluding fenced and inline code, checks 2,217 relative links +and 678 fragments in 34 Markdown files changed against `origin/main`; no file or +fragment is missing. This remains a manual audit, not a new CI anchor check. +Added prose and diff checks pass. No production code or test changes accompany +this closeout. + +Fresh GPT-6.1-sol high corpus and GPT-6-astra high evidence/governance reviewers +independently review `27a02ba..7d98228`. Both approve with one verified Minor: +the catalogue's current status-consistency assertion quotes the former +nineteen/three split. It now references the index-owned counts instead. Both +reviewers verify the five promoted entries against existing tests, 165 catalogue +rules (107 architecture, 58 outside), twenty Active/two Adopted standards, +maintainer-attributed VoiceOver scope and insertion-only ADR history. Neither +claims new broad runtime execution. + +Fresh GPT-6-sol high consistency and GPT-6.1-sol high history/evidence reviewers +independently review `27a02ba..2b6dbb4` after the fix. Both approve without findings. +They verify current status, catalogue and standards counts, bounded manual +evidence, preserved historical records and insertion-only ADR changes. The +history reviewer independently checks 1,832 relative links and 565 fragments in +the 23 closeout Markdown files; none is missing. Neither reruns a broad runtime +suite. Both closeout review rounds are complete. + +P02d-6 implementation is complete; PR review and merge remain separate. P02d-7 +owns `make demo`, the browser/full-stack CI harness, Lighthouse activation and the +Phase 02d exit checks. Its decision pass must close G20/G33/G38/G44/G45's remaining +parts before implementation. Full Playwright/axe and the expanded renderer/Studio +remain Phase 06; no later packet is delivered by this closeout. + +#### P02d-6 external-review remediation (2026-10-10) + +The external review of PR #27 at `47f9c12` approves without Blocker/Major +findings. Its three Minors and three documentation comments are rechecked against +the current tree; all remain valid and receive bounded fixes: + +- The cross-tenant course probe derives a foreign-only published slug and locale + from `SeedData`, not a second JavaScript literal. The other host's asserted + catalog keeps a visible control for that course. C# independently checks the + refused API path, locale and 404; the shared slug cannot serve this purpose + because it exists in both tenants. Normal/missing course and hidden lesson + checkpoints also assert API status. Next's 307/Location/no-store/404 chain + remains owned by the Node artifact; the API observer does not observe Next + response headers. The broad 1–59 check remains the visitor-budget ceiling; + existing exact per-mode counts and checkpoints remain unchanged. +- The malformed-theme proof removes its redundant root-style-attribute check. + Its existing scan still rejects four-color token declarations in any style + element or inline style, and checks the complete compiled default palette. These HTML + proofs inspect emitted CSS; they do not measure a browser's computed cascade. + The earlier contrast numbers remain calculated palette ratios. +- Missing content without an admitted locale fails through `notFound()` rather + than constructing `/null/status/not-found`; a defensive unit control covers + the otherwise unreachable inconsistent request. +- Error Handling records the delivered mapping and links Steps 1–3. README + inventory distinguishes the public pages from Studio/portal scaffolds. All + five P6 rule headings use H3 under H2; the corpus reader admits H3/H4 with + mixed-level planted controls so no rule falls out of the catalogue census. +- Failure containment uses each scenario's actual private code, retaining the + common private-value/message-key canaries. The ICU parser suggestion does not + require a dependency change: the lockfile uses 3.5.18 for both the direct + structural parser and `use-intl`'s runtime `intl-messageformat` dependency. + Build-time `icu-minify` uses 3.5.21 separately; existing actual formatting and + production-build controls remain mandatory. No general parser-parity claim is + introduced. + +Validation passes 1,066 guarded frontend cases (1,006 web, 60 SDK), lint and +typecheck; 198 Release architecture cases; and all 20 real renderer/cleanup +integration cases, including all six production modes. All report zero failures +and skips/todos where applicable. The H4-only parser mutation fails the mixed +heading control; the restored parser passes the full architecture suite. Format +verification and diff checks pass. A local audit of the four changed Markdown +files checks 1,017 relative links and 353 fragments without a missing target. +No broad backend-suite rerun is claimed by these focused local checks. + +Two fresh read-only remediation reviews approve `47f9c12..e871e88` on 2026-10-10: +GPT-6.1-sol at high effort, then GPT-6-astra at high effort. Both report no verified +actionable findings after standards, isolation, correctness, test-proof and +documentation checks. Neither reviewer claims a runtime-suite rerun. The +[PR #27 description](https://github.com/HodeTech/LearnStack/pull/27) owns the +exact-head CI evidence. + +#### P02d-6 systematic-review decision package (2026-10-10) + +**Maintainer response recorded — 2026-10-10.** The two external reports at +`ed6f81e` are review data, not new authority. Rechecks confirm guidance/status +drift, ordinary static source-fence gaps, missing dirty/clean response controls +and a second-bootstrap failure-classification gap. The exact-response-owner +design remains Proposed; the Open Graph and security maintenance parts below +are separately approved. + +The existing G40 content-error HTTP 200/noindex and cursor-free canonical/noindex +policies are accepted choices, not implementation drift. Google's +[pagination guidance](https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading) +recommends individual canonicals; its +[status guidance](https://developers.google.com/crawling/docs/troubleshooting/http-status-codes) +explains temporary-error and soft-404 tradeoffs. These recommendations justify +recording the tradeoff, not silently reopening the approved policies. + +G10 explicitly defines editable base64url JSON seek cursors without confidentiality +or authentication. G40's opacity means the renderer does not interpret the token; +it does not hide anchor UUIDs from visitors. Scope/eligibility remains independently +enforced. Encryption, MAC rotation or server-side cursor state would need a new +decision and is not a correction to this PR. + +##### Maintainer decisions (2026-10-10) + +1. **Second bootstrap — design requested; not accepted.** The maintainer did not + approve the neutral 500 proposal and requested a fuller response-owner design + preserving exact 429/503. Revised proposed + [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md) selects one + live middleware-owned read and an immutable native request-local snapshot for + RSC. This removes the second-read failure and explicitly proposes two normal + document calls / three followed-missing calls in place of three/five. It also + proposes a closed Retry-After bound. These ownership, DTO handoff and accounting + changes await approval; no dependent code or current-contract change is made. + Independent design review rejected response-write interception as fragile; + the revised concrete ALS singleton design has no remaining architecture + finding, subject to actual Next 15.5.27 feasibility and isolation proofs. +2. **Open Graph locale — approved.** Emit `language_TERRITORY` only when the + admitted tag has an explicit two-letter territory and no script/variant + information would be silently discarded. Omit unrepresentable locale/alternate + properties rather than inventing a territory. `tr-TR` becomes `tr_TR`; + `en`, `tr`, `zh-Hant` and numeric-region tags are omitted. Document language, + route and hreflang keep + their exact BCP-47 tags. The [protocol](https://ogp.me/) makes these properties + optional; omission can leave consumers applying their own default. This adds + the bounded G40 projection and qualifies Standards 08's blanket rule. +3. **Security maintenance — approved.** Pin Next and eslint-config-next to + 15.5.27, disable the unused image optimizer, inspect/patch affected transitive + versions within compatible bounds, and re-prove native ingress and actual + production HTML/RSC. + The fresh audit reports 46 findings (2 critical, 28 high, 15 moderate, 1 low), + not 46 reachable public flaws. The AVIF + [advisory](https://github.com/advisories/GHSA-2xp9-vwfh-vxw4) affects the current + dependency version; attacker-controlled image input is not demonstrated. + The [15.5.27 metadata](https://registry.npmjs.org/next/15.5.27) supplies a + compatible 15.x backport. A Next bump alone does not clear transitive findings; + record each remaining advisory's actual input path and maintenance disposition. + +The approved ADR-0054 maintenance note is appended only after passing replacement +proofs. Its exact text is: + +> **Amendment 7 — Next security maintenance (2026-10-10).** The current verified +> runtime pin is Next 15.5.27 with matching eslint-config-next. The signed raw +> target, full-URL RSC projection and equivalent redirect-query contract are +> unchanged. The unused image optimizer is disabled. P02d-6's remediation record +> owns the replacement native/production proofs and dependency triage; historical +> 15.5.18 observations remain unchanged. + +No speculative native-addon/install-script policy is introduced. Existing exact +pins, frozen lockfile and real builds remain mandatory. Dependency patching does +not establish air-gapped packaging support. + +##### Remediation plan and review boundaries + +1. Correct current guidance/status carriers and skill examples. Strengthen the + existing response assertions, source-retention/prefetch fences, production + formatter-path tests and applicable accessibility controls. Align decimal + limit parsing and closed cursor-error classification with existing contracts. + These corrections need no new behavior decision. +2. Implement the approved G40 Open Graph projection. Separately prepare the fuller + exact-bootstrap response-owner design; its implementation waits for approval. + The eventual approved design must prove second-bootstrap faults through the + actual production fixture without weakening provenance, read-only/RLS or the + admitted content-error policy. +3. Apply the approved compatible security patches and close unused image + optimization; re-run affected full/native/real-API suites, audit, formatting + and local link/fragment checks. Record fresh exact-head PR CI. Append the + approved maintenance note only after its replacement proofs pass. + +Each group is committed and receives two fresh independent review rounds, with +verified findings corrected before the next group. All work stays on development. +The maintainer's earlier browser/VoiceOver report remains attributed to its tested +commit; later defensive/proof changes do not imply a new manual pass. P02d-7 and +Phase 06/11 retain their explicitly named browser, full accessibility and hardening +work. This package makes no new passing runtime or merge-readiness claim. + +##### Remediation group 1 — existing-contract corrections + +**Implemented; both review rounds and focused fix verification complete — +2026-10-10.** No approval-gated decision above is implemented by this group. +ADR-0055 remains Proposed. + +The Step 1 status and current i18n/theme carriers now match delivery. Skills use +locale-bearing public folders, the shared resource loader, supported Next page +exports and explicit catalogue wiring. Future block/entitlement sketches are +labelled as targets. Phase 06 explicitly owns localized section names and full +Playwright/axe completion; Phase 11 explicitly owns frontend telemetry. + +The production response predicates are shared with dirty/clean companions: +inline Flight escaping, entity-encoded attributes, opposite/protected values, +whole/partial palette emission, attribution and localized status metadata. +Emitted viewport checks reject zoom restrictions; they are not browser zoom proof. +The two unused ICU sentinels detect unchanged complete catalogues, not arbitrary +partial copy leakage. Static import fences supply the separate client boundary. +The bounded source analyzer now covers retained local factories/collections, +module mutable bindings, static/global writes and Next Link/router imports. +Admitted Studio/portal scaffolds are render roots and explicitly noindex. + +Direct tests exercise the actual request configuration and public UI wrapper; +callsite census follows ordinary aliases/Promise tuples and requires a nonempty +production subject. Actual lint controls cover image, object, area and image-input +alt text. A prefixed style-breakout value tests the theme regex's start anchor. +Loading uses a status live region. Counts explicitly describe the current page. +Positive decimal limits saturate at the API bound without rejecting long valid +values; only exclusive owned-cursor errors with a supplied cursor select reset UI. + +The following review claims do not justify changing accepted behavior: + +- Cursor confidentiality, self-canonical pagination and content-error HTTP status + are already decided; their tradeoffs and pending approval boundaries are above. +- Studio/portal bootstrap is the admitted scaffold contract, not an implemented + authentication surface. Their full UI remains Phase 04/06/07. +- Missing error-label context is outside the current provider-wrapped public + tree. No whole catalogue or hardcoded fallback is added to its Client Component. + The assertion that `reset` can never recover is not reproduced; the supported + framework reset and catalog recovery link remain. +- Security headers remain Phase 11's explicit scope. Arbitrary reflective/eval + source analysis, a complete WCAG audit and browser-computed theme/zoom proof are + not newly claimed by the strengthened bounded controls. +- ADR-0027's Decision explicitly authorizes the contract below it; the Context + placement does not make that contract nonbinding. Accepted history is preserved. +- Packet 10's 19/3 standards count is historical; its timestamp is now explicit. + Phase 06's P6 review/merge-pending statement is still true for this open PR. +- The review skill's conditional manual-evidence completion gate remains valid + for future work. Branding has no authored-language field; inventing a language + for the institution name would not establish correct pronunciation. + +Validation at `cc626e8`: the guarded frontend runner passes 1,197 cases (1,137 web, +60 SDK), with zero skips/todos; workspace lint/typecheck pass. Five Release corpus tests +and seven ADR-workflow cases pass. The final focused Release integration run passes +20 cases: six real production Next/native HTTPS/API/PostgreSQL modes and fourteen +cleanup/log-control companions, with zero skips. No backend full-suite rerun or new +manual accessibility pass is inferred from these focused checks. + +**Round 1 — fresh independent reviews of `ed6f81e..cc626e8`.** GPT-6-astra +(high) reviewed runtime/source-boundary behavior; GPT-6.1-sol (high) reviewed +proofs, guidance and documentation. Three findings were verified: shorthand +factory returns and destructured shared-storage aliases escaped the bounded +retention fence, and the attribution dirty control failed on its palette before +reaching attribution. Four new dirty cases fail before the retention fix; they +and two request-local clean cases pass afterward. The attribution control keeps +a valid palette and checks the specific failure in both entitlement directions. +Focused validation passes all 263 boundary cases and 36 response-helper cases; +web typecheck passes. Neither review claims a Docker/full-suite/manual rerun. + +**Round 2 — fresh independent reviews of `ed6f81e..69b382a`.** GPT-6.1-sol +(high) reviewed runtime/source boundaries; GPT-6-astra (high) reviewed proofs and +documentation. The proof/documentation review approved. Two further bounded +retention gaps were verified: resolved local object member factories and +destructured closure captures. Seven additional dirty controls fail before the +fix, while seven request-local or pure-value controls remain clean. The fix follows +literal members and selected named/indexed binding values, without treating an +unrelated sibling collection as a captured value. All 277 boundary cases and web +typecheck pass. Fresh independent verification of `69b382a..bdb88bb` approved +without actionable findings and independently passed all 277 boundary cases. +The verifier confirmed the seven dirty cases escape the prior analyzer and the +selected-binding clean controls remain clean. This closes group 1. + +##### Remediation group 2 — approved Open Graph locale projection + +**Implemented; both independent reviews complete — 2026-10-10.** The approved +G40 addendum above +separates Open Graph's optional locale format from BCP-47 identity. Only canonical +language plus an explicit two-letter territory is projected; script, variant, +extension, bare-language and numeric-region tags are omitted. Eligible and enabled +alternates keep their exact URLs and hreflang while unrepresentable Open Graph +alternates are omitted. No additional API reads or territory inference is added. +Unit projections and actual production-document checks cover both conversion and +omission. All 61 metadata cases and web typecheck pass. On the concurrently +patched Next 15.5.27 runtime, the guarded frontend suite passes 1,229 cases +(1,169 web / 60 SDK), zero skips/todos. The actual API/PostgreSQL production-render +suite passes all 20 cases, zero skips; its first run exposed an overly narrow +fixture-alternate expectation, corrected before this passing run. The production +build passes. Two independent review rounds follow the implementation commit. +ADR-0055 remains Proposed and has no dependent code in this group. + + +**Round 1 — independent review of `ca03942..75c3e61`.** GPT-6.1-sol (high) +independently passed 61 metadata cases and web typecheck. It found no production +projection error, but verified that the runtime alternate loop accepted missing +and ineligible serialized alternates. The corrected shared predicate compares +complete current/alternate arrays against the representable eligible hreflang +set. Six committed dirty/clean controls cover missing, ineligible, duplicate, +malformed and invented territory output. All 103 metadata/response-helper cases +pass. + +**Round 2 — fresh independent review of `ca03942..f16d937`.** GPT-6-astra +(high) approved without verified findings and independently passed the same +103 cases. The actual API/PostgreSQL fixture then passed all 20 cases, zero skips, +with the complete serialized-array predicate active. This closes group 2. + +##### Remediation group 3 — approved security maintenance + +**Implemented; replacement proofs and both independent review rounds pass — +2026-10-10.** The approved +paired Next/eslint-config-next 15.5.27 update disables unused image optimization. +Compatible lockfile patches cover PostCSS 8.5.23, sharp 0.35.5, js-yaml 4.3.2, +brace-expansion's existing major lines, nanoid 3.3.18, source-map-js 1.2.2, +browserslist 4.28.7, baseline-browser-mapping 2.11.0 and selector-parser 6.1.3. +Next pins an older PostCSS exactly, so only its dependency edge has a permanent +8.5.23 override. Redocly core 1.34.20 remains within the SDK's existing range and +updates its exact js-yaml dependency. Normal and frozen installation pass. + +Comparable fresh audits distinguish deployment from development tooling: + +| Scope | Before maintenance | After compatible patches | +|---|---|---| +| Production | 46 findings: 2 critical / 28 high / 15 moderate / 1 low | 2 findings: 1 high / 1 moderate | +| Full workspace | 59 findings: 5 critical / 32 high / 21 moderate / 1 low | 11 package/advisory records: 3 critical / 2 high / 6 moderate; 10 distinct GHSAs | + +The original 46-finding report was production scope. The full baseline uses the +pre-maintenance committed manifests/lockfile in a disposable directory. Neither +comparison claims every advisory is a reachable public flaw or a clean audit. +Current residual input paths and dispositions are: + +| Advisory | Current input and disposition | +|---|---| +| [GHSA-vfj7-8cjw-p6xm](https://github.com/micromatch/braces/issues/70) | Braces processes checked-in build/lint/watch globs through Tailwind/Next ESLint. No fixed release exists; retain visibility and reassess upstream or any request-supplied glob use. | +| [GHSA-rj75-hqrm-r3gf](https://github.com/postcss/postcss-selector-parser/security/advisories/GHSA-rj75-hqrm-r3gf) | Selector-parser 6.x processes checked-in CSS through Tailwind/PostCSS Nested. Fix 7.1.6 exceeds their declared range; no request-time selector input is identified. Track an upstream backport or separate compatible parent migration. | +| [GHSA-67mh-4wv8-2f99](https://github.com/evanw/esbuild/security/advisories/GHSA-67mh-4wv8-2f99) | Esbuild's serving feature through Vite/Vitest is not used by repository scripts. Proposed test-toolchain migration below removes the affected branch. | +| [GHSA-4w7w-66w2-5vf9](https://github.com/vitejs/vite/security/advisories/GHSA-4w7w-66w2-5vf9), [GHSA-v6wh-96g9-6wx3](https://github.com/vitejs/vite/security/advisories/GHSA-v6wh-96g9-6wx3), [GHSA-fx2h-pf6j-xcff](https://github.com/vitejs/vite/security/advisories/GHSA-fx2h-pf6j-xcff) | Vite development HTTP/editor/file-serving paths; repository scripts expose no Vite dev-server workflow. Windows-specific prerequisites are not a blanket exemption. Migration below replaces Vite 5. | +| [GHSA-5xrq-8626-4rwp](https://github.com/vitest-dev/vitest/security/advisories/GHSA-5xrq-8626-4rwp), [GHSA-82fw-gwwq-j7x9](https://github.com/vitest-dev/vitest/security/advisories/GHSA-82fw-gwwq-j7x9) | Vitest UI/API/mocker paths; scripts use run mode without UI/API/browser configuration or public mocker exports. These remain reported findings; migration below replaces both Vitest/mocker branches. | +| [GHSA-5gmw-xhrv-c9v3](https://github.com/tinylibs/tinypool/security/advisories/GHSA-5gmw-xhrv-c9v3), [GHSA-85c8-ppgw-ccpr](https://github.com/tinylibs/tinypool/security/advisories/GHSA-85c8-ppgw-ccpr) | Test-worker construction/options need prior prototype pollution and applicable attacker-controlled loading input; none is identified. Migration below removes tinypool rather than forcing an incompatible major into Vitest 2. | + +The P02d-6 remediation owns this triage and the approval request below. The +maintainer owns any remaining backport/parent-migration decision; applicable +Security Standards patch deadlines remain unchanged. No test-toolchain major is +silently included in the already approved compatible-patch package. + + +Replacement validation passes on Next 15.5.27: frozen install; production build; +workspace lint/typecheck; guarded frontend **1,235 cases** (1,175 web / 60 SDK), +zero skips/todos; and all **20** actual API/PostgreSQL production-render cases, +zero skips. All nine pinned SWC emission cases run against the installed patch. +Native ingress passes TLS, GET/HEAD, query projection/redirects, DEBUG containment, +production upgrade closure and retained HMR. The image proof decodes a valid raw +PNG, sees disabled GET/HEAD 404, enables only a disposable copied configuration, +then decodes optimized 200 and proves the same disabled predicate rejects it. +All **19** native lifecycle/negative controls pass. No shared build is mutated. +The approved ADR-0054 maintenance note is appended after these replacement proofs; +historical 15.5.18 observations remain unchanged. Two independent review rounds +follow the implementation commit. No new manual browser/VoiceOver pass is claimed. + +**Round 1 — fresh independent reviews of `f16d937..3f6f37f`.** GPT-6-astra +(high) reviewed dependency ranges, resolved versions, audit triage and ADR history; +GPT-6.1-sol (high) reviewed runtime proof controls, copied-build ownership and +cleanup. Both approved without verified actionable findings. These were read-only +reviews; syntax and diff checks pass, but neither claims a new runtime-suite run. +The full Release architecture suite also passes all 198 cases, zero skips; all +seven ADR-workflow cases pass. The second independent review round follows. + +**Round 2 — fresh independent reviews of `f16d937..05a4313`.** GPT-6.1-sol +(high) independently checked dependency ranges, lockfile deltas and saved audit +totals; GPT-6-astra (high) checked native proof falsifiability, runtime config +loading, cleanup and preserved gates. Both approved without verified actionable +findings. They passed syntax/diff checks and inspected installed packages/source; +neither performed another build or runtime-suite run. A local audit of the 22 +changed Markdown files checks 1,703 relative file targets and 567 fragments, with +inline/fenced examples excluded and no missing targets. Added prose respects +88 columns; CI's existing link gate still checks file existence only. This closes +the approved compatible-security group. ADR-0055 and the separate test-toolchain +migration remain pending approval and have no implementation in these commits. +Fresh exact-head PR CI remains the final validation step. + +###### Test-toolchain migration — approved (2026-10-10) + +The separately reviewable candidate pins Vitest **4.1.11** and Vite **6.4.3** in +both web and SDK, resolving esbuild **0.25.12** within Vite's range. Vitest 4 removes +tinypool; no tinypool major override is proposed. React plugin 4.7.0, jsdom 26.1.0, +Node 22.23.1, TypeScript 5.6.3 and React 19 remain. Narrow compatible resolution +pins may keep Vitest on Vite 6 and Vite on the selected esbuild patch; Vite 8 must +not appear as an accidental second tree. + +The [official migration](https://v4.vitest.dev/guide/migration) changes pool and +mock-constructor behavior. The existing arrow `Intl.Locale` constructor mock +must become a constructible function/class and still prove its intended error. +Inspect mock cleanup; retain explicit Testing Library cleanup and `globals:false`. +The JSON reporter keeps the counters/status/file fields consumed by the guarded +runner; all its skip/todo/missing/omitted-file negative controls must still fail. + +Before completion: frozen install, resolved graph/advisory audit, guarded full +frontend suite, lint, typecheck and production build; two independent review +rounds and verified fixes. Preserve package/control deadlines and all existing +proof gates. The maintainer separately approved this major test-toolchain upgrade +on 2026-10-10; implementation and fresh two-round review follow that approval. +It accepts no new architecture/ADR contract. The earlier compatible-security +group's pending-approval statement records its own commit-time boundary. + +###### ADR-0055 draft review reconciliation (2026-10-10) + +The maintainer's review is a request for draft corrections, not ADR acceptance. +The revised Proposed record names ADR-0054's unchanged Retry-After instruction and +limits the proposed qualification to renderer forwarding; API refusal selection +and metadata stay unchanged. It also names ADR-0054's deferred request-local reuse +and ADR-0027's admission loader, aligns the title with the existing filename, and +requires canonical Registered catalogue rules before dependent production code. + +Next 15.5.27 native-to-middleware-to-RSC context propagation must be demonstrated +before acceptance. An isolated feasibility experiment is research, not permission +to ship the proposed runtime. Maintainer approval is still required after review. + +The draft first appeared in mixed fix commit `cc626e8`, was revised in `bdb88bb`, +and received its decision-scoped commit in `ca03942`. That draft packaging is +recorded rather than rewritten. No Accepted ADR-0055 decision or dependent runtime +exists; acceptance-before-production implementation has not been bypassed. + +ADR-0054's original Next 15.5.18 pin and retired test name were accurate at +acceptance. Preserve that history: its existing Amendment 7 identifies the +current 15.5.27 maintenance baseline. No accepted-body erratum is appropriate. + +Two fresh independent reviews of `46bc8a4..2bf9d57` approve these draft corrections +without verified findings: GPT-6.1-sol (high), then GPT-6-astra (high). Both checked +the accepted sources, actual duplicate reads, historical pin/test and five changed +relative links/fragments. Neither claims a runtime feasibility proof. Seven +ADR-workflow tests pass. A local three-document audit resolves 442 relative +targets and their fragments; added prose and diff checks pass. + +##### Remediation group 4 — approved test-toolchain migration + +**Implementation recorded before independent review — 2026-10-10.** Both web +and SDK pin Vitest 4.1.11 and Vite 6.4.3. Narrow overrides keep Vitest on Vite 6 +and Vite on compatible esbuild 0.25.12; the existing Next/PostCSS override remains. +The resolved graph removes Vitest 2, Vite 5, tinypool and vite-node, without +introducing Vite 7/8. Runtime dependencies and application behavior are unchanged. + +The `Intl.Locale` mock uses a constructible function and proves that the intended +RangeError was thrown by identity, preventing an accidental constructor TypeError +from satisfying the fallback case. Configurations, explicit cleanup, globals, +runner/report validation, package/control deadlines and CI gates stay unchanged. + +Frozen installation and 46 focused locale/runner cases pass. The guarded frontend +suite passes all 1,235 cases (1,175 web / 60 SDK), zero skips/todos; workspace lint, +typecheck and production build pass. The Release architecture suite passes 198 +cases, zero skips. The full audit falls from 11 records / 10 distinct advisories +to two records / two advisories: zero critical, one high and one moderate. The +production audit retains the same two residuals already triaged in group 3; +neither audit is described as clean. Independent review rounds follow this commit. + +**Round 1 — independent review of `2bf9d57..0761d84`.** GPT-6.1-sol (high) +reviews dependency compatibility and approves without verified findings. A fresh +resolved graph matches the saved graph and installed lock; surviving package +records and runtime dependency declarations are unchanged. GPT-6-astra (high) +reviews runtime/test proofs and also approves without findings. It independently +passes 110 focused locale, runner, caller, HMR and cleanup cases, verifies the +26-web/one-SDK file census, and checks the installed JSON reporter semantics. +Neither reviewer claims another full frontend/build/architecture execution. + +**Round 2 — fresh independent review of `2bf9d57..a97f6ee`.** GPT-6-astra +(high) approves the dependency/documentation lens without verified findings, +independently matching the installed lock and fresh graph to the committed tree. +GPT-6.1-sol (high) approves runtime/proof integrity without findings. It passes +178 focused cases, including 68 shuffled DOM/request/mock cases, and validates +both reports with the actual repository validator. Its direct installed-spy +control distinguishes the intended RangeError from the old arrow's TypeError +and proves restoration of native locale behavior. No full-suite, build, install +or audit rerun is attributed to these reviewers. This closes group 4; fresh +exact-head CI follows. ADR-0055 remains Proposed and unimplemented. + +##### ADR-0055 isolated feasibility observation (2026-10-10) + +The root independently replays a disposable native HTTPS / production Next +15.5.27 fixture on Node 22.23.1. All 37 requests pass the propagation matrix: +eight simultaneous identical HTML, eight Flight, eight prefetch, eight host/locale +HTML/Flight combinations, HEAD and HTML/Flight missing/error cases. Native, +middleware and RSC compare actual holder/store references; request IDs are +observations, not context lookup keys. Unbound and duplicate-ALS controls each +refuse with 503, without snapshot publication or RSC consumers. Prefetch runs +middleware without dynamic RSC consumers in this synthetic fixture. + +Valid HEAD exposes a lifecycle caveat: Next can resume an already-started +not-found component after response finish. The store is correctly disposed, its +snapshot cleared, and late access refused; Next logs the bounded fixture error. +ADR-0055 now explicitly requires disposal checks after awaits and neutral +production diagnostics. Response finish does not imply synchronous reclamation +of already captured local references or completion of all React work. + +The experiment uses synthetic site publication. It proves neither real API/ +provenance/RLS nor the proposed two/three-call accounting, cancellation, active +shutdown, keep-alive, HMR or browser navigation. Certificates, children and owned +build output are cleaned; a local reproducible source/results bundle is retained +for maintainer inspection. No experiment source enters the production tree. +This supports feasibility of the proposed same-process design only. ADR-0055 +remains Proposed; dependent production implementation still requires approval +and all named production proofs. + +**Independent feasibility review — two rounds.** GPT-6-astra (xhigh) checks +the fixture/driver, retained diagnostics and root replay. It verifies one wording +gap: the RSC context-error paragraph also covered expected post-finish HEAD work. +Commit `5b5f5a9` limits that paragraph to active requests; the reviewer rechecks +and approves the narrow feasibility claim without remaining findings. It does +not characterize observation-only summary fields as comprehensive mutation tests. +GPT-6.1-sol (high) then independently reviews `22a9775..5b5f5a9`, confirms the +matrix and active/late distinction, and approves without findings. Both reviews +inspect evidence rather than run another build. The root's separate replay passes +the same matrix and both negative controls. No review constitutes ADR acceptance. + +##### ADR-0055 acceptance and implementation plan (2026-10-10) + +**Accepted — 2026-10-10; implementation not yet delivered.** After the isolated +Next 15.5.27 feasibility experiment and two independent feasibility reviews, the +maintainer explicitly approves revised +[ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md) and dependent +implementation. The earlier draft/review/feasibility notes record their own +pending-approval boundaries; this dated acceptance supersedes those current-status +readings without rewriting them. The decision-only acceptance commit precedes +production changes. All work stays on development. + +**Bounded G40 supersession.** The original G40 acceptance and its three/five-call +delivery remain historical. ADR-0055 replaces only duplicate bootstrap ownership, +request-local snapshot handoff and call accounting: middleware owns one live site +read and exact neutral 404/429/503; RSC re-verifies provenance and consumes the +immutable snapshot bound to that native request. A completed product document +costs two API calls, a fixed status/scaffold document one, and a followed missing +detail three. Actual HEAD/RSC/prefetch and Flight fallback counts require separate +production proof. Changes after bootstrap appear in the next request's site value; +content eligibility still runs live at the API. + +Renderer Retry-After forwarding accepts only eligible parsed integer zero-to-sixty +delta-seconds on supported 429/503 cases. Ineligible values are omitted without +clamping or invention. API refusal selection/metadata, numeric quotas, content +HTTP 200/noindex, cursor SEO and the local missing-detail 307-to-404 chain remain +unchanged. ADR-0053/0027/0054 carry dated bounded supersession navigation. + +Five canonical rules are Registered before code in the +[catalogue](../standards/21-architecture-tests-catalogue.md#p02d-6-request-local-bootstrap-admission-controls): +active native context, exact bootstrap HTTP responses, one immutable per-request +snapshot, native lifecycle completion and preserved production ingress boundaries. +Registered status is a commitment, not an executable or passing-test claim. + +###### Implementation and review sequence + +1. **Native context, facade and lifecycle units.** Add the sole versioned native + ALS holder and server-only facade, binding verified host/peer/method/target to a + fresh pending/ready/closed request store. Publish a bounded deeply immutable + snapshot only once; cancel/clear exactly once on finish/close/shutdown. Unit + controls cover missing/duplicate/mismatched context, abort, late publication, + deep immutability and overlapping identical requests. Extend source fences only + for this explicit owner/facade boundary. Commit, run fresh independent review + round 1, verify/fix/commit findings, then use new reviewers for round 2 and + verify/fix/commit its findings. +2. **Middleware publication and RSC consumption.** Middleware owns one bootstrap, + bounded Retry-After and refusal/redirect terminal states; RSC/resource/i18n + consumers use only the verified ready snapshot and native cancellation signal. + Remove the second site read without changing locale authority or content-state + policy. Add mapping and fault controls, update affected unit expectations, and + commit. Complete the same two fresh independent review/fix rounds before Step 3. +3. **Actual production proof and closeout.** Exercise the shipped native launcher, + pinned Next and real API/PostgreSQL as `learnstack_app`: first-wire refusals, + zero Education/theme after failure, exact counts, identical/differing concurrent + host/locale requests, HTML/RSC/prefetch/status/scaffolds, next-request freshness, + keep-alive, abort/shutdown/HMR and valid HEAD late work with neutral diagnostics. + Retain stock-launch, method/upgrade, exempt asset/health, no build bootstrap and + private-value containment controls. Plant failures beside clean controls. Run + affected full suites/build/lint/typecheck, catalogue and local link/fragment + checks; commit and complete both fresh independent review/fix rounds. Only then + mark proven rules Implemented, update delivery navigation and the existing PR, + and verify fresh exact-head CI. Merge remains a maintainer action. + +No step or review round is complete at acceptance. Missing propagation or lifecycle +proof cannot be replaced by another bootstrap, DTO headers, shared data or an +unapproved response owner; a required architectural change returns for a new +decision. P02d-7 and Phase 06/11 retain their named browser/accessibility/hardening +work. No new manual browser/VoiceOver result is implied by this approval. + +###### ADR-0055 Step 1 — Native request context and lifecycle + +**Implemented — 2026-10-10; both independent review rounds complete.** The native +launcher installs the sole versioned ALS holder before Next preparation and wraps +each admitted HTTP delegation in a fresh verified binding. Server-only consumers +retrieve the existing holder lazily; no bundled runtime constructs a replacement. +The holder copies only the closed public Site fields, bounds the copied snapshot +to the existing decoded-response ceiling and freezes its nested values. Refusal, +finish, close, abort and shutdown prevent later publication/use and release the +holder's snapshot reference and owned listeners. Request-input `close` and handler +promise resolution do not terminate the response lifetime. + +Forty-eight focused unit cases cover state/binding conflicts, source mutation, +the inclusive UTF-8 byte ceiling, eight overlapping identical requests, escaped +handles, singleton descriptor checks and completed HEAD/late work. Source fences +refuse runtime imports of the native owner, facade fallback construction and +Client Component access, with dirty/clean controls. The shared transport limits +retain the existing ten-second and 8 MiB values. + +The guarded frontend run passes **1,284** cases: **1,224 web and 60 SDK**, with zero +skips/todos. Typecheck, lint, production build and all **198 architecture cases** +pass. Native ingress verification and all **19 setup/cleanup controls** pass, +including production upgrades, development HMR, signal/IPC/EPIPE and owned +fixture cleanup. These unit/native-foundation results do not claim the complete actual +middleware-to-RSC handoff: Step 2 still owns publication/consumption and removal +of the second bootstrap; Step 3 owns actual product integration and lifecycle +proofs. The five new catalogue rules remain Registered until that proof closes. + +**Review round 1 — `166ffb3`.** Fresh security/lifecycle and proof/structure +reviewers independently run all 326 focused cases. They verify two gaps: completed +handles retain native request/response objects through the disposal closure and +the default abort exception's lazy stack; ordinary `call`/`apply`/`bind` wrappers +also evade the new facade installer fence. The fixes clear the retained closure, +use a fixed primitive cancellation reason on both terminal paths and recognize +the three installer wrappers. Dirty/clean controls cover every wrapper; the +original proof reviewer verifies its finding is closed. An isolated GC regression +retains completed handles while checking that both native objects are released, +with live-object positive controls. Both original and closure-only mutants fail +at the collection assertion for ready/refused paths; the repaired 327-case +focused run, typecheck and lint pass. Actual middleware/RSC integration remains +pending in the next steps. + +**Review round 2 — `af34e29`.** Fresh runtime and proof reviewers independently +run 367 and 446 focused cases. They verify that ordinary literal object/array +aliases evade the facade installer check and that the new signal handler leaves +a real development HMR connection/process alive. The source check now resolves +those static aliases, with dirty and clean controls. The launcher owns upgraded +sockets, cancels admission, awaits native/Next cleanup and bounds termination. +The native proof keeps HMR open through SIGTERM and SIGINT and requires exit code +zero and socket closure without fixture escalation. The original runtime reviewer +independently repeats both signals on real Next 15.5.27: both close and exit in +7 ms without SIGKILL, and closes the finding. The proof reviewer verifies its +minimal alias fix and all 278 boundary cases. Root revalidation passes 327 focused +cases, typecheck, lint, native ingress and all 19 setup/cleanup controls. Step 1 +is complete; no second-bootstrap removal or full product proof is claimed here. + + +###### ADR-0055 Step 2 — Single bootstrap publication and checked consumers + +**Implemented — 2026-10-10; both independent review rounds complete.** Middleware +requires the matching active native context before transport, performs the sole +site call and publishes only after successful route admission and response +construction. Redirects and refusals terminalize without a snapshot. Controlled +404/429/503 responses are bodyless for HEAD; the renderer forwards only eligible +integer Retry-After values from zero through sixty, without clamping. + +The RSC loader independently verifies provenance, consumes that native snapshot +and constructs its content caller with native cancellation. It never calls +`getSite()`. Invalid provenance and exempt transport fallbacks retain their prior +neutral behavior; active context/configuration defects fail with fixed internal +diagnostics. Identity checks distinguish simultaneous identical bindings. Private +memoized loaders have checked outer wrappers, and resource/UI/i18n/document +consumers recheck after their awaits; completed cache hits and retained translators +cannot revive an ended native request. + +The guarded frontend run passes **1,342** cases: **1,282 web and 60 SDK**, zero +skips/todos. Typecheck, lint, production build and all **198 architecture cases** +pass. The native ingress proof passes with one site call for status/scaffold +requests, real middleware/RSC consumption and retained TLS, method, optimizer, +DEBUG, HMR and signal controls. Focused tests include 88 middleware/admission and +18 actual-memo resource lifecycle cases. These are Step 2 results; Step 3 still +owns real-API/PostgreSQL product accounting, exact wire failures, broader lifecycle +and navigation proofs. The five catalogue rules remain Registered. + +**Review round 1 — `578dcd8`.** Fresh runtime/security and proof/structure +reviewers approve without actionable findings. Independent focused replays pass +122 and 400 cases. They verify single bootstrap ownership, exact middleware +refusals, bodyless HEAD, eligible Retry-After bounds, immutable snapshot identity, +post-await and memo-hit lifetime checks, cancellation and retained source fences. +Neither review claims Step 3's actual API/PostgreSQL or navigation obligations. + +**Review round 2 — `578dcd8`.** New runtime/security and proof/structure reviewers +approve without actionable findings. Independent focused replays pass 122 and +439 cases. They confirm real memo/runtime controls reject completed and +cross-store values before Education or result inspection, while preserving +request cancellation and the server-only boundary. Step 2 is complete; the +remaining production proof obligations stay with Step 3. + +###### ADR-0055 Step 3 — Production admission proof and closeout + +**Implemented — 2026-10-10; both independent review rounds complete.** The six +existing production modes consume the shipped native admission snapshot. +Release execution through real API/PostgreSQL passes all six cases, with zero +skips: transport **39**, foundation **33**, pagination **12**, presentation **30**, +product isolation **28** and product freshness **34** API calls. Exact checkpoint +assertions preserve the approved two/one/three-call contract, prior content-state +behavior and existing isolation, containment, build and stock-launch controls. + +`PublicAdmissionRenderingTests` and `verify-public-admission.mjs` add one actual +production case with three separately budgeted phases: wire **32**, lifetime +**48** and browser/HMR **10** API calls. Healthy calls use the real API and +PostgreSQL as `learnstack_app`, with positive READ ONLY and non-bypass observations. +Test-owned boundary faults exercise first-wire GET/HEAD 404/429/503, bounded +Retry-After, malformed/oversized responses, transport failures, deadlines and +invalid site admission. Refusals load no Education or tenant theme. A wrong-status +mutant fails the wire oracle, followed by a passing clean control. + +The lifetime phase forces overlapping identical HTML/RSC/prefetch requests and +mixed host/locale requests, proves distinct deeply frozen snapshots, and checks +zero retained contexts/snapshots after completion. Four concurrent prefetch lanes +make exactly eight API calls. Physical keep-alive reuse starts fresh admission; +client aborts cancel held bootstrap/content calls. A valid HEAD response finishes +before test-owned deferred work resumes; that work is refused before Education. +Shutdown cancels two held content requests, clears both snapshots and exits +without fixture escalation. Missing, duplicated and mismatched native contexts +fail closed without an API call. + +Stock Brave 154.1.96.61 proves actual refused Flight navigation at 429 and 503 +falls back to a new document request. The browser uses a disposable profile and +fixture certificate trust, without changing workstation trust. Development HMR +changes both source and live API data in the same process and proves fresh +admission with two site calls and no Education call. A bounded TLS WebSocket +watcher waits for the pinned Next compiler's `serverComponentChanges` message; +sync/client-only frames cannot release the source-change barrier. These are +narrow navigation/lifecycle proofs, not P02d-7's browser demo, Lighthouse or a new +manual accessibility audit. + +Two observed gaps were corrected before this commit. A successful JSON-shaped +response with the wrong media type was accepted by the configured caller; it now +requires the existing success/Problem Details media types before SDK parsing, +with cancellation, reader-release and positive controls. The initial full Docker +run exposed an HMR source-watcher race despite a passing focused run. The compiler +completion barrier replaces the racing source-write/request sequence; the focused +production case and subsequent full Docker run pass without retry or sleeps. + +Final local validation passes **2,946 backend cases**: **1,705 unit**, **198 +architecture**, **4 contract**, **172 Docker-free integration** and **867 Docker +integration**, zero skips. The guarded frontend run passes **1,402 cases**: +**1,342 web and 60 SDK**, zero skips/todos. Release build has zero warnings/errors; +format, workspace lint/typecheck, production build, native ingress and all +**19** ingress cleanup controls pass. The five admission catalogue rules are +Implemented with executable owners and planted controls. Accepted ADRs retain +their original bodies and receive dated delivery navigation. The reviews and +subsequent CI investigation are recorded below. + +**CI investigation and native completion proof.** The first Linux run on +`37ec51e` passes 866 Docker cases but fails the new production Fact during its +healthy wire control, after both real API calls return 200. An independent initial +console-only local attempt also fails without a retained substage; its captured +unchanged replay and five root replays pass. A diagnostic commit splits the closed +wire-control stages without printing provider or response data. + +The proof had inferred native completion from client response EOF. Node's socket +write callback emits server `finish`; client EOF and a later IPC message do not +establish that event has run. A test-only independent finish/close observer now +registers after production disposal listeners and waits for actual native terminal +events before asserting zero counts. Held-active observations stay immediate. +Six dirty/clean cases prove client/delegation completion cannot release the barrier +and missing runtime cleanup still fails after the barrier resolves. No sleep, +count-poll, production lifetime change or API retry is added. The actual production +Fact and guarded 1,402-case frontend run pass locally with this proof correction. +The diagnostic-only `9f785fc` then passes all six required jobs, including all +867 Docker cases and the new production Fact in +[run 38054051927](https://github.com/HodeTech/LearnStack/actions/runs/38054051927). +The exact first Linux substage remains unknown; this passing replay does not +establish the original cause. The completion correction addresses an independently +verified ordering assumption, not a claimed reconstruction of that failure. + +**Review round 1 — `7a2b4b2..37ec51e`.** GPT-6-astra and GPT-6.1-sol, both at +xhigh effort, review runtime/security and production proof/documentation +respectively. Both approve without actionable findings and independently pass +94 focused cases. They do not claim another full production-suite run. + +**Review round 2 — `7a2b4b2..37ec51e`.** Fresh GPT-6-astra and GPT-6.1-sol +reviewers at xhigh effort check runtime/lifecycle and proof/documentation. Static +runtime checks and 94 focused cases pass, but the runtime review's first +console-only production attempt fails as recorded above; its retained unchanged +replay passes. The proof reviewer records the early catalogue-status promotion: +`37ec51e` marked five rules Implemented after passing execution but before both +review rounds, contrary to the approved sequence. This process deviation is +preserved here rather than rewriting the plan. The later completed reviews and +fix verification support the current Implemented status. + +**Focused fix review round 1 — `9f785fc..b8d5199`.** Fresh GPT-6-astra at xhigh +effort verifies native observer ordering, independence from runtime counts and +unchanged active observations. It finds a real proof gap: one microtask wait lets +an already-resolved empty-pending mutant pass all six controls. Independent +verification reproduces that behavior; `100534f` crosses a deterministic +`setImmediate` turn before both pending assertions. The actual Vitest mutant now +fails three cases; restored production code passes all six. No wall-clock sleep or +runtime change is added. + +**Focused fix review round 2 — `9f785fc..100534f`.** Fresh GPT-6.1-sol at xhigh +effort approves without actionable findings, independently passes all six cases +and rejects the empty-pending mutant at all three corrected assertions. It +verifies native completion cannot conceal missing runtime cleanup and that the +existing ten-second IPC bound and API accounting remain unchanged. The guarded +full frontend replay passes 1,402 cases, zero skips/todos. + +The repeated optimizer-child cleanup comment is not applicable: `start()` +registers the child with its owner immediately, and failure unwinds through the +existing top-level `finally`/`owner.dispose()`. The implementation agent and an +independent proof reviewer verify that path; no redundant local cleanup is added. +The original manual browser/VoiceOver evidence retains its tested scope and commit. + +Closeout verification passes 198 architecture cases and seven ADR-workflow cases, +with no failures or skips. A local audit of the 37 changed Markdown files checks +2,392 relative links and 735 fragments without missing targets; inline/fenced +examples are excluded. Added prose respects 88 columns. CI's link gate still +checks file existence only. + +**Subsequent Linux capture failure — `b8d5199`.** Native completion checks pass, +but the admission Fact rejects an empty real API log capture; 866 other Docker +cases and five required jobs pass. The pinned Serilog hosting implementation uses +a process-global logger by default: another concurrent API host can replace it, +and disposing that host can close it. This verified shared-state mechanism does +not establish the exact historical interleaving. The public-read xUnit collection +now explicitly opts out of parallel scheduling with other collections, preserving +production logger configuration, enrichment, sink disposal and the nonempty-log +assertion. Forced overlapping HTTP requests inside each proof remain concurrent. +No logger replacement, synthetic event, polling or weakened assertion is added. +**Log-capture fix review round 1 — `ef05ab0`.** Fresh GPT-6-astra at xhigh +effort approves without actionable findings. It verifies the pinned xUnit runner +awaits parallel collections and their fixture disposal before starting an isolated +collection. It independently confirms the pinned Serilog global-logger mechanism, +sequential API phase ownership and the unchanged forced HTTP overlap gates. + +**Log-capture fix review round 2 — `ef05ab0`.** Fresh GPT-6.1-sol at xhigh +effort independently approves without actionable findings. It checks collection +and child-host lifetimes, awaited/idempotent fixture disposal, real-log assertions +and the four-arrival request barriers. Neither reviewer starts another Docker or +browser run or claims to reconstruct the earlier Linux interleaving. + +**Fix verification.** The full local Release Docker suite passes **867 cases**, +including the admission Fact and all six retained production modes, with zero +failures or skips. Release build has zero warnings/errors; format verification, +all **198 architecture cases**, seven ADR-workflow cases and the local link audit +pass. The previous guarded frontend execution remains **1,402 cases**, zero +skips/todos; this scheduling fix changes no frontend source. Two overlong prose +lines in this P6 delivery record are wrapped without changing their meaning. + +All three implementation steps and both subsequent focused fixes have completed +their two independent review rounds. The [PR #27 description](https://github.com/HodeTech/LearnStack/pull/27) +owns final exact-head CI after this documentation commit. Maintainer review and +merge remain pending. P02d-7 retains the full browser demo and Lighthouse; +Phase 06/11 retain their named broader accessibility and production-hardening work. + +**Latest external review follow-up — 2026-10-10.** The review against `d1cc011` +reports no Blocker or Major. Its fixed-port observation is valid: native listening, +Next's port option and redirect authority now share `PUBLIC_HTTPS_PORT`, preserving +the Accepted local HTTPS port 3000. Middleware explicitly narrows the verified +envelope instead of using a non-null assertion. + +The admission proof now also holds four scaffold requests at one real API barrier: +two hosts, each requesting `/studio` and `/portal`. Distinct seed palettes provide +positive controls; each HTML response contains its own palette and excludes the +other tenant's palette and name. Four separate immutable snapshots are released +after native completion. The driver asserts exactly four site calls and no +Education call for this checkpoint. The lifetime phase now uses **52** API calls; +wire **32** and browser/HMR **10** remain unchanged. The earlier **48**-call receipt +above describes the previous proof revision. + +The suggested silent/shared logger replacement is not applied. The unsupported +renderer warning is intentionally bounded to one event per request, contains only +fixed state/count fields and has a passing privacy/once-only test. Phase 11 owns +the broader frontend observability contract; removing this signal would weaken +the current diagnostic contract. + +**Follow-up review round 1 — `1496269`.** Fresh GPT-6-astra at xhigh effort +approves without actionable findings. It verifies shared port authority, explicit +envelope narrowing, real overlap, independent seed palettes, snapshot identity, +native completion, exact accounting and the bounded scaffold coverage claim. + +**Follow-up review round 2 — `1496269`.** Fresh GPT-6.1-sol at xhigh effort +independently approves without actionable findings. It reconciles the **32/52/10** +phase totals and checks provenance, cleanup, falsifiability and documentation. +Both rounds are read-only source reviews; runtime execution belongs to the parent. + +Focused local verification passes: the real admission Fact **1/1**, retained +rendering **20/20** (including all six production modes), architecture **198/198**, +guarded frontend **1,402/1,402**, typecheck, native compilation, lint and changed +C# format verification. TRX counters confirm zero failures/skips; the frontend +runner also refuses skips/todos. The PR description owns final exact-head CI +after this review-record commit. Maintainer review and merge remain pending. + +**Ingress instrumentation follow-up — `b073f35`.** The shared-port refactor also +changes a literal launcher anchor used by the separate native ingress fixture. +Its first [CI execution](https://github.com/HodeTech/LearnStack/actions/runs/38060818584) +rejects missing automatic-upgrade observations. The disposable copy now matches +the shared constant and checks that both instrumentation anchors occur exactly +once before rewriting. The fix changes no production code or assertion strength. +Local production build, native TLS/ingress proof, all **19** ingress cleanup/ +negative controls and lint pass. + +**Instrumentation fix review round 1 — `7ea14c5`.** Fresh GPT-6-astra at high +effort approves without actionable findings. In-memory checks reject missing and +duplicate anchors and confirm that the transformed launcher parses. It verifies +observer installation before Next's first-request upgrade registration, unchanged +upgrade assertions and compatible cleanup controls. + +**Instrumentation fix review round 2 — `7ea14c5`.** Fresh GPT-6.1-sol at high +effort independently approves without actionable findings. It checks actual +transformation syntax, one shared-constant listener, adjacent source anchors, +registration order and cleanup. Both rounds are read-only and start no runtime +services. The PR description owns final exact-head CI after this record commit. + +### P02d-6 merge and closeout (2026-10-10) + +The maintainer merged [PR #27](https://github.com/HodeTech/LearnStack/pull/27) at +2026-10-10 17:07:50 UTC. GitHub records final PR head +`46ed971bf976514fb451a162cc9450d147ed0441` and merge commit +`378346126949c90bb286b5217c24513fc2044f06`. The merge's second parent is that +head, and both commits have the identical tree. Development is fast-forwarded to +the verified merge without changing branches or rewriting history. The final +head includes the testing-standard correction marking both ADR-0055 Step 3 +review rounds complete. + +- All six required checks pass on the + [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/38070332107) + and the [merge commit](https://github.com/HodeTech/LearnStack/actions/runs/38070479860). + Independently downloaded merge-run TRX confirms **2,946 passed**, zero failures + or skips: 1,705 unit, 198 architecture, four contract, 172 Docker-free + integration and 867 Docker integration cases. +- Merge-run frontend logs confirm **1,402 passed** (1,342 web, 60 SDK), successful + typecheck, lint, production build and SDK drift verification. Native production + ingress verification and all **19** setup/cleanup and negative controls pass. + Release builds report zero warnings and errors. These are merge-run receipts; + the documentation closeout does not rerun the full runtime suites. +- Read-only verification confirms `strict: true` and the same six required Actions + contexts, including OpenAPI diff and Docker integration. No protection setting + changes. Lighthouse remains disabled with activation owned by P02d-7. + +**P02d-6 is closed.** Localized catalog, course/outline and ordered plain-text +lesson pages, safe four-color themes, exact-locale metadata, scoped pagination +and controlled public states are delivered. ADR-0055 adds middleware-owned single +bootstrap admission, immutable request-local reuse and production lifecycle/ +isolation proofs. All implementation steps and focused fixes retain their +recorded independent review rounds. The +[packet closeout](#p02d-6-packet-closeout-2026-10-10) owns scoped keyboard, focus, +reflow and contrast observations and the maintainer's VoiceOver smoke; this +merge adds no new manual observation or full WCAG-conformance claim. + +**Next: P02d-7 — Demo, full-stack CI and exit.** Its decision pass and +implementation have not started. Resolve the remaining G20/G33/G38/G44/G45 parts +against the delivered renderer before harness implementation: + +- Define `make demo` and stop/re-run ownership on a clean checkout, environment + projection, readiness, non-destructive seeding and the printed host/locale URLs + (G45). Local use and CI reuse the selected entrypoint. +- Select Lighthouse's tools, both-host/locale URL set, assertions, budgets, + aggregation and artifacts; activate its currently disabled job and reconcile + standards/required-check carriers with the chosen enforcement (G44). +- Complete the shared full-stack/browser demo and trusted-hop CI evidence + (G33/G38), including anonymous catalog-to-lesson flows with Keycloak stopped. +- Implement and prove G20's remaining production/seed and frontend genericity + fences in required checks, preserving tenant-data-driven differences. +- Reconcile every exit criterion and register row with its evidence and record + the Education/seed preservation obligations and premises `P02b-0` re-verifies. + [Phase 02b](phase-02b-events-auth.md) follows only after the Phase 02d exit + decision, not this packet merge. + +Phase 06 retains full Studio/portal, authored composition and Playwright/axe; +Phase 11 retains broader production hardening and telemetry. Course Marketplace +commerce is not delivered by this closeout. Earlier dated delivery records, +including their pre-merge pending statements, remain historical and unchanged. + +**Documentation-only closeout validation.** All **198** local Release architecture +cases and seven ADR lifecycle/workflow controls pass, with zero failures/skips. +The six changed Markdown files resolve **873** relative links and **371** fragments +with zero errors in the local audit. Added prose wrapping and diff checks pass. +Earlier dated phase records are byte-preserved; no Accepted ADR or production +code changes. + +## P02d-7 — Demo, full-stack CI and exit + +### P02d-7 decision package (2026-10-10) + +**Accepted — 2026-10-11; package and revised ADR-0056 approved.** Read-only +inspection starts from `f857437` on `development`, after the P6 merge closeout. +The maintainer approved the lifecycle, genericity, four-step review plan and +bounded seventh-check activation after real success. No implementation, passing +P7 test, enforcement delivery or phase exit is claimed. The user requires new +ADRs to be reviewed and approved before dependent work. Accepted +[ADR-0056](../decisions/0056-public-demo-browser-and-lighthouse-enforcement.md) +owns the new browser/Lighthouse measurement and required-check contract. + +P7 completes the walking skeleton's operational proof: a reviewer starts the +actual seeded sites with one command; the same lifecycle supplies CI's browser +and audit job; genericity and every phase-exit obligation receive named evidence. +Education writes, public DTOs, tenant authority, native ingress, anonymous quotas, +and request-local admission retain their Accepted contracts. + +#### P02d-7 inspection and document actions + +Three independent read-only review lenses covered demo/orchestration, +browser/Lighthouse, and genericity/exit. Source inspection was cross-checked with +the current branch and official tool metadata. This preparation executes no +runtime suite and does not reuse P6's counts as P7 results. + +| Area reviewed | Current premises and required action | +|---|---| +| README, CLAUDE, platform vision, MVP scope, roadmap index, principles and glossary | P1–P6 are merged; P7 is the remaining exit packet. Preserve the white-label/data-driven boundary and Proposed marketplace status. Keep current packet surfaces synchronized without rewriting dated delivery history. | +| ADR-0018/0035/0036/0040/0043/0048/0050/0051/0052/0053/0054/0055 and ADR-0027 | Existing content, RLS, read-only, exact-pin, TLS/provenance, quota and one-bootstrap contracts survive. G20/G45 implementation detail needs no ADR; new measurement/tool enforcement is Proposed ADR-0056. | +| Standards 03/06/07/08/11/12/13/14/15/16/20/21, CI and CONTRIBUTING | The Lighthouse job is still disabled. Qualify Testing 06's “None exist / first browser flow Phase 06” when P7's narrow flow ships; retain full Phase 06 Playwright/axe ownership. Update Performance status only with hard enforcement and distinguish CI targets from timeouts. | +| Makefile, compose dev/e2e, seed/public-local launchers, ingress/configuration and public server | No demo target exists. `make seed` runs migrations before the script's readiness gate. Wait for PostgreSQL before migration; parameterize one compose selection through start/wait/migrate/seed/stop. Health endpoints alone cannot prove seeded readiness or listener ownership. | +| SeedData, source-reader/name guards, module-reference guards and frontend source census | The existing source proof reads all strings, not just identities. Derive a typed identity vocabulary for G20 and canonical built-ins; add the whole-production Seeder-reference fence. Existing HTML/Flight schema-replacement proof supplies a behavioral companion, rather than a duplicate production mutation surface. | +| Production renderer fixture, admission browser, cleanup helpers, seed/local-dev/integration/test skills, compose and web READMEs | Reuse owned-process/TLS/private-output controls. Correct stale seeder activation, P6 merge and raw API restart guidance. Narrow old “CI uses Testcontainers only” and human-only browser statements when the compose-backed proof ships. | +| Phase 02b/05/06/11 and module handoff documents | Fix Phase 02b's mutable plain-HTTP/open-G32 premise; carry native HTTPS, visitor/peer accounting and single-bootstrap inputs into P02b-0 re-verification. Preserve Phase 05 migration obligations and Phase 06/11 ownership. | + +No accepted ADR body or prior delivery record is rewritten. Current contradictions +outside the new package receive bounded carrier fixes in the owning step; the exit +matrix verifies they are all resolved. + +**Preparation review — 2026-10-10.** Independent GPT-6-astra and GPT-6.1-sol +reviews verified the proposal against current contracts/source. Corrections +cover the package heading, complete seeded-ID vocabulary, actual Lighthouse +audit/navigation set and live status carriers. The maintainer's external review +additionally exposed the ADR lifecycle parser incompatibility; it was reproduced +and fixed. Metric/batch wording, tool pin/license placement, decimal gzip units +and the exact Testing 06 carrier action are now explicit. Earlier dated +“not started” statements describe their record time; this package and the top +packet table own current state, and Step 4 verifies that navigation at closeout. + +Documentation preparation passes all 198 Release architecture cases and all +seven ADR lifecycle/workflow controls, with zero failures/skips. These results +validate the draft corpus, not the unimplemented browser/Lighthouse harness. + +**Additional maintainer review — 2026-10-11.** The review identified ambiguity +between per-audit timeouts and the total deadline. Revised ADR-0056 specifies +one serial worker, nested deadlines and the 244-second quiet-window cost; the +first complete run must prove feasibility before activation, with no silent +parallelism or reduced census. It makes the potentially stricter gzip window, +origin coverage and exclusions explicit, names the four budgeted audits and +keeps FCP/Speed Index unasserted. The source-verified category name replaces the +imprecise agentic term. Tool ownership, behavioral script-rule ownership and +G33's retained human evidence are explicit. The revised ADR remains Proposed. + +An independent GPT-6-astra review found no unresolved revision finding. +Read-only upstream verification confirmed the audit/filter selection and the +pinned DevTools source for slow-4G constants. Revision validation passes 198 +Release architecture cases, seven ADR lifecycle/workflow controls and the +changed-document relative-link/anchor, wrapping and diff checks. No browser run +or timing feasibility is claimed by these preparation checks. + +#### P02d-7 accepted answers + +The maintainer approved the package on 2026-10-11. G20 detail, G33 CI topology, +G38's narrow browser-job scope and G45 lifecycle are Accepted planning decisions; +their implementation and proof remain pending. The maintainer subsequently +approved revised ADR-0056 on the same date, closing G44's measurement decision. +The seventh-check activation is authorized only after the approved ADR's complete +real PR run succeeds. The combined decision commit precedes implementation. + +| Gate | Approved scope / remaining decision authority | +|---|---| +| G20(b/c/d) | Typed exact identity matching, bounded canonical built-ins/exemptions and a whole-production Seeder-reference ban; the section below owns the detail. Implement the existing Registered rule and adopt the real schema-replacement companion. | +| G33 CI part | Same workstation-style loopback API/native TLS topology in the CI runner, one per-run secret, real migrated database and `learnstack_app`. Disposable CI certificates/resolver mapping; no system-trust mutation or additional trusted transport. | +| G38(c) job | A narrow managed-Chromium library script follows real catalog → course → lesson links in the three seed host/locale lanes. Existing product HTML/Flight proofs remain required; full Playwright/axe stays Phase 06. | +| G44 remaining detail | Accepted ADR-0056 owns direct pinned Lighthouse/Chromium, nine URLs × three runs, actual-page admission, hard gzip/CLS/accessibility checks, advisory timings, serial real-window pacing and artifacts. Its revised measurement contract was approved on 2026-10-11. Bounded activation of `public demo + lighthouse` as the seventh required check is approved only after the complete approved proof succeeds on a real PR, with protection read-back. | +| G45 | Foreground production-demo supervisor, shared full seed gate, persistent non-destructive local data and owned-process cleanup; the lifecycle below owns the details. | + +#### P02d-7 demo lifecycle + +`make demo` is the local entrypoint; `make demo DEMO_MODE=ci` selects isolated +automation through the same lifecycle. The mode selects environment/compose +ownership and the proof driver, not different product code or a bypass. Make +arguments are validated; startup, readiness, migration, seeding and cleanup share +one explicit compose project/file/env selection. + +1. Check installed prerequisites and refuse concurrent ownership or occupied + API/web listeners; never adopt or kill a foreign process. Restore locked + frontend, .NET and tool dependencies without changing Git hook configuration. + Prepare missing private root configuration from `.env.example`, validate + required values and refuse stale/disagreeing projections rather than overwrite + user values. Generate a missing hop secret through the existing preparation. +2. Local hosts/CA/leaf preparation remains the explicit manual G32 prerequisite. + Verify host resolution, certificate/key match, validity and trust with + actionable sanitized errors before infrastructure starts. Never edit system + hosts or install a root CA automatically. CI creates private disposable + configuration/certificates in its owned checkout and uses ADR-0056's scoped + browser trust and independent Node TLS checks. +3. Start the existing seven-service default compose stack, wait for PostgreSQL + before any migration, then retain the existing full default-service and both + Keycloak-realm seed gate. Apply all current migration chains with the migration + role and seed via the normal contextual request path as `learnstack_app`. + No destructive reset, overwrite or direct seed SQL is added. +4. Build the web production bundle and API, then launch the real API and mandatory + native HTTPS web listener in owned process groups. Use existing paired private + configuration, role validation and child-environment boundaries. These are + production builds with the accepted local Development deployment mode; + stock `next start` is not substituted for native ingress. +5. Declare ready only after owned-child readiness, verified TLS and positive + host/locale/content checks. Print catalog/course/lesson URLs for English + `en` and Yoga `tr-TR`/`en`, derived from the seed declaration. Static + `/healthz` or `/api/healthz` success alone is insufficient. +6. Ctrl+C, parent/control closure, child failure or a startup error stops and + joins owned API/web process trees. Local compose/data remains available; + `make down` is the explicit infrastructure stop. Re-run after shutdown + converges without reset; simultaneous invocations fail clearly. +7. CI uses the existing e2e overlay and a unique owned project. Stop its Keycloak + after successful seeding and assert the stopped state before fresh browser + navigation. On every exit, remove only that invocation's processes, project + and private files. Confirm child exit before deleting sensitive trees; fail + and preserve private diagnostics if cleanup cannot be established. + +Browser/Lighthouse uses actual limiter windows under ADR-0056. No API restart, +quota inflation, forged visitor or 429 retry is part of a successful proof. +API status/call observation must have a nonempty positive control; missing or +truncated observation fails. Reuse structured host completion events where +possible, retaining only sanitized counters/receipts in artifacts. + +#### P02d-7 genericity enforcement + +The typed `SeedData` declaration remains the single identity source. Build the +G20 vocabulary from every declared entity ID, including built-in row and theme +IDs; tenant/organization slugs, hosts and display names; course/lesson keys and +localized slugs/titles; customization keys, item keys, schema property names and +localized definition/field/band labels. Do not classify +ordinary body prose, locale codes, publication/access values or JSON-schema +keywords as tenant identities simply because the existing reader sees them. + +Compare complete decoded string values ordinally; compare GUID literals by +their parsed GUID value. This is an exact-literal fence, not a claim to prove +every possible dynamically assembled branch. Read C# literals, frontend TS/JS +literals and JSON values with syntax-aware readers, excluding comments. Fail on +unreadable/empty identity sources or production subjects. Preserve the frontend +census's refusal of unsupported source forms; no silent extension/import gap. + +Canonical platform built-in keys/labels come from their owning declarations/registries, +not copied into an expanding arbitrary allow-list. Preserve the accepted G20(c) +bounded exemptions: `SeedData`, explicitly identified seed/development launch +data, operational documentation and test-owned fixtures/assertions. Production +middleware, ingress, transport, renderer and message catalogues are subjects. +No blanket `scripts`, configuration or catalogue directory exemption is added. + +Additionally forbid every non-test production project except the Seeder itself +from referencing `LearnStack.Tools.Seeder`, both through compiled references and +restore-resolved project references. This catches identity comparisons through +`SeedData` symbols that contain no local literal. + +Planted failing controls cover backend identity/customization-ID comparisons, +renderer/transport branches, a shared frontend helper, message JSON values and +Seeder references. +Passing controls cover comments, canonical platform built-ins and specifically +allowed development/test data. Prove the actual production census is nonempty. +Re-run the existing real API/PostgreSQL/HTML/Flight presentation successor-revision +proof as the behavioral companion, with a field-assertion failure control; retain +original-pin and unaffected-tenant checks. The new browser proof observes +distinct ordered authored fields, without adding a production mutation endpoint. + +#### P02d-7 implementation plan + +Work remains on `development`; no alternate branch or worktree. Each step lands +its implementation commit, then two fresh independent agent review rounds. +Verify findings against current code, fix valid findings and commit before the +next round/step. A new architectural decision pauses only its dependent work. + +| Step | Delivery | Validation before completion | +|---|---|---| +| 1 — Shared demo lifecycle | Compose selection, pre-migration wait, locked restoration, private configuration, foreground ownership, production build/start, seeded readiness, non-destructive repeat/stop and local guidance. | Clean-checkout preparation with the documented manual TLS prerequisite; repeat convergence; stale/missing configuration; port collision/foreign listener; child failure, signal/parent closure and owned cleanup controls. | +| 2 — Genericity and exit foundations | Existing G20 production literal rule, whole-production Seeder-reference fence, canonical built-ins/exemptions, behavioral companion and preliminary criterion/evidence inventory. | Nonempty backend/frontend/JSON census; planted dirty/clean controls; architecture/unit/contract and relevant integration tests; existing exact-pin/schema-replacement product proof. | +| 3 — Browser and audit proof | Pinned tools/browser; seed-derived nine-URL manifest; Keycloak-stopped linked navigation; computed themes/ordered fields; actual audited-page admission, gzip collector, metrics/census validator, rate pacing and sanitized artifacts. | Real same-build/same-database run; no API 429; positive call observer; wrong/error page, invalid report, over-budget and missing-source controls; TLS and failure cleanup; all 27 report pairs. | +| 4 — Required CI and phase exit | Always-running seventh job, bounded protection activation after real success, standards/carrier alignment, complete evidence matrix and P02b-0/Phase 05 handoff. | All backend/frontend suites with zero skips; real CI and live protection read-back; links/anchors/wrapping; every gate/deliverable/criterion reconciled; zero 02d Registered/Awaiting rows; two review rounds and explicit exit verdict. | + +The new job does not replace any existing required suite or fixture. Preserve +the accepted P6 keyboard/focus/reflow/contrast and maintainer VoiceOver record, +with its actual limits; record new automated observations separately. Promoting +Performance to Active is conditional on delivering the proposed hard checks, +not on accepting this package. Its index/header/count change lands with the +enforcer; Accessibility is already Active for its delivered public-page scope. + +#### P02d-7 approval and exit boundary + +The complete lifecycle and G20/G33/G38/G45 answers, four-step review plan and +bounded seventh-check activation were approved on 2026-10-11. Revised ADR-0056's +tools/measurement/browser contract was subsequently approved on the same date. +Its register dependencies are recorded in the combined decision commit before +implementation. +No other unresolved product choice was found in this inspection. Unexpected +architectural changes need a separate reviewable decision; implementation details +inside the approved package proceed without further approval. + +At closeout, map every Deliverable and Completion Criterion to current named +evidence, including carried-forward evidence and its limits. Reconcile current +Phase 02b native-HTTPS/quotas/single-bootstrap premises without accepting its +auth/BFF gates. Record independent Course/Lesson roots, stable IDs/URLs, ordering, +scope, translated bodies, exact pins and access policy as Phase 05 preservation +obligations; re-seeding is not a migration. + +Do not declare Phase 02d exited merely because P7 code or its PR is complete. +The exit verdict must state which obligations passed, identify evidence/CI/protection +receipts and leave no unresolved 02d-owned gate or Registered/Awaiting rule. The +maintainer's PR review and merge remain separate from implementation completion. + +### P02d-7 Step 1 — shared demo lifecycle (2026-10-11) + +**Complete — both review rounds and their fixes verified.** +The foreground `make demo` supervisor shares explicit Compose selection, +PostgreSQL-before-migration readiness, full seven-service/both-realm admission, +contextual seeding, production builds and owned process cleanup. Local data is +retained; CI uses a unique project, disposable private configuration and the e2e +overlay. Its browser/audit driver remains Step 3 work and is not claimed here. + +`DemoManifest.Create` derives all three host/locale lanes, nine URLs, ordered field +expectations, palettes and excluded course titles from `SeedData`. Its export +requires no database. Configuration validation uses Npgsql's real parser to +refuse stale role/password/database/host/port combinations before infrastructure. +The runtime environment helper is shared with the existing paired API launcher; +migration and worker credentials are excluded. TLS prerequisites do not modify +hosts or system trust. The exclusive demo lock never kills a recorded foreign PID. + +**Initial verification.** The Release Seeder build has zero warnings/errors. +All 1,705 unit, 198 architecture, four contract, nine focused integration and +42 Seeder integration cases pass with zero failures/skips. Focused integration +includes eight manifest/configuration cases and the real-API/PostgreSQL local +launcher proof without a PlatformAdmin credential. The guarded frontend runner +passes 1,413 cases without skips/todos; the final 13-case focused suite also +covers structured API-listener readiness and an invocation-owned native cache. +Lint and typecheck pass. Node controls cover +explicit selection, readiness refusal, runtime credential isolation, foreign +listeners, bounded bodies, certificate mismatch, real process timeout/cancellation +and owned trees. These initial checks precede the complete startup and review +evidence below. + +**Complete isolated lifecycle proof.** An owned temporary checkout copy starts +all seven services with the e2e overlay, passes both realm gates, applies every +migration chain and seeds through the application role. Its owned production +API/native renderer passes positive lesson checks in all three seed host/locale +lanes. Re-running the ordinary Seeder leaves the nonempty audit count unchanged. +Teardown confirms process/project absence, removes its private configuration, +certificate tree and lock, and releases the API/web listeners. This is a Step 1 +startup/neutrality/cleanup proof; it is not Step 3 browser/Lighthouse evidence. + +**Workstation port prerequisite.** The first attempt correctly refused occupied +5080/5432 ports. After explicit maintainer authorization on 2026-10-11, the two +foreign containers were stopped only for validation and restarted afterward; +both returned healthy. LearnStack volumes remain intact. Its local PostgreSQL +and Keycloak cannot run concurrently while the foreign database retains 5432; +no port mapping or foreign project configuration was changed. + +**Step 1 review round 1 — `3160714..82459cb`.** Fresh GPT-6-astra and +GPT-6.1-sol reviewers independently covered the full diff through lifecycle/ +security and evidence/corpus lenses. Four distinct findings were verified: +selected-env migration fallback, terminal hangup cleanup, split UTF-8/byte-bound +capture and restricted-course marketing exclusions in the demo manifest. +Corrections add actual Make/configuration, process/signal/parent, split-output +and marketing-disjoint controls. Combined seeding now rejects disagreeing ambient +credentials before stack/migration actions. Default-service enumeration is shared +as reinforcement; the suspected gated-port defect was not reproduced. The +suspected parallel prerequisite race was rejected because global `.NOTPARALLEL` +already serializes those acts. The 18-case focused suite, typecheck, eight +manifest/configuration cases and all 198 architecture cases pass. Lint and the +guarded frontend run pass all 1,420 cases with zero skips/todos. The complete +isolated lifecycle rerun also passes real SIGHUP/repeated-signal cleanup and +listener release. The two authorized foreign containers return healthy afterward. + +**Step 1 review round 2 — `3160714..4966dca`.** Fresh GPT-6-astra and +GPT-6.1-sol reviewers independently inspected lifecycle/security and evidence/ +corpus. Both reran all 18 focused cases. Two additional findings were confirmed: +Docker can read `COMPOSE_PROFILES` from the selected dotenv file, and Development +API configuration can consult workstation user secrets through its profile. +The selected-file control now refuses reserved Compose assignments, including +export/whitespace/colon forms. A read-only real Compose control observes exactly +seven default services and refuses the planted file profile before Docker. +The demo API receives an empty invocation-owned HOME/APPDATA/TMPDIR; restoration +and builds retain their own profiles. A real API/PostgreSQL test accepts the +configured hop secret and rejects an additional secret planted in a foreign +profile. No user profile is modified. All 24 focused lifecycle cases, typecheck +and the real launcher cases pass with zero failures/skips. Lint, all 1,426 +guarded frontend cases and all 198 architecture cases pass. A fresh focused fix +review found that the foreign-secret request omitted its visitor header, allowing +an unrelated refusal to mask the regression. The corrected three-case real API +suite supplies that header and removes the profile boundary only in an owned +copy: the foreign secret now produces 200 in the mutant and 404 in the clean +runtime. All three cases pass. Both required review rounds and their verified +fixes are complete; Step 2 follows. + +### P02d-7 Step 2 — genericity and exit foundations (2026-10-11) + +**Implementation and both independent review rounds complete.** The exact-literal +G20 fence reads categorized `DemoIdentities.Create` values derived from typed +`SeedData`, including all declared IDs and translated identity/definition/field +labels. Ordinary body prose, locale/status/access values and schema keywords do +not become identities. Canonical platform values come from +`BuiltInCustomizations`, including collisions with demo values. + +Backend Roslyn and frontend TypeScript AST readers compare complete decoded +strings ordinally and GUIDs by value, including alternate spellings. Embedded +JSON strings and standalone JSON values are inspected. Source parse errors, +empty/malformed vocabulary and missing production subjects fail loudly. The +frontend fixture is derived, not a second declaration; architecture tests compare +it to the current typed projection. Regenerate it after editing `SeedData`: + +```sh +dotnet run --project backend/src/LearnStack.Tools.Seeder -c Release -- \ + --demo-identities > frontend/apps/web/src/test/fixtures/demo-identities.json +``` + +The backend scans Seeder orchestration as production and exempts only its exact +`SeedData.cs` declaration. Frontend scans app/package/configuration/native code +and root Node scripts, with exact named test-proof and development-launch data +exemptions. The existing unsupported-runtime-source/import census is preserved. +Every production project except the Seeder is checked for both compiled and +restore-resolved Seeder references, preventing symbolic `SeedData` access. + +The existing real API/PostgreSQL/HTML/Flight presentation successor proof calls +one shared ordered-field assertion. Planted label, value, ordering, active-markup, +language and internal-name controls exercise the same predicate without changing +production rendering. Original-pin and unaffected-tenant observations remain. + +**Initial verification.** Release suites pass 1,705 unit, 203 architecture and +four contract cases with zero failures/skips. The existing presentation-mode +real API/PostgreSQL/native production proof passes (one case), exercising both +HTML and Flight, successor/rebinding, original pins and the unaffected tenant. +Lint, typecheck, formatting and all 1,442 guarded frontend cases pass with zero +skips/todos. This is not Step 3 browser/Lighthouse evidence. + +**Review round 1.** Fresh GPT-6-astra and GPT-6.1-sol reviewers independently +checked backend identity/reference coverage and frontend subjects/behavioral +controls. Four verified omissions were fixed: conditional C# branches, UTF-8 +literals, emitted JSX values and runtime helpers hidden by test exemptions. +The initial fix exposed conditional branches conservatively; round 2 below +replaces that approach to preserve lexical semantics. JSX handling uses TypeScript's +emitter. Exact test directories replace name-wide directory exclusions, and +runtime relative imports include helpers even behind test filenames. Native HMR +and the shared process-stop helper are production subjects. Planted dirty/clean +controls cover all four findings. Release architecture (203), guarded frontend +(1,444), lint, typecheck, formatting and the documentation link audit pass. +Second-round review follows the fix commit. + +**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol reviewers verified three +census omissions and one ordering-control gap. Flattening C# branches could let +an inactive comment hide active code. The reader now parses feasible symbol +configurations independently, discovers conditional symbols to a fixed point, +and refuses more than eight symbols or unreadable configurations. UTF-8 and raw +literal semantics remain intact. Frontend generated-output exclusions now name +actual roots; nested source directories remain subjects. Runtime imports resolve +local module URL query/fragment suffixes and percent escapes, while computed +imports fail loudly. Literal `require.resolve` loads remain countable. The +ordering offender now swaps intact label/value pairs rather than corrupting them. +Release architecture (203) and all guarded frontend cases (1,446), lint, +typecheck, formatting and link/anchor checks pass. Fresh fix verification follows. + +**Fresh fix verification.** The prior omissions are closed. The verifier found +one new resolver-options gap: a relative `require.resolve` input could redirect +through `paths`. That unmodeled form now fails loudly, with a planted control; +the actual literal external-package ESLint load remains accepted. Both review +rounds and their verified findings are complete. Step 3 follows. + +#### P02d-7 preliminary exit evidence inventory + +This is an inventory, not a phase-exit verdict. Step 4 reconciles every individual +Deliverable and Completion Criterion against exact-head evidence, current CI and +protection receipts; historical delivery records retain their original limits. + +| Criterion group | Existing evidence to retain/recheck | P7 completion work | +|---|---|---| +| Two sites, linked catalog/course/lesson, distinct field sets and branding | P6 product/presentation HTML/Flight fixture; maintainer keyboard/focus/reflow/VoiceOver record; `DemoManifest` typed expectations. | Step 3 real Chromium linked navigation and computed themes, three host/locale lanes; same API/web/database with owned Keycloak stopped. | +| Clean preparation, non-destructive repeat and owned stop | Step 1 isolated seven-service/two-realm startup, audit-neutral Seeder repeat and signal/parent/process/TLS controls. | Step 3 shares the lifecycle; Step 4 records complete CI receipt and cleanup. | +| Education schema, RLS, scope, satellites, parents, privileges, migrations | `EducationIsolationTests`, migration/tenant-scoping/index/grant sweeps and P1 delivery record. | Re-run full backend suites at exit; Phase 05 preservation handoff. | +| Writer invariants, exact pins, locale/slug/state/body validation, MUST audit, branding and seed convergence | `EducationWriterTests`, `TenancyWriterTests`, `SeederTests`, P2 record. | Re-run with zero skips; retain typed inventories and bounded branding/access contracts. | +| Definition/settings reads, generations, rollback safety, fallback, no read validation | `CustomizationProjectionTests` and composition/cache/settings suites; P3 record. | Re-run; retain existing generation/family metrics and settings freshness boundary. | +| Public eligibility, cursor/scope/locale, DTO/HEAD/OpenAPI/SDK, no-store, read-only pipeline | P4 public HTTP, contract, transaction and dispatch guards. | Re-run SDK/contract/OpenAPI drift and all required checks; retain current seven-check read-back only after success. | +| Provenance/ingress/hop/visitor limits, private carriers, native production freshness, single bootstrap | P5 remediation and ADR-0055 real native/API proofs; P6 bootstrap/refusal coverage. | Step 3 uses identical ingress/limiter and records positive API calls with zero 429. | +| Localized renderer, inert authored text, metadata/status, manual accessibility | P6 i18n/route/HTML-RSC/a11y guards and recorded human checks. | Step 3 observes actual browser documents; Lighthouse supplements the bounded manual record. | +| G20 exact-literal/reference fence and schema replacement | This Step 2 backend/frontend dirty/clean controls and existing presentation successor fixture. | Both independent review rounds; Step 3 ordered fields. Computed comparisons remain a review/behavioral boundary. | +| Performance/accessibility audits, report/census/gzip guards | ADR-0056 accepted obligations, four Registered behavioral rules. | Step 3 implements 27 report pairs/hard checks; Step 4 activates mandatory CI/protection and updates statuses with enforcement. | +| Governance, all gates/catalogue rows, module/standard/skill/vision/MVP carriers and named exclusions | Existing decision register and P1–P6 records. | Step 4 complete criterion matrix, zero 02d Registered/Awaiting rows, owner-document checks and P02b-0/Phase 05 handoffs. | + +### P02d-7 Step 3 — browser and audit proof (2026-10-11) + +**Complete — both independent review rounds and verified fixes pass.** +The shared CI lifecycle invokes `verify-public-demo.mjs` over the same seeded +production API/native renderer. `DemoManifest` also derives hidden lesson titles +and field values, excluding values shared with eligible public content. The +browser follows the actual catalog/course/lesson links in all three host/locale +lanes and compares computed theme colors, identity and ordered authored fields. + +Exact development-tool pins are Lighthouse 13.5.0 and Playwright 1.64.0, using +its managed full Chromium 156.0.8078.4, revision 1248. The audit configuration +has an independently recorded 125-audit/14-artifact census and complete category +weights. A custom initial-navigation gatherer observes the actual document and +all delivered Script bodies; it never refetches or navigates. The shared policy +checks original inline source, complete decoded bodies, normalized gzip and the +actual audited product DOM before admitting a JSON/HTML report pair. + +The structured API completion observer retains only aggregate status/path-family +counts. A fresh HTTPS product read supplies its positive control. Four serial +batches preserve the real admission policy, with the approved quiet intervals +and subordinate deadlines. The public receipt records setup/proof/cleanup +milliseconds, versions, configuration, source digests, report inventory and API +counts. Browser profiles, certificates, private configuration and raw logs stay +outside the public evidence. CI cleanup confirms owned process/project absence +and removes owned private files, environment and lock within its separate bound. + +**Initial verification.** All 43 focused frontend controls and eight existing +manifest/configuration integration cases pass with zero failures/skips. Lint +and typecheck pass. The guarded frontend runner passes all 1,489 cases +(1,429 web + 60 SDK); all 203 architecture cases pass, with zero skips. +The controls include actual installed Lighthouse configuration +resolution, measured over-budget sources, wrong/error product documents, invalid +reports/census, missing/truncated/foreign-target sources and split API events. +The first complete serial feasibility run passes: lifecycle setup 61,468 ms, +proof 549,269 ms (9 min 9 s), and confirmed cleanup 10,656 ms. It produces all 27 +JSON/HTML pairs and nine browser screenshots. All hard checks pass: normalized +initial JavaScript is 106,381–106,573 bytes, CLS is zero, and scored automated +accessibility is 1 on every run. The four proof batches observe exactly +18/36/36/36 successful API calls; the separate observer control observes two. +Both untrusted/wrong-SPKI browser controls refuse before reaching the API. +The CI-owned Keycloak stays stopped. Owned processes/project/private files, +environment and lock are removed; the two authorized foreign containers restart. + +LCP samples are 2,008.544–2,166.836 ms, producing an advisory median warning for +each of the nine URLs. Server response is 15–23 ms and TBT 4–16 ms. These are +local simulated lab samples, not field/p95 performance or a new manual WCAG pass. +This is working-copy feasibility evidence over the `69ce613` baseline and build +`vCA7HXnit3froptth4IYD`; it is not an exact-head CI claim. Subsequent receipt-only +hardening records the complete expected/configuration census and startup/final +counters; the final committed CI run must validate those changes. Step 4 owns +CI enforcement, protection activation and phase exit. + +The first runtime attempts exposed harness defects before any audit verdict: +macOS's certificate verifier stalled when Chromium inherited the isolated Node +HOME, and optional `undefined` configuration properties differed from their JSON +receipt. A causal disposable TLS experiment confirms certificate refusal with +the real account HOME; only the managed browser receives it, with an explicit +owned disposable profile. Worker/API environments remain isolated. Configuration +comparison now uses the serializable receipt and an actual-resolution control. +The linked nine-page browser path subsequently passed, with exactly 18 successful +API calls and no 429, before the configuration comparison stopped that attempt. +These observations are preliminary validation, not the complete feasibility gate. + +**Transitive review.** Both direct tools are Apache-2.0 development dependencies. +The added tree includes MPL-2.0 `axe-core` 4.14.0, used by Lighthouse's development +accessibility audit; retain its package license/source obligations if distributing +that tool. Existing runtime package versions are unchanged. Resolving the added +OpenTelemetry API peer changes some lockfile peer identities without adding +application instrumentation. The full-workspace audit reports zero critical, +one high and one moderate advisory; neither path comes from the new tools. +The existing [security triage](#remediation-group-3--approved-security-maintenance) +owns Braces' unfixed build-glob recursion issue and the incompatible-major +selector-parser fix. Their maintainer/backport/parent-migration ownership and +Security Standards deadlines remain unchanged; this is not a clean-audit claim. + +#### Step 3 review round 1 + +Fresh GPT-6-astra (xhigh) runtime/measurement and GPT-6.1-sol (xhigh) +proof/corpus/dependency reviews cover `69ce613..d99d10b`. Both request changes; +three verified findings concern the proof, with no production-code defect. +Independent root reproductions confirm each failure before correction. + +- Completion observation silently ignored damaged JSON and unterminated records; + the receipt preceded final API output drain. Separate stdout/stderr decoders, + pending-tail refusal, joined EOF finalization and post-cleanup final census now + prevent malformed, late or 429 traffic from disappearing. Actual record controls + include split/interleaved clean output, damaged/newline/EOF records and late + success/refusal events. +- Lighthouse treats its navigation timeout as a warning. A real disposable + Chromium/Lighthouse run took 22,116 ms and admitted an incomplete image load. + Report admission now refuses warnings. The shared proof includes that actual + soft-timeout control with an otherwise passing report counterpart. +- Ancestor opacity and zero-area rendering hid product markers while the DOM gate + admitted them. Browser-native visibility plus positive-area rectangles now + apply to markers and individual field labels/values. Each real lesson navigation + plants ancestor-opacity, zero-area and hidden-label mutations, verifies refusal, + restores the document and re-admits the visible control, without new API calls. + +All 74 focused proof/lifecycle cases pass with zero failures/skips. Disposable +managed-Chromium controls verify visible admission and hidden/zero-area refusal. +A complete rerun and fresh independent round 2 remain pending; the earlier local +feasibility result is preserved and does not validate these subsequent changes. + +#### Step 3 review round 2 + +Fresh GPT-6-astra (xhigh) runtime/measurement and GPT-6.1-sol (xhigh) +proof/corpus reviews cover `69ce613..38c15d9`. Both request changes. Three +verified proof gaps remain; the existing 50 proof controls passed independently. + +- A completion record missing its opening brace or carrying a prefix was ignored, + as was an unexpected endpoint completion. The owned API emits structured + startup/output; only empty plaintext separators are now admitted. Damaged and + unexpected completion records refuse the entire census, including a 429. +- Process-group absence preceded child `close` and buffered stream EOF. An actual + child with deliberately deferred stdout demonstrated a 429 arriving after a + prematurely passing final census. Cleanup now joins `close` with a separate + shared five-second stop/output-drain bound before observer finalization. The + regression holds and releases the real pipe, proves cleanup waits, then refuses + the 429. +- Clip/filter/mask and offscreen/overflow styles could hide laid-out markers. + The bounded seeded-page predicate now refuses these ancestor styles and + horizontally unreachable/negative-area markers. Each lesson navigation checks + eight actual DOM mutations, restores and re-admits its positive control; + the receipt requires all 24 completed controls. This is not a general CSS + occlusion or visual-accessibility audit. + +All 78 focused proof/lifecycle cases, typecheck and lint pass. The full guarded +runner passes 1,500 cases (1,440 web + 60 SDK), with zero failures/skips/todos. +Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) fix reviews approve +`38c15d9..39cee01` and the final shared cleanup-deadline adjustment. Independent +controls reproduce the old observer/drain gaps, confirm joined stdout/stderr, +refuse daemon output errors and bound a TERM-resistant child plus held output +to 5,003 ms. Managed Chromium refuses all eight DOM mutants and re-admits each +restored counterpart; the five added cases passed the old predicate. + +The complete `38c15d9` rerun passes: setup 60,270 ms, proof 571,089 ms, +cleanup 10,688 ms, all 27 report pairs and nine screenshots, actual soft-timeout +refusal, nine visibility controls and 134 successful API completions, with zero +429/malformed/pending records. The authorized foreign containers restart healthy. +That receipt precedes round-2 fixes. The complete `39cee01` rerun also passes: +setup 60,374 ms, proof 585,644 ms and cleanup 10,719 ms. Build +`d0bzXjXoImUdH317X83rK`, invocation `825982bee2ed568f43208368f99f332d`, +produces all 27 report pairs, nine screenshots and 24 completed visibility +controls. The actual soft-timeout and both TLS refusal controls pass; final +observation contains 134 successful calls, zero 429/malformed/pending records. +All owned cleanup checks pass and the authorized foreign containers restart. +The subsequent shared-bound change has focused verification above and must also +run in final CI. Both independent review rounds and fresh fix verification are +complete. Step 4 owns CI enforcement and phase exit; neither is claimed here. + +### P02d-7 Step 4 — CI enforcement and phase exit (2026-10-11) + +**Implementation, both independent review rounds and real CI complete.** The +[CI and exit closeout](#p02d-7-ci-and-phase-exit-closeout-2026-10-11) records +successful artifacts and the activated seventh required context. +The always-running `public demo + lighthouse` job replaces the disabled +placeholder. It installs the exact locked browser tools and managed Chromium, +then invokes `make demo DEMO_MODE=ci` over the shared seven-service lifecycle. +The 20-minute job includes setup, the 12-minute serial proof, separate bounded +cleanup and artifact handling. An unconditional bounded workflow receipt records +failure even when setup prevents a product receipt. Uploads allow only public +JSON/HTML reports, screenshots and sanitized workflow/proof receipts. + +The [individual exit evidence matrix](phase-02d-exit-evidence.md) maps all +36 Deliverables, 79 Completion Criteria, 39 exclusions and nine exit obligations. +It preserves prior human/PR evidence and names the verified CI receipts; +implementation alone does not constitute phase exit. + +**Criterion reconciliation.** Published roots cannot receive new translations +under ADR-0050. The third-locale proof therefore creates and publishes new +French-only roots through supported commands, preserving the existing EN/TR +public responses and all five migration histories. Organization branding writers +remain unrouted. The branding criterion now separates API-root command refusal +from mapped-host reads and distinguishes a successful business audit from the +required standalone denied-attempt audit. This corrects the mutable criterion's +no-audit overclaim; ADR-0033/0044 and production auditing are unchanged. + +**Education preservation handoff.** Phase 05 inherits separate Course/Lesson +roots and their contained Pattern A translations. Its migration preserves stable +IDs and published localized URLs, `(sort,id)` lesson order, tenant/organization +scope, translated bodies, exact content-type/taxonomy revision pins and course +access policy. `SeedData.All` supplies both tenant curricula: eight courses, +ten lessons and 27 translations at their declared scopes, including draft and +restricted controls. Carry those persisted fixtures through the migration; +reseeding is not a migration strategy. + +> **Reconciliation — 2026-10-12.** The settings-event ownership below records +> P7's expectation at closeout. Accepted +> [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) +> selects completed provisioning as the first useful event; the +> [Tenancy catalogue](../modules/tenancy/README.md#integration-event-catalogue) +> promises no settings-invalidation event. Settings remain uncached. Any future +> cached consumer needs its scope/key/freshness decision; Phase 11 owns the +> distributed adapters on their existing triggers, without a settings-event promise. +> The dated handoff text is retained. + +**P02b-0 re-verification handoff.** Re-read the four `/api/v1/public` GET/HEAD +pairs and contract; retained `*.learnstack.local` seed hosts over native HTTPS, +manual local hosts/CA setup and private paired hop configuration; coordinated +60/min visitor and 600/min physical-peer accounting; tenant-wide English versus +organization-scoped Yoga seed context; one live bootstrap with two calls per +normal product document and three for a followed missing-content chain; and the +uncached settings reader plus `learnstack.tenancy.settings` eager-invalidation +event owned by Phase 02b. These delivered premises do not Accept future +session/BFF/authenticated-rate-limit decisions. + +**Initial validation at `bf5bc9c`.** Both third-locale/branding cases pass locally +with zero skips. Release build has zero warnings/errors; 1,705 unit, 203 architecture, +four contract and 180 Docker-free integration cases pass, as do all 1,500 guarded +frontend cases. Typecheck, lint, whitespace and 2,042 relative links (666 fragments) +pass. All 871 Docker integration cases pass with zero skips; execution guards pass. +Two fresh review rounds, a real +successful PR job and the authorized seventh-context activation/read-back remain. +No PR, live check activation or phase exit is claimed yet. + +#### Step 4 review round 1 (2026-10-11) + +Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) agents reviewed +`06d46ad..bf5bc9c` for runtime/CI ownership and corpus/exit evidence. Their +confirmed findings concern proof completeness and CI prerequisites, not a +production contract defect. C40–C42 now share one HTTP test: 17 requests pair +foreign-only/shared slugs, exact-locale omissions and organization/tenant host +controls with exact raw translation sets on each request's own enlisted +application connection. The third-locale case now enables French on the foreign +host and proves its positive catalog before checking the same French detail +URLs are hidden. Missing Cache-Control can no longer bypass its assertions. + +The CI job starts an absolute deadline before checkout, bounds setup steps and +interrupts the shared lifecycle by minute 16, reserving four minutes inside the +unchanged 20-minute ceiling for owned cleanup, policy cleanup and artifacts. +Four controls execute the actual workflow shell: first-step reservation, +remaining-budget arguments and two exhausted-budget refusals. An actual GNU +timeout → make → shared Node-owner experiment exits 124 only after child cleanup. +The internal 12-minute serial proof deadline remains unchanged. + +The GitHub-hosted Linux prerequisite loads only an invocation-owned AppArmor +userns profile for the exact managed Chromium when the kernel restriction needs +it, then performs a sandbox-enabled launch smoke. Fifteen isolated controls +exercise ownership, literal paths, failed load/removal and cleanup without +changing workstation policy. A real Linux job remains required; the initial +runner risk was source-supported inference, not a reproduced hosted failure. +The exit matrix, stale review guidance, Phase 02b risk premises and mutable +renderer/writer scope descriptions now match delivered contracts. + +All three focused locale/branding Docker cases pass with zero skips and the +execution guard. The guarded frontend rerun passes 1,504 cases (1,444 web + 60 +SDK), zero failures/skips/todos; typecheck, lint, scoped backend formatting and +whitespace pass. The initial full backend totals above precede the added combined +case. Final complete PR CI, round 2 and protection read-back remain required. + +#### Step 4 review round 2 (2026-10-11) + +Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) agents reviewed +`06d46ad..100b022` across runtime/CI ownership, security, correctness, +maintainability, test quality and the complete changed corpus/exit matrix. +Both approve with no remaining Blocker or Major. The corpus reviewer confirmed +two Minor navigation/census remnants: the matrix still called the expanded +three-case class two cases, and CONTRIBUTING still described completed +ADR-0055 reviews as remaining. Both are corrected; the reviewer independently +checked the bounded follow-up. One overlong P7 prose line is wrapped without +changing its content, and catalogue navigation names the new deadline/sandbox +controls. Earlier P1–P6 delivery records remain unchanged. + +The runtime reviewer independently passes all 15 Chromium-prerequisite controls, +four actual-workflow deadline controls and all three focused Docker HTTP cases, +with zero skips, plus whitespace. The corpus reviewer verifies all 36/79/39/9 +inventory counts, complete named evidence, 175 Implemented rules, 21 Active/one +Adopted standards and future-owner scope. Root checks pass seven ADR lifecycle +and 14 OpenAPI-CI controls. The complete PR's 33 unique Markdown files resolve +2,188 relative links and 686 fragments with no errors before these closing +navigation additions. Fenced and inline examples are excluded from link counts. +Both review rounds and verified fixes are complete. Actual successful Linux PR +CI, complete artifact receipts and authorized protection activation/read-back +remain required before a positive phase-exit verdict. + +#### P02d-7 CI and phase-exit closeout (2026-10-11) + +**Verdict: implementation and Phase 02d exit verification complete.** All four +P7 steps completed both fresh independent review rounds; verified findings are +fixed and committed. [PR #28](https://github.com/HodeTech/LearnStack/pull/28) +remains open for maintainer review and merge. No merge is claimed. + +All seven jobs passed in the first real +[PR run](https://github.com/HodeTech/LearnStack/actions/runs/38106505383) for source +head `8605fc94f7ba343d5cd7cc15d28001d99349735b`. GitHub tested synthetic merge +`15109c3a80a41ee7b6d6f9832880c7b2b13877f5`, whose parents are that source and +main `378346126949c90bb286b5217c24513fc2044f06`. The sanitized workflow receipt +records both identities. Downloaded TRX files confirm 1,705 unit, 203 architecture, +four contract, 180 Docker-free integration and 872 Docker integration passes: +2,964 backend tests, zero failures/skips. All three locale/branding/combined-scope +cases are present and Passed. Frontend job output confirms 1,444 web + 60 SDK +passes, zero failures/skips/todos; typecheck, lint, builds and SDK drift pass. +Meta, secret scan and OpenAPI compatibility pass too. + +The `public-demo-lighthouse` artifact contains exactly 27 JSON/HTML report pairs, +nine screenshots and two sanitized receipts; no private logs, profiles, env files +or keys are included. Report digests, nine URL/three-run census, configuration, +invocation, build and synthetic checkout identities match. The invocation is +`aab02c37c71c02569f71ef8829a96c09`; build is `yTmMjFs6JVE2ea_W-jFzX`. +Node 22.23.1, Lighthouse 13.5.0, Playwright 1.64.0 and Chromium revision 1248 / +156.0.8078.4 run on the four-CPU Ubuntu 24 hosted runner. Its sandbox-enabled +launch passes with the exact-executable temporary AppArmor prerequisite; +the owned policy removal passes afterward. + +All nine linked navigations and 24 planted visibility refusals pass. Every audit +has normalized initial JS gzip 106,359–106,553 bytes, CLS 0 and automated +accessibility 1. Per-URL timing medians remain advisory, not production p95. +All 134 API observations are 200, with zero 429, malformed or pending records: +six startup + two observer-control + 18 linked-browser + 3 × 36 audit calls. +Both TLS refusal controls and the actual audit-timeout control pass. Keycloak is +stopped before anonymous navigation. Setup/proof/cleanup take +228,127 / 650,154 / 11,041 ms; the proof stays inside 12 minutes and cleanup +inside 30 seconds. The complete job takes 15 minutes 51 seconds, within its +20-minute ceiling and absolute setup/proof deadline. + +After that successful run, the authorized API update adds only +`public demo + lighthouse` to main's required contexts. A fresh full read-back +confirms seven GitHub Actions contexts (`app_id: 15368`), strict up-to-date +checking, all six prior contexts retained and every unrelated protection setting +identical to the immediately preceding API response. The current list lives in +[CONTRIBUTING](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main). + +The [individual evidence matrix](phase-02d-exit-evidence.md) reconciles all +36 deliverables, 79 criteria, 39 explicit exclusions and E01–E09. All 45 register +rows have dated Accepted closure links; no Phase 02d-owned Registered/Awaiting +catalogue rule remains. All four ADR-0056 rules are Implemented; corpus checks +confirm 175 Implemented catalogue entries and 21 Active/one Adopted standards. +The existing P6 human/VoiceOver evidence retains its original attribution and +limits; this closeout claims no new final-head manual WCAG or zoom audit. +Phase 05 preservation and P02b-0 premises are handed off above and in their +owning documents; no future-phase decision is accepted by this exit. +Closing-document checks pass all five CorpusConsistencyTests with zero skips; +the 33 changed/new Markdown files resolve 2,197 relative links and 694 fragments +with no errors. Added prose respects 88 columns; ADR-0056 changes are insertion-only. + +##### Reviewed implementation head verification (2026-10-11) + +The first run above owns activation history. The separately downloaded +[reviewed-head run](https://github.com/HodeTech/LearnStack/actions/runs/38108622191) +passes all seven jobs for source `d47ef17c8473e17e0950361dc35e419ba6c0825c`, +tested merge `ba44563af66fbd7744b6625673e61286a8e77fa4` with the same main parent. +Its invocation is `170c02e7741fbc6c79895ce718cecd89`; build is +`rlL6ubYmcf7_VQaPBN-fA`. TRX/frontend receipts confirm the same 2,964 backend +and 1,504 frontend passes, zero failures/skips/todos. + +All 27 report pairs, nine screenshots, nine navigations and 24 visibility +refusals pass. Report digests and source/build/invocation/configuration identities +match. Normalized gzip is 106,358–106,551 bytes, CLS 0 and automated +accessibility 1 throughout. Both TLS refusals, the audit-timeout control and all +134 API observations (200 only, no malformed/pending records) pass. +Setup/proof/cleanup take 214,616 / 644,207 / 12,962 ms; all cleanup flags pass. +Sandbox-enabled Chromium and owned AppArmor cleanup pass. These numbers belong +to the exact implementation head reviewed externally, not to later commits. + +##### External review follow-up (2026-10-11) + +The maintainer's review of `3783461..d47ef17` reported no Blocker/Major and +four bounded documentation/maintenance findings. All four are verified and +addressed: the reviewed-head receipt above supplements activation history; +runtime imports move to the file header; installed tool/browser metadata feeds +the shared census and remains checked against independent committed pins; and +ADR-0056 gains dated acceptance-baseline navigation without changing history. +Tool versions, budgets, admission and cleanup behavior are unchanged. + +Local validation passes 1,454 web + 60 SDK tests, zero failures/skips/todos, +typecheck, lint and all 203 architecture tests. Ten added cases cover installed +metadata/pin mismatch, malformed or missing browser metadata, stale census and +wrong-version report refusal, each retaining a clean passing control. Both fresh +independent remediation rounds reviewed `d47ef17..dca3a7b` and approved without +findings. Each independently checked installed dependency resolution, fail-closed +metadata/census comparison and the downloaded historical receipts. All five +corpus tests pass; the complete PR's 33 changed/new Markdown files resolve +2,201 relative links and 698 fragments without errors. The new remediation head +must still pass full seven-job CI through the PR rollup before merge. + +##### Systematic review remediation (2026-10-11) + +The later review examined source `aebefee`. Its findings were re-verified against +current code before changes; this is a separate record from the historical +`d47ef17` review above. No new architecture decision or budget change is needed. +Work remains on `development`; PR #28 is not merged by this record. + +1. **Lifecycle and launcher — complete.** `cd6affd` removes the unsupported + Seeder launcher argument, attempts independent process/observer/Compose + cleanup stages even when a preceding stage fails, and retains failure causes + internally without echoing private diagnostics. Private files are removed + only after confirmed cleanup. Socket errors distinguish occupied ports from + other bind failures; declaration files describe the actual lifecycle API. + `/artifacts/` is ignored. All 34 lifecycle tests, lint and typecheck pass. + Two first-round reviewers and a fresh second-round reviewer approved without + findings. +2. **Genericity census — complete.** `db6bcdf`, `90114f0` and `c6cd69f` close + source-root/format admission and supported static import gaps. Local and + inherited-config candidate ambiguities are conservatively included or + refused; workspace manifests have explicit ownership. Backend evaluation + checks `Compile` and `ProjectReference` coverage, exact output roots and + bounded build shapes/properties. First-round frontend/backend reviewers + identified five verified resolution/build-admission gaps, fixed in + `90114f0`. The fresh second round found inherited-config shadowing, fixed in + `c6cd69f`; its same counterexample now refuses and its clean control passes. + All 18 frontend genericity cases, seven backend genericity cases, all 203 + architecture cases, lint, typecheck and targeted format pass. This remains a + bounded exact-literal/static-import fence, not arbitrary program analysis. +3. **Proof helpers and carriers — complete.** `9a0d285` extracts actual worker + network-inventory reconciliation and verifier advisory aggregation for fast + dirty/clean controls. Navigation counts come from completed + observations; upload globs admit only named reports/screenshots/receipts. + Current architecture, infrastructure, standards and route-authoring guidance + describe delivered G44/G45 enforcement. Two first-round reviewers and a fresh + second-round reviewer approved without findings. The second round also + reproduced all historical advisory medians from the downloaded receipt. + All 128 focused tests, 1,537 frontend cases (1,477 web + 60 SDK) and 2,092 + Docker-free backend cases (1,705 unit + 203 architecture + four contract + + 180 integration) pass with zero failures/skips/todos. Release build, format, + lint, typecheck and production frontend builds pass; 15 sandbox-policy and + seven ADR-status controls pass. The complete PR's 36 Markdown files resolve + 2,289 relative links and 719 fragments; added prose respects 88 columns. + The final PR rollup must still pass all seven required jobs, including the + real Docker and 27-audit lifecycle proof, before merge. + +**Late automatic-review follow-up.** Run 38125035732 passes all seven jobs for +source `4541d63`, including 2,964 backend and 1,537 frontend cases, the real +27-audit proof and cleanup. A later CodeRabbit comment exposed a local-DX gap: +ignored `.env.local` and OS/editor files reached raw filesystem classification. +The follow-up admits only explicitly known machine filenames that Git also +ignores. Ignored source files, unknown formats and compiler coverage retain +fail-closed behavior. The first independent round approved `d16d2d7`. The fresh +second round reproduced an automatically imported `.csproj.user` build hook; +`.user` is therefore excluded from the machine-file exemption in `9343e99`, +with explicit refusal controls. The reviewer independently re-ran the actual +collector: clean ignored files pass and the original build-hook counterexample +refuses. Both review rounds are complete, with no remaining findings. All 19 +frontend and seven backend genericity cases pass; the complete guarded frontend +rerun passes 1,538 cases (1,478 web + 60 SDK), zero failures/skips/todos. +Owned temporary ignored-file controls pass both actual raw collectors and are +removed afterward. Whitespace and the complete PR's link/fragment audit pass. +The final PR rollup below owns replacement final-head CI; all seven jobs remain +required before merge. + +**CI stability follow-up.** Run 38126790757 reports one unit-test failure in +`A_Factory_That_Ignores_Its_Token_Is_Still_Bounded`; all 203 architecture cases, +including the new admission controls, pass. This pre-existing test races an +80 ms cache deadline against a 600 ms factory delay. It now holds the factory +behind an explicit release signal until the cache's own timeout is observed, +checks that a replacement waits and retains the late-result/cache assertions. +The bounded test wait cannot masquerade as the cache timeout: its message must +identify the cache's own deadline. The release is guaranteed in `finally`. +Production cache behavior and its budget are unchanged. `32a7951` delivers +this test-only fix. Fresh GPT-6.1-sol (high) and GPT-6-astra (high) reviews approve +in two separate rounds with no findings; the second reviewer independently +passes the focused Release case. All 51 cache cases and all 1,705 unit cases +pass with zero skips. Replacement final-head CI remains required by the rollup +below; the initial failed job is not counted as passing evidence. + +**Other finding dispositions.** The gzip adapter equality checks wiring; the +independent Script observer checks source-window coverage, not a second byte +measurement. Existing fast tests already cover report admission, source-byte +normalization, completion accounting and gatherer cleanup; full orchestration, +TLS refusal, real visibility and report-file checks remain real lifecycle/CI +proofs. The added helpers supplement those proofs rather than replacing them. +The review's zero-fast-coverage claim was therefore broader than the actual gap. + +The reported PR-body count/gzip mismatch compared different receipts. Downloaded +[run 38119659152](https://github.com/HodeTech/LearnStack/actions/runs/38119659152) +for source `aebefee`, tested merge `0bb897c`, verifies 2,964 backend and 1,514 +frontend passes, gzip 106,358–106,552 bytes. Historical `d47ef17` numbers above +remain correct for that earlier head; neither substitutes for final remediation +CI. The newer proof took 619,309 ms inside the accepted 720,000 ms deadline; +cleanup took 10,595 ms inside 30,000 ms. No deadline increase is justified. + +Ordinal complete-value matching and strict readable JSON are accepted G20 +behavior, so host case-folding and JSON-comment tolerance are not introduced. +Below-fold laid-out content remains valid full-page evidence; adding a viewport +bottom cutoff would reject legitimate long lessons. Bounded child ownership +records are retained through process-group/EOF confirmation; no sustained leak +was demonstrated. The older `public-local` exit behavior, dormant platform +branches and test-project placement are unchanged maintenance suggestions. +Census regeneration instructions already name the authoritative Seeder command. + +Mutable Action tags are pre-existing throughout CI, with no accepted SHA-pinning +policy. This patch does not introduce a repository-wide dependency policy; +[Security Standards](../standards/11-security.md#dependency-hygiene) already assign +update automation to Phase 11. Accepted ADR-0053/0056 baseline and dated notes +remain historical; their then-pending wording is not rewritten as a correction. +Current carriers link delivered P7 evidence instead. No new human/WCAG evidence +is claimed by these orchestration and proof changes. + +Closing documentation commits must also pass the seven required jobs before +merge; the [PR check rollup](https://github.com/HodeTech/LearnStack/pull/28/checks) +owns that moving-head result. Next after maintainer review and merge is +**P02b-0 re-verification and decision pass**, before Phase 02b implementation. + +### P02d-7 merge and closeout (2026-10-11) + +The maintainer merged [PR #28](https://github.com/HodeTech/LearnStack/pull/28) at +2026-10-11 09:38:58 UTC. GitHub records final PR source +`8d9d2195cfadf1d83807613ea22d792b7ce329f4` and squash merge +`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`, whose parent is the previous main +`378346126949c90bb286b5217c24513fc2044f06`. Source and squash merge have the +identical tree `7f83bee243fe17626ef10af051e54a9218fd7aaa`. Development incorporates +the main merge without switching branches or rewriting published history. + +All seven required checks pass in the +[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38127402847) +for that source. The tested synthetic merge is +`2d8ff6b23cd1b27691ea0038859944ca6c0ce395`, with the final source and previous +main as parents. Independently verified downloaded receipts confirm: + +- **2,964 backend passes**, zero failures/skips: 1,705 unit, 203 architecture, + four contract, 180 Docker-free integration and 872 Docker integration cases. +- **1,538 guarded frontend passes**: 1,478 web and 60 SDK, zero + failures/skips/todos; lint, typecheck, builds and SDK drift also pass. +- Exactly 27 Lighthouse JSON/HTML report pairs, nine screenshots and two + sanitized receipts. Report digests, source/checkout/build/invocation identities + and the nine-URL/three-run census match. Normalized initial JS gzip is + 106,358–106,552 bytes, CLS 0 and automated accessibility 1 throughout. + Per-URL timing medians remain advisory. +- Nine linked navigations, 24 planted visibility refusals, both TLS refusals and + the actual audit-timeout control pass. All 134 API observations are 200, + with zero 429, malformed or pending records. Setup/proof/cleanup take + 170,462 / 618,055 / 10,695 ms; all owned-cleanup flags pass. +- A fresh protection read-back retains `strict: true` and all seven GitHub + Actions contexts, including `public demo + lighthouse`. This closeout changes + no protection setting. + +The [post-merge main run](https://github.com/HodeTech/LearnStack/actions/runs/38129121225) +tests the squash commit separately; its result is not inferred from source CI. +At this documentation check, five jobs pass; Docker integration and the +demo/Lighthouse job are still running. + +**P02d-7 and Phase 02d are closed.** All seven implementation packets are merged; +all four P7 steps and verified fixes retain their recorded independent reviews. +The [individual exit evidence](phase-02d-exit-evidence.md) reconciles all +36 deliverables, 79 completion criteria, 39 exclusions and nine exit obligations. +Earlier dated delivery/review records, Accepted ADRs and their acceptance-time +or pre-merge wording remain historical and unchanged. No new human/VoiceOver, +full WCAG, zoom, production-p95 or deployment-readiness claim is added. + +**Next: P02b-0 — phase-entry re-verification.** The +[Phase 02b packet table](phase-02b-events-auth.md#packets-and-decision-gates) +requires re-reading code, corpus and Hub premises against HEAD, including the +[P7 handoff](#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11). +P02b-0 has not started; each later packet closes its own gates in its decision +pass. No Phase 02b implementation or auth/BFF decision is accepted here. + +Phase 05 retains versioned-curriculum migration and preservation of existing +Education/seed records; Phase 06 retains full renderer/Studio and Playwright +Test/axe; Phase 07 retains enrollment, learner portal, progress and access grants. +Phase 11 retains production hardening, telemetry and demand-gated adapters. +Course Marketplace ADR-0049 and Phase 09a remain Proposed; commerce, commissions, +payouts and cross-installation federation are not delivered. + +**Documentation-only closeout validation.** All 203 local Release architecture +cases and seven ADR lifecycle/workflow controls pass, with zero failures/skips. +The seven changed Markdown files resolve 1,088 relative links and 478 fragments +with zero errors; added prose wrapping and whitespace checks pass. Prior dated +phase delivery records and all Accepted ADR files are byte-preserved. Full runtime +suites are not rerun locally for this documentation-only change; the final PR +receipts above supply their evidence. + +## Status archive + +The Status block the phase document carried until 2026-10-22, kept verbatim. Its +in-document links were retargeted to whichever file now holds their target. The +phase document's current Status block replaces it; nothing below is current. + +> **Status (2026-10-11).** Phase 02d is **complete and merged** through +> [PR #28](https://github.com/HodeTech/LearnStack/pull/28). The +> [merge closeout](#p02d-7-merge-and-closeout-2026-10-11) records final verification +> and the completed phase exit. P02b-0 phase-entry re-verification is next. +> The kickoff, `P02d-0`, ships this +> plan — the inherited baseline, the packet table, the decision register, criteria that +> name their evidence, and the corrections to the documents that contradicted the phase +> — and no code. Every later packet opens with its decision pass and updates its own +> row, linking its delivery record. +> +> | Packet | Title | State | +> |---|---|---| +> | P02d-0 | Kickoff | ✅ this plan | +> | P02d-1 | Education schema and database-level isolation | ✅ complete and merged — 2026-09-14; [merge closeout](#merge-and-closeout-2026-09-14) | +> | P02d-2 | Writers and seed | ✅ complete and merged — 2026-10-02; [merge closeout](#p02d-2-merge-and-closeout-2026-10-02) | +> | P02d-3 | Read internals | ✅ complete and merged — 2026-10-03; [merge closeout](#p02d-3-merge-and-closeout-2026-10-03) | +> | P02d-4 | Public read API and contract checks | ✅ complete and merged — 2026-10-08; [merge closeout](#p02d-4-merge-and-closeout-2026-10-08) | +> | P02d-5 | Server-rendering path | ✅ complete and merged — 2026-10-09; [merge closeout](#p02d-5-merge-and-closeout-2026-10-09) | +> | P02d-6 | Public renderer | ✅ complete and merged — 2026-10-10; [merge closeout](#p02d-6-merge-and-closeout-2026-10-10) | +> | P02d-7 | Demo, full-stack CI and exit | ✅ complete and merged — 2026-10-11; all four steps completed both independent review rounds; [merge closeout](#p02d-7-merge-and-closeout-2026-10-11) | + +**Acceptance update — 2026-10-02.** P02d-1 remains merged. The maintainer accepted +ADR-0050/0051 and the [P02d-2 package](#p02d-2-decision-package-2026-10-02), including +its four implementation steps. Required decision bookkeeping is complete; this +update delivers no code. Implementation has not started and waits at the maintainer's +explicit request. ADR-0049 and Phase 09a remain Proposed. + +**Implementation resumed — 2026-10-02.** The maintainer's implementation request +revokes the acceptance-time wait. [Delivery](#p02d-2-implementation-delivery-2026-10-02) +records all four completed implementation steps and their two independent review +rounds. At that pre-merge milestone, P02d-2 was ready for PR review, its merge +closeout was pending, and P02d-3 was next. + +**Merge complete — 2026-10-02.** The acceptance and implementation notes above +record the pre-merge milestones. P02d-2 is now closed through +[PR #23](https://github.com/HodeTech/LearnStack/pull/23); its +[merge closeout](#p02d-2-merge-and-closeout-2026-10-02) records verification. +At that closeout, Phase 02d remained in progress and P02d-3 was next, with its +decision pass still open. + + +**P02d-3 complete — 2026-10-02, unmerged.** The preceding notes record earlier +milestones. The [decision package](#p02d-3-decision-package-2026-10-02) is Accepted; +all three implementation steps and both fresh review rounds per step are complete. +The [delivery record](#delivery-record-p02d-3) records code, verified fixes and +2637 passing tests. The packet is ready for maintainer PR review. P02d-4 is next: +its public-read decision pass and contracts are not started. + +**Merge complete — 2026-10-03.** The preceding P02d-3 note is its pre-merge +milestone. P02d-3 is now closed through +[PR #24](https://github.com/HodeTech/LearnStack/pull/24); its +[merge closeout](#p02d-3-merge-and-closeout-2026-10-03) records the final correction, +verification and merge. P02d-4's public-read decision pass is next; no public +endpoint or browser implementation is claimed by this closeout. + +**P02d-4 preparation — 2026-10-03.** The +[decision package](#p02d-4-decision-package-2026-10-03) and +[ADR-0052](../decisions/0052-anonymous-public-read-boundary.md) are Proposed after +document and code review. No gate is Accepted by this preparation and no code has +been written. The maintainer reviews one concrete package before implementation. + +**P02d-4 Accepted — 2026-10-03.** The maintainer approved ADR-0052 and the +[decision package](#p02d-4-decision-package-2026-10-03), including read-only setup, +host provenance, public contracts and the sixth required OpenAPI check. Decision +records and carrier updates precede implementation; the delivery record will own +actual code, reviews and checks. Development remains the working branch. + +**P02d-4 implementation complete — 2026-10-04, unmerged.** All four steps and +their two independent review rounds are complete. The +[delivery record](#p02d-4-step-4-contract-sdk-and-ci) records passing real CI and +verified activation of the sixth required check. +[PR #25](https://github.com/HodeTech/LearnStack/pull/25) awaits maintainer review +and merge. P02d-5 is next; its decision pass has not started. + +**P02d-4 merge complete — 2026-10-08.** The preceding notes record pre-merge +milestones. P02d-4 is now closed through +[PR #25](https://github.com/HodeTech/LearnStack/pull/25); its +[merge closeout](#p02d-4-merge-and-closeout-2026-10-08) records final verification. +Phase 02d remains in progress. P02d-5 is next; its decision pass has not started. + +**P02d-5 preparation — 2026-10-08.** The +[decision package](#p02d-5-decision-package-2026-10-08) and +[ADR-0053](../decisions/0053-trusted-public-server-rendering.md) are Proposed after +baseline review. The preceding merge note records the state at closeout. No P5 +gate is Accepted, no implementation is started and maintainer approval is pending. + +**P02d-5 acceptance — 2026-10-08.** The maintainer approved ADR-0053 and the +[decision package](#p02d-5-decision-package-2026-10-08) after the external-review +corrections. Its named gate parts close; implementation starts on development, +with four steps and two fresh review rounds per step. P6/P7 gates remain open. + +**P02d-5 implementation complete — 2026-10-09, unmerged.** All four steps and +their two independent review rounds are complete; confirmed fixes are verified and +committed. The [packet closeout](#p02d-5-packet-closeout-2026-10-09) records the final +local verification and scope. P02d-5 awaits maintainer PR review and merge. P02d-6's +public-renderer decision pass is next; no P6/P7 gate is closed by this delivery. + +**External-review remediation — 2026-10-09.** ADR-0054 is Accepted and its runtime +and proof corrections are delivered. The [current remediation record](#p02d-5-external-review-remediation-2026-10-09) +owns the five steps, their reviews and final PR/CI readiness. Earlier delivery +notes remain historical; PR #26 is not merged. + +**P02d-5 merge complete — 2026-10-09.** The preceding notes record pre-merge +milestones. P02d-5 is now closed through +[PR #26](https://github.com/HodeTech/LearnStack/pull/26); its +[merge closeout](#p02d-5-merge-and-closeout-2026-10-09) records the final head, +verification and merge. Phase 02d remains in progress. P02d-6's public-renderer +decision pass is next; P6/P7 implementation has not started. + +**P02d-6 preparation — 2026-10-09.** The +[decision package](#p02d-6-decision-package-2026-10-09) and +[Proposed ADR-0027](../decisions/0027-frontend-i18n.md) are ready for maintainer +review. All P6 gate parts remain unaccepted. The package explicitly proposes the +404 navigation/status tradeoff exposed by the pinned framework experiment; +implementation waits for approval, not an assumed framework guarantee. + +**P02d-6 acceptance — 2026-10-09.** The maintainer approved revised ADR-0027 and +the complete [decision package](#p02d-6-decision-package-2026-10-09), including +the local 307→404 URL change, HTTP 200/noindex content-failure states and four +implementation steps. The acceptance commit closes its named gate parts and +reconciles their carriers before code. Every step uses commits and two fresh +independent review rounds. Development remains the working branch. + +**P02d-6 implementation complete — 2026-10-10, unmerged.** All four steps and +both independent review rounds per step are complete. The +[packet closeout](#p02d-6-packet-closeout-2026-10-10) records automated verification, +manual browser observations and the maintainer's passing VoiceOver smoke. +P02d-6 awaits maintainer PR review and merge. P02d-7's demo, browser/Lighthouse +harness and phase-exit decision pass are next; they have not started. + +**P02d-6 merge complete — 2026-10-10.** The preceding notes record pre-merge +milestones. P02d-6 is now closed through +[PR #27](https://github.com/HodeTech/LearnStack/pull/27); its +[merge closeout](#p02d-6-merge-and-closeout-2026-10-10) records the final head, +verification and merge. Phase 02d remains in progress. P02d-7's demo, Lighthouse +and phase-exit decision pass is next; implementation has not started. diff --git a/docs/roadmap/phase-02d-exit-evidence.md b/docs/roadmap/phase-02d-exit-evidence.md index 6553ec2f..e8d10b69 100644 --- a/docs/roadmap/phase-02d-exit-evidence.md +++ b/docs/roadmap/phase-02d-exit-evidence.md @@ -3,9 +3,9 @@ **Reconciliation complete — 2026-10-11.** All four P7 steps completed both independent review rounds. The real PR check receipts, verified artifacts, seventh-check activation and positive exit verdict are recorded in the -[CI and exit closeout](phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11). +[CI and exit closeout](phase-02d-delivery-log.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11). This document is an evidence index, not a new architecture decision. PR #28 is -merged; the [merge closeout](phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) +merged; the [merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) owns final verification and the completed phase exit. The rows enumerate all 36 [deliverables](phase-02d-walking-skeleton.md#deliverables), @@ -34,7 +34,7 @@ identified separately where needed. P1–P6 refer to the merged packet records i [Phase 02d](phase-02d-walking-skeleton.md); Step 1–3 refer to P7's records. [Run 38127402847](https://github.com/HodeTech/LearnStack/actions/runs/38127402847) supplies final B/I/F/O/J for source `8d9d219`, tested merge `2d8ff6b`; the -[merge closeout](phase-02d-walking-skeleton.md#p02d-7-merge-and-closeout-2026-10-11) +[merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) records full identities and verified artifacts. Earlier runs retain their dated counts and seventh-check activation history. The squash merge has the same tree as the final PR source; its post-merge run is identified separately. @@ -53,7 +53,7 @@ causal focused proof; the final CI lifecycle must include it. H retains PR #27's original manual attribution: commit `180dde0`, macOS 27.0.1, Brave 154.1.96.61, both seeded hosts and EN/TR routes. The -[P6 closeout](phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +[P6 closeout](phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records keyboard/focus, 320 CSS-pixel reflow and long-string observations, calculated contrast, and the maintainer's VoiceOver catalog → course → lesson, missing-page and invalid-link recovery smoke. Seeded contrast ratios were @@ -209,7 +209,7 @@ by listing its phase here. **Reconciled — 2026-10-12.** X04 follows the Accepted P02b-1 production contract and current Tenancy catalogue. P7's dated handoff remains preserved -with its [reconciliation](phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11). +with its [reconciliation](phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11). | ID | Exclusion locator | Named owner | Evidence and boundary | |---|---|---|---| @@ -267,7 +267,7 @@ with its [reconciliation](phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforc | E08 | Zero 02d Registered/Awaiting catalogue rows and standard/index alignment | Four P7 promotions with actual behavioral owners and hard CI, computed counts and Standard_Status_Headers_Match_The_Index exact-head receipt. | | E09 | Delivery record names moved P02b-0 premises | /api/v1 contract, *.learnstack.local native HTTPS/manual trust, visitor+peer quotas, seed default-org/tenant scopes, uncached settings with the dated future-invalidation reconciliation, single bootstrap; do not Accept auth/BFF future gates. | -The [Step 4 preservation and P02b-0 handoff](phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +The [Step 4 preservation and P02b-0 handoff](phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) names the retained Education data, live API/host/trust/limiter/bootstrap premises and the reconciled uncached-settings boundary. Phase 05 migrates the existing records; it does not treat reseeding as migration. Course Marketplace ADR-0049 diff --git a/docs/roadmap/phase-02d-walking-skeleton.md b/docs/roadmap/phase-02d-walking-skeleton.md index 66993062..e153d37f 100644 --- a/docs/roadmap/phase-02d-walking-skeleton.md +++ b/docs/roadmap/phase-02d-walking-skeleton.md @@ -1,141 +1,28 @@ # Phase 02d: Two-Tenant Walking Skeleton -> **Status (2026-10-11).** Phase 02d is **complete and merged** through -> [PR #28](https://github.com/HodeTech/LearnStack/pull/28). The -> [merge closeout](#p02d-7-merge-and-closeout-2026-10-11) records final verification -> and the completed phase exit. P02b-0 phase-entry re-verification is next. -> The kickoff, `P02d-0`, ships this -> plan — the inherited baseline, the packet table, the decision register, criteria that -> name their evidence, and the corrections to the documents that contradicted the phase -> — and no code. Every later packet opens with its decision pass and updates its own -> row, linking its delivery record. +> **Status (2026-10-22).** Phase 02d is **complete and merged** through +> [PR #28](https://github.com/HodeTech/LearnStack/pull/28) on 2026-10-11; its +> [merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) records final +> verification and the completed phase exit, and the +> [exit evidence](phase-02d-exit-evidence.md) maps each exit criterion to its proof. +> +> This document is the plan. Every dated decision package, step record, review +> round, correction and merge closeout lives in the [delivery log](phase-02d-delivery-log.md), split out +> on 2026-10-22 under +> [ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md). An Accepted +> decision package there is normative; the [decision register](#the-decision-register) +> links each answer. > > | Packet | Title | State | > |---|---|---| > | P02d-0 | Kickoff | ✅ this plan | -> | P02d-1 | Education schema and database-level isolation | ✅ complete and merged — 2026-09-14; [merge closeout](#merge-and-closeout-2026-09-14) | -> | P02d-2 | Writers and seed | ✅ complete and merged — 2026-10-02; [merge closeout](#p02d-2-merge-and-closeout-2026-10-02) | -> | P02d-3 | Read internals | ✅ complete and merged — 2026-10-03; [merge closeout](#p02d-3-merge-and-closeout-2026-10-03) | -> | P02d-4 | Public read API and contract checks | ✅ complete and merged — 2026-10-08; [merge closeout](#p02d-4-merge-and-closeout-2026-10-08) | -> | P02d-5 | Server-rendering path | ✅ complete and merged — 2026-10-09; [merge closeout](#p02d-5-merge-and-closeout-2026-10-09) | -> | P02d-6 | Public renderer | ✅ complete and merged — 2026-10-10; [merge closeout](#p02d-6-merge-and-closeout-2026-10-10) | -> | P02d-7 | Demo, full-stack CI and exit | ✅ complete and merged — 2026-10-11; all four steps completed both independent review rounds; [merge closeout](#p02d-7-merge-and-closeout-2026-10-11) | - -**Acceptance update — 2026-10-02.** P02d-1 remains merged. The maintainer accepted -ADR-0050/0051 and the [P02d-2 package](#p02d-2-decision-package-2026-10-02), including -its four implementation steps. Required decision bookkeeping is complete; this -update delivers no code. Implementation has not started and waits at the maintainer's -explicit request. ADR-0049 and Phase 09a remain Proposed. - -**Implementation resumed — 2026-10-02.** The maintainer's implementation request -revokes the acceptance-time wait. [Delivery](#p02d-2-implementation-delivery-2026-10-02) -records all four completed implementation steps and their two independent review -rounds. At that pre-merge milestone, P02d-2 was ready for PR review, its merge -closeout was pending, and P02d-3 was next. - -**Merge complete — 2026-10-02.** The acceptance and implementation notes above -record the pre-merge milestones. P02d-2 is now closed through -[PR #23](https://github.com/HodeTech/LearnStack/pull/23); its -[merge closeout](#p02d-2-merge-and-closeout-2026-10-02) records verification. -At that closeout, Phase 02d remained in progress and P02d-3 was next, with its -decision pass still open. - - -**P02d-3 complete — 2026-10-02, unmerged.** The preceding notes record earlier -milestones. The [decision package](#p02d-3-decision-package-2026-10-02) is Accepted; -all three implementation steps and both fresh review rounds per step are complete. -The [delivery record](#delivery-record-p02d-3) records code, verified fixes and -2637 passing tests. The packet is ready for maintainer PR review. P02d-4 is next: -its public-read decision pass and contracts are not started. - -**Merge complete — 2026-10-03.** The preceding P02d-3 note is its pre-merge -milestone. P02d-3 is now closed through -[PR #24](https://github.com/HodeTech/LearnStack/pull/24); its -[merge closeout](#p02d-3-merge-and-closeout-2026-10-03) records the final correction, -verification and merge. P02d-4's public-read decision pass is next; no public -endpoint or browser implementation is claimed by this closeout. - -**P02d-4 preparation — 2026-10-03.** The -[decision package](#p02d-4-decision-package-2026-10-03) and -[ADR-0052](../decisions/0052-anonymous-public-read-boundary.md) are Proposed after -document and code review. No gate is Accepted by this preparation and no code has -been written. The maintainer reviews one concrete package before implementation. - -**P02d-4 Accepted — 2026-10-03.** The maintainer approved ADR-0052 and the -[decision package](#p02d-4-decision-package-2026-10-03), including read-only setup, -host provenance, public contracts and the sixth required OpenAPI check. Decision -records and carrier updates precede implementation; the delivery record will own -actual code, reviews and checks. Development remains the working branch. - -**P02d-4 implementation complete — 2026-10-04, unmerged.** All four steps and -their two independent review rounds are complete. The -[delivery record](#p02d-4-step-4-contract-sdk-and-ci) records passing real CI and -verified activation of the sixth required check. -[PR #25](https://github.com/HodeTech/LearnStack/pull/25) awaits maintainer review -and merge. P02d-5 is next; its decision pass has not started. - -**P02d-4 merge complete — 2026-10-08.** The preceding notes record pre-merge -milestones. P02d-4 is now closed through -[PR #25](https://github.com/HodeTech/LearnStack/pull/25); its -[merge closeout](#p02d-4-merge-and-closeout-2026-10-08) records final verification. -Phase 02d remains in progress. P02d-5 is next; its decision pass has not started. - -**P02d-5 preparation — 2026-10-08.** The -[decision package](#p02d-5-decision-package-2026-10-08) and -[ADR-0053](../decisions/0053-trusted-public-server-rendering.md) are Proposed after -baseline review. The preceding merge note records the state at closeout. No P5 -gate is Accepted, no implementation is started and maintainer approval is pending. - -**P02d-5 acceptance — 2026-10-08.** The maintainer approved ADR-0053 and the -[decision package](#p02d-5-decision-package-2026-10-08) after the external-review -corrections. Its named gate parts close; implementation starts on development, -with four steps and two fresh review rounds per step. P6/P7 gates remain open. - -**P02d-5 implementation complete — 2026-10-09, unmerged.** All four steps and -their two independent review rounds are complete; confirmed fixes are verified and -committed. The [packet closeout](#p02d-5-packet-closeout-2026-10-09) records the final -local verification and scope. P02d-5 awaits maintainer PR review and merge. P02d-6's -public-renderer decision pass is next; no P6/P7 gate is closed by this delivery. - -**External-review remediation — 2026-10-09.** ADR-0054 is Accepted and its runtime -and proof corrections are delivered. The [current remediation record](#p02d-5-external-review-remediation-2026-10-09) -owns the five steps, their reviews and final PR/CI readiness. Earlier delivery -notes remain historical; PR #26 is not merged. - -**P02d-5 merge complete — 2026-10-09.** The preceding notes record pre-merge -milestones. P02d-5 is now closed through -[PR #26](https://github.com/HodeTech/LearnStack/pull/26); its -[merge closeout](#p02d-5-merge-and-closeout-2026-10-09) records the final head, -verification and merge. Phase 02d remains in progress. P02d-6's public-renderer -decision pass is next; P6/P7 implementation has not started. - -**P02d-6 preparation — 2026-10-09.** The -[decision package](#p02d-6-decision-package-2026-10-09) and -[Proposed ADR-0027](../decisions/0027-frontend-i18n.md) are ready for maintainer -review. All P6 gate parts remain unaccepted. The package explicitly proposes the -404 navigation/status tradeoff exposed by the pinned framework experiment; -implementation waits for approval, not an assumed framework guarantee. - -**P02d-6 acceptance — 2026-10-09.** The maintainer approved revised ADR-0027 and -the complete [decision package](#p02d-6-decision-package-2026-10-09), including -the local 307→404 URL change, HTTP 200/noindex content-failure states and four -implementation steps. The acceptance commit closes its named gate parts and -reconciles their carriers before code. Every step uses commits and two fresh -independent review rounds. Development remains the working branch. - -**P02d-6 implementation complete — 2026-10-10, unmerged.** All four steps and -both independent review rounds per step are complete. The -[packet closeout](#p02d-6-packet-closeout-2026-10-10) records automated verification, -manual browser observations and the maintainer's passing VoiceOver smoke. -P02d-6 awaits maintainer PR review and merge. P02d-7's demo, browser/Lighthouse -harness and phase-exit decision pass are next; they have not started. - -**P02d-6 merge complete — 2026-10-10.** The preceding notes record pre-merge -milestones. P02d-6 is now closed through -[PR #27](https://github.com/HodeTech/LearnStack/pull/27); its -[merge closeout](#p02d-6-merge-and-closeout-2026-10-10) records the final head, -verification and merge. Phase 02d remains in progress. P02d-7's demo, Lighthouse -and phase-exit decision pass is next; implementation has not started. +> | P02d-1 | Education schema and database-level isolation | ✅ complete and merged — 2026-09-14; [merge closeout](phase-02d-delivery-log.md#merge-and-closeout-2026-09-14) | +> | P02d-2 | Writers and seed | ✅ complete and merged — 2026-10-02; [merge closeout](phase-02d-delivery-log.md#p02d-2-merge-and-closeout-2026-10-02) | +> | P02d-3 | Read internals | ✅ complete and merged — 2026-10-03; [merge closeout](phase-02d-delivery-log.md#p02d-3-merge-and-closeout-2026-10-03) | +> | P02d-4 | Public read API and contract checks | ✅ complete and merged — 2026-10-08; [merge closeout](phase-02d-delivery-log.md#p02d-4-merge-and-closeout-2026-10-08) | +> | P02d-5 | Server-rendering path | ✅ complete and merged — 2026-10-09; [merge closeout](phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) | +> | P02d-6 | Public renderer | ✅ complete and merged — 2026-10-10; [merge closeout](phase-02d-delivery-log.md#p02d-6-merge-and-closeout-2026-10-10) | +> | P02d-7 | Demo, full-stack CI and exit | ✅ complete and merged — 2026-10-11; [merge closeout](phase-02d-delivery-log.md#p02d-7-merge-and-closeout-2026-10-11) | ## Goal @@ -169,8 +56,8 @@ anonymous, so it needs no identity provider. ### What this phase inherits -This is the Phase 02a entry baseline. The dated delivery records below own current -implementation; P02d-2 now supplies the locale, branding and Education writers. +This is the Phase 02a entry baseline. The dated records in the +[delivery log](phase-02d-delivery-log.md) own what the phase built on it. Most of what this phase meets is already shipped or already decided. Each item links its owner; where a choice is still open, it names the register row that answers it. @@ -217,6507 +104,272 @@ owner; where a choice is still open, it names the register row that answers it. [Packet 6](phase-02a-kernel-tenancy.md#delivery-record-packet-6); neither seed tenant holds a row, and no command writes one. **G11**, **G13**. - **The customization write path.** Both tenants hold the built-in `card` content type - and `plain` taxonomy, owned per tenant, and every Customization command bumps the - tenant's generation - ([Packet 8](phase-02a-kernel-tenancy.md#delivery-record-packet-8)). - `Customization.Application.Contracts` exposes no read; the module spec's § Primary - read flow says "Not implemented". **G12**, **G22**. -- **The seed.** [Packet 7](phase-02a-kernel-tenancy.md#delivery-record-packet-7) seeds - two tenants through the request path, maps the English school's host tenant-wide and - the yoga studio's host to its default organization, and writes both host rows on names - under `*.learnstack.local` that a browser reaches only after a hosts-file edit. Every - seeder step after provisioning announces the tenant's default organization. **G7**, - **G14**, **G32**. -- **The frontend scaffolds.** `frontend/apps/web/src/middleware.ts` answers `503` - whenever `NODE_ENV` is `production` (so under `next start`), writes the raw host into - `x-tenant-id`, copies every inbound header, matches `/api/healthz` too, and carries - TODOs that assign the work to Phase 02a. - `frontend/packages/sdk/src/{server,client}.ts` take a `tenantId` option and return - `{}`, which stops compiling once the generated `paths` is non-empty, and the package - root re-exports the server entry. `frontend/apps/web/.env.local.example` points the - API origin at APISIX, which only `make dev-gated` starts. The root layout fixes - `lang="en"` and a platform `<title>`. The Vitest harness, Packet 3b's placeholder page - test and Packet 10's `src/test/lint-rules.test.ts` exist; - `lib/customization/composites.ts` registers four composite keys and no component. - **G31**, **G35**, **G36**, **G38**, **G43**. -- **CI and the development loop.** The `openapi diff` and `lighthouse budget` jobs are - placeholders behind unset `vars.ENABLE_*` variables and report as skipped; activation - takes the edits - [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) - lists. The SDK pipeline is wired with empty output, and - [Frontend Architecture Standards § SDK](../standards/07-frontend-architecture.md#sdk) - gives its drift gate to this phase. The contract suite asserts only a `200` - ([Testing Standards § API Contract Tests](../standards/06-testing.md#api-contract-tests)). - The `backend integration (Testcontainers)` job runs on every pull request and is - required as of P02d-1. The inherited required-check gaps, including the renamed `meta` - check, are [repaired and verified in Step 3](#step-3--packet-completion-2026-09-14). - `make dev` starts containers only, `dotnet run` reads no `.env`, and - `make seed` waits on every default-profile service and both Keycloak realms - ([Infrastructure Standards § Healthchecks and the readiness gate](../standards/12-infrastructure.md#healthchecks-and-the-readiness-gate)). - No job starts the API or `next start` as a process a browser can reach. **G31**, - **G44**, **G45**. -- **Standards that meet their first subject here.** A new module owes its spec and - audit-coverage matrix - ([Documentation Standards § Per-Module Specifications](../standards/13-documentation.md#per-module-specifications), - [Audit Coverage Standards](../standards/18-audit-coverage.md)). - [Accessibility Standards](../standards/16-accessibility.md) binds the first public - surfaces, and the [standards index](../standards/README.md#honest-status-today) row - for Localization Standards places the i18n runtime in Phase 04. **G39**, **G43**. -- **What Phase 02b expects of this phase.** The development-transport part of its gate - **G12** - ([Phase 02b § The decision register](phase-02b-events-auth.md#the-decision-register)), - now **G32**; the shared-peer premise of its **G14**, now **G34**; and its criterion - that both sites still render anonymously with Keycloak stopped. - -P02d-1 implements Education's roots, translations, migration and isolation. -P02d-2 implements its six commands and seeded data. P02d-3 supplies internal reads; -P02d-4 supplies public endpoints and contract/SDK controls. P02d-5 supplies native -HTTPS ingress, coordinated anonymous admission, the configured trusted server -caller and live-host/locale entry. Public product pages, text-card components, -theme injection and accessibility remain P02d-6; the browser/demo/Lighthouse -harness and phase exit remain P02d-7. - -### Explicitly not in this phase - -Named so that no reader has to guess, and so no later phase can assume it was done here: - -| Capability | Owning phase | -|---|---| -| Authentication, sessions, login | [Phase 02b](phase-02b-events-auth.md) | -| Token-keyed authenticated and write rate-limit budgets, and what the pre-authentication limiter does once a caller is validated | [Phase 02b](phase-02b-events-auth.md) (G14) | -| Keycloak realm reconciliation (a seed step that writes to Keycloak) | [Phase 02b](phase-02b-events-auth.md) (G12) | -| Future settings caching and any required invalidation | A future cached consumer's scope/key/freshness decision; [Phase 11](phase-11-production-hardening.md#demand-gated-building-blocks) owns triggered distributed adapters. The [Tenancy catalogue](../modules/tenancy/README.md#integration-event-catalogue) declares no settings-invalidation event | -| Isolation tests through authenticated or id-addressed routes | [Phase 02b](phase-02b-events-auth.md) | -| Identity domain, roles, permissions, invitations; permission keys for public reads; the rule that every endpoint carries `[Authorize]` or `[AllowAnonymous]` | [Phase 03](phase-03-identity-admin.md) | -| A tenant-scope read across all organizations on a tenant host (the `app.scope` carrier) | [Phase 03](phase-03-identity-admin.md) | -| CMS editing, page builder, media library and tenant media origins | [Phase 04](phase-04-cms-media-pages.md) | -| Per-locale publish readiness workflow, `tenant_route_slugs` registry | [Phase 04](phase-04-cms-media-pages.md) | -| Studio authoring of translated field values (titles, bodies, slugs) and the view of untranslated gaps — where it lives is an open question | [Phase 04](phase-04-cms-media-pages.md#admin-studio-cms-screens); its screen row goes in [Phase 06 § Admin Studio — screen ownership](phase-06-renderer-admin-studio.md#admin-studio--screen-ownership) | -| `Accept-Language` negotiation for API-returned messages; the per-tenant locale fallback chain; the `/{locale}/{slug}` page routing shape | [Phase 04](phase-04-cms-media-pages.md) | -| Authoring and translating a content type's field order and labels; the closed set of built-in primitive field types (number, boolean, date/time, select) | [Phase 04](phase-04-cms-media-pages.md) | -| The schema-version migration path for stored instances; deleting a content-type revision after a zero-instance count | [Phase 04](phase-04-cms-media-pages.md) | -| Customization deprecate and revise commands, and per-band taxonomy editing | [Phase 04](phase-04-cms-media-pages.md) and [Phase 05](phase-05-education-learning-content.md), consolidated in [Phase 06](phase-06-renderer-admin-studio.md) | -| Tenant-authored page composition (`TenantPageBlock` rows and their cache family) | [Phase 04](phase-04-cms-media-pages.md); the block resolver is [Phase 06](phase-06-renderer-admin-studio.md)'s | -| Deciding whether a customization change owes an integration event | [Phase 04](phase-04-cms-media-pages.md), per [the Customization spec § Integration-event catalogue](../modules/customization/README.md#integration-event-catalogue) | -| The `Redirect` model the CMS auto-creates when a published slug changes | [Phase 04](phase-04-cms-media-pages.md) | -| Search — the `ITenantSearch` port and its PostgreSQL default | [Phase 04](phase-04-cms-media-pages.md) | -| Search — the Meilisearch adapter behind that port | [Phase 09](phase-09-billing-integrations-analytics.md) | -| Course versioning, programs, lesson items, completion rules; richer publish-readiness validation and versioned publication; catalog visibility separate from publication | [Phase 05](phase-05-education-learning-content.md) | -| The migration that brings this phase's courses and lessons under course versions and modules | [Phase 05](phase-05-education-learning-content.md) | -| The authenticated course and lesson authoring surface, with the commands that edit a course or lesson or reorder lessons after the seed | [Phase 05](phase-05-education-learning-content.md) | -| The `Level` aggregate and the catalog API's levels resource; the `TenantLevelTaxonomy` editor | [Phase 05](phase-05-education-learning-content.md) | -| The `TenantLessonItemType` read, the batched reference walk and the measured customization cost model; the `embed-html` sanitisation contract | [Phase 05](phase-05-education-learning-content.md) | -| Admin Studio, navigation menus, SEO metadata beyond what G40 settles for translated public pages, full block registry | [Phase 06](phase-06-renderer-admin-studio.md) | -| The full `UnknownVersionBlock` / `UnknownBlock` placeholders and per-block error boundary; tenant-authored error pages; redirect handling | [Phase 06](phase-06-renderer-admin-studio.md) | -| Branding configuration surface — tenant-admin editor, theme preview, logo, header and footer settings; the per-organization branding override (`OrganizationBranding`) and the token merge | [Phase 06](phase-06-renderer-admin-studio.md) | -| Preview of draft courses and lessons through the production renderer | [Phase 06](phase-06-renderer-admin-studio.md) | -| Browser end-to-end flows (Playwright) and axe checks through Playwright | [Phase 06](phase-06-renderer-admin-studio.md), per [Testing Standards § End-to-End Tests](../standards/06-testing.md#end-to-end-tests); any narrow smoke this phase adopts is G38 | -| Enrollment, learner portal, progress tracking; [Course Access](../glossary.md) — whether content published anonymously here stays on the public path once enrollment exists | [Phase 07](phase-07-enrollment-learner-portal.md) | -| Live classroom | [Phase 08c](phase-08c-classroom.md) | -| Billing | [Phase 09](phase-09-billing-integrations-analytics.md) | -| Hub, entitlement gating | [Phase 02c](phase-02c-hub-foundation.md) | -| APISIX as the edge gateway for a non-development deployment; gateway or CDN caching; edge rate limiting | [Phase 11](phase-11-production-hardening.md#security), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | -| Plan-differentiated API rate limits (`LimitKeys.ApiRatePerMinute`) | [Phase 11](phase-11-production-hardening.md#security) for the key's gate; [Phase 02c](phase-02c-hub-foundation.md) for its enforcement path | -| The L2 cache tier behind `ICacheService` (default `InMemoryCacheService`) | [Phase 11](phase-11-production-hardening.md), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | -| Content-Security-Policy and the other secure headers | [Phase 11 § Security](phase-11-production-hardening.md#security), per the [standards index](../standards/README.md#honest-status-today) row for Security Standards | -| `GET /readyz`; the production Dockerfile and image pipeline; the performance baseline and load tests against [Performance Standards](../standards/15-performance.md) | [Phase 11](phase-11-production-hardening.md) | -| Custom-domain TLS automation | [Phase 11](phase-11-production-hardening.md), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | - -Decisions made or referenced in this phase: - -- [ADR-0003 Tenant Isolation Defense in Depth](../decisions/0003-tenant-isolation-defense-in-depth.md) - (Amendment 3's template, Amendment 5's organization write guards and the accepted - Amendment 6 INSERT and parent-mirror correction every Education table takes) -- [ADR-0048 Publication Before Course Versioning](../decisions/0048-walking-skeleton-publication.md) - (independent course and lesson state, combined anonymous-read eligibility, and - Phase 05 preservation obligations) -- [ADR-0008 Localization Schema](../decisions/0008-localization-schema.md) (satellite - translation tables; slugs on the translation row, unique within `(tenant_id, locale)`) -- [ADR-0010 Cross-Module Communication](../decisions/0010-cross-module-communication.md) - (Education reads Customization and Tenancy only through their application contracts) -- [ADR-0013 Page Block Schema Versioning](../decisions/0013-page-block-schema-versioning.md) - (the pin rule - [Tenant Customization Model § 4](../architecture/32-tenant-customization-model.md) - extends to content types, and the placeholder for an unknown version) -- [ADR-0017 Tenant / Organization Hierarchy](../decisions/0017-tenant-organization-hierarchy.md) - (organization scope; `OrganizationBranding` as Phase 06's override) -- [ADR-0018 Tenant-Driven Customization Model](../decisions/0018-tenant-driven-customization-model.md) - (genericity, the renderer architecture, and its 2026-09-04 key and locale amendment) -- [ADR-0023 Strongly-Typed Id Source Generator](../decisions/0023-strongly-typed-id-source-generator.md) - (the new aggregates' identifiers) -- [ADR-0024 API Versioning Policy](../decisions/0024-api-versioning-policy.md) (what the - breaking-change check freezes) -- [ADR-0032 Exception Handling, Logging, and Observability Architecture](../decisions/0032-exception-handling-logging-and-observability.md) - (the pipeline, `Result<T>`, Problem Details, the controller shape) -- [ADR-0033 Audit Durability Model](../decisions/0033-audit-durability-model.md) and - [ADR-0044 Audit Write Path](../decisions/0044-audit-write-path.md) (classification of - the anonymous reads and of the MUST-class writes) -- [ADR-0034 Hub Contract Surface Invariant](../decisions/0034-hub-contract-surface-invariant.md) - (host resolution never calls the Hub) -- [ADR-0035 Demand-Gated Infrastructure](../decisions/0035-demand-gated-infrastructure.md) - (this scope fires no trigger) -- [ADR-0036 Tenant Resolution and Trusted Inputs](../decisions/0036-tenant-resolution-trusted-inputs.md) - (host resolution, the trusted hop and the pre-classification limiter; G33 and G34 may - owe it an amendment) -- [ADR-0039 The Optimistic Concurrency Token](../decisions/0039-optimistic-concurrency-token.md) - (`row_version` and the one ETag derivation) -- [ADR-0040 Ambient Unit of Work](../decisions/0040-ambient-unit-of-work.md) (the closed - setter set G15, G22 and G23 test against, and the read-only mode G28 may add) -- [ADR-0041 Correcting False Statements in Accepted ADRs](../decisions/0041-correcting-false-statements-in-accepted-adrs.md) - (how an erratum a decision pass finds is written) -- [ADR-0042 Tenant Provisioning Cross-Aggregate Transaction](../decisions/0042-tenant-provisioning-cross-aggregate-transaction.md) - (each locale and setting row by its own command; one aggregate root per command) -- [ADR-0043 Customization Payload Validation](../decisions/0043-customization-payload-validation.md) - (lesson-body validation on the command path; no compiled-validator cache) -- [ADR-0045 Entitlement and Feature-Flag Socket](../decisions/0045-entitlement-and-feature-flag-socket.md) - (`tenancy.white_label_branding`, whose meaning G16 asks) -- **Accepted [ADR-0027](../decisions/0027-frontend-i18n.md)** — the frontend i18n - library and catalogue contract; P02d-6 first consumer, accepted with G39 on - 2026-10-09. Phase 04 consumes the foundation; implementation is separate. - -## Scope - -### Packets and decision gates - -Phase 02a needed twelve packets for a narrower scope. This phase declares eight, in -dependency order. `P02d-0` writes no code. Every packet after it opens with the decision -pass [Roadmap § Decision Timing](README.md#decision-timing) describes: its gates are -Accepted, and its catalogue rows registered, before its first line of code. - -| Packet | Contents | Cannot start until | -|---|---|---| -| **P02d-0** | Phase entry: this plan — the inherited baseline, the packet table, the decision register, criteria that name their evidence, and the corrections to the documents that contradicted the phase. It answers no gate. The required-check edits identified at kickoff belong to `P02d-1`; its [delivery record](#step-3--packet-completion-2026-09-14) records their repair | Phase 02a exits (met) | -| **P02d-1** | Education schema and database-level isolation: the Education migration chain (`courses`, `lessons`, both translation satellites) with its policies, grants, foreign-key indexes and immutability triggers; the insert-time organization control; aggregates and EF configuration; the structural guards; the schema-level Education isolation suite as `learnstack_app`; the Education module spec skeleton and its pinned-list entry | G1, G2, G3 (values), G4, G5 (column), G6 (a), G7, G8, G9, G10 (order), G26 (slug grammar) Accepted | -| **P02d-2** | Writers and seed: the Education write commands and the Tenancy locale and setting commands, with their catalogue sources, matrices and composition-root registration; the Customization contract the lesson writer calls; the seeder's acts, contexts, ordering and re-run behaviour; each tenant's own content type, taxonomy, locales, branding, courses and lessons; `SeederTests` and the Packet 7 suite recomputed | G3 (commands and seeded states), G5 (validation), G7 (child derivation), G11, G12 (contract), G13, G14, G15, G16 (a–e), G17, G18, G19, G20 (literal source), G21 (subresources), G23 (bound) Accepted; P02d-1 | -| **P02d-3** | Read internals, no HTTP: the generation-keyed customization projection and its cache families; the typed settings accessor | G12 (cache key), G22, G23 (accessor), G24 Accepted; P02d-2 | -| **P02d-4** | Public read API and contract checks: the `[PublicSurface]` reads, their table rows and classification; response contracts, read eligibility, the cursor and the locale matrix; the cache directive; the committed OpenAPI snapshot with the breaking-change check, the regenerated SDK types and the drift gate, activated and required; the request-level Education isolation suite with positive controls | G5 (unresolved band), G6 (b), G10 (codec), G12 (response), G16 (f, g), G24 (response), G25, G26, G27, G28, G29, G30, G31 Accepted; P02d-3 | -| **P02d-5** | Server-rendering path: the development hostnames and transport; the development trusted-hop configuration; the server SDK transport; the middleware replacement and entry behaviour; the anonymous limiter over the hop; the rendering mode; the hop runtime evidence; the frontend skip refusal and the hop predicates' tests | G6 (c), G20 (exemptions), G21 (cookies), G30 (headers), G32, G33, G34, G35, G36, G37, G38 (a, d), G44 (whether) Accepted; P02d-4 | -| **P02d-6** | Public renderer: the `(public)` route tree, pages and page states; the UI message layer; lesson field rendering and its fallbacks; theming injection; the accessibility minimum; the renderer's tests | G5 (unresolved band), G12 (page state), G16 (g), G20 (subjects), G38 (b, c), G39, G40, G41, G42, G43 Accepted; P02d-5 | -| **P02d-7** | Demo, full-stack CI and exit: `make demo` and its stop behaviour; the full-stack Lighthouse job if G44 activates it here; the Keycloak-stopped check; the standards-index transitions; the outbound carrier re-verification; the delivery record naming what `P02b-0` re-verifies; the exit checks | G20 (Implemented), G33 (CI), G38 (c's job), G44, G45 Accepted; P02d-6 | - -`P02d-2` precedes `P02d-3` because the projection reads the definitions the seed -publishes, and because the lesson writer — not the renderer — is the first caller of the -Customization contract. `P02d-4` regenerates the SDK, so the SDK surface that must -compile against non-empty `paths` is decided there. The rendering mode and the entry -behaviour close in `P02d-5`, not `P02d-6`, because the middleware replacement and the -SDK transport are written there and change under a different answer. G32 closes in -`P02d-5` unless an earlier packet writes a seed-host literal outside `SeedData`. - -#### The decision register - -Each row is a question this phase must answer before the packet it blocks starts. The -**Leaning** column preserves the reviewers' original proposal and is **not** a -decision; where the reviews disagreed, it states each position. The **Decision status** -column links the accepted answer for each closed part. The **Vehicle** column -is what this repository's own rules require for the answer to count. A gate whose -vehicle is an amendment is Accepted **before** the code it governs is written, not -alongside it. It closes in the decision pass of the first packet whose code it shapes, -together with any coupled gate that blocks the same packet; where its parts shape -different packets, the **Blocks** cell names the part each packet waits on. Every -premise a row cites is re-verified at that pass rather than trusted. - -| # | Question | Leaning | Vehicle | Blocks | Decision status | -|---|---|---|---|---|---| -| G1 | How does a row whose vehicle is a phase-doc statement, a standard or a catalogue row show that it is Accepted, so that the exit's "no row open" can be checked — and is the answer this phase's or roadmap-wide? | The row stays and gains a closed date and a link to the statement, and each packet's Status row and delivery record list the rows it closed. Roadmap-wide if Phase 02b's phase-doc rows should close the same way | A sentence in [Roadmap § Decision Timing](README.md#decision-timing) if roadmap-wide, or in this register's framing paragraph if local. No ADR | P02d-1 (the first pass to close such a row; it shapes no code) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): G1 | -| G2 | Which aggregate does `Lesson` belong to, and what is its parent: an entity inside `Course`, its own root referencing `Course`, or a minimal `CourseVersion` and default `Module` now? With it: how the satellites are mapped (base type, markers, `deleted_at`), the `sort` invariant and tie-breaker, and what the shape obliges Phase 05 to preserve — course and lesson ids, published slugs, order, organization scope, the inline body | The reviews split. One brings the version spine forward so Phase 05 enriches rather than re-parents; two keep this phase thin and record the preservation obligations, with Phase 05 designing the move. Between the thin shapes: inside `Course` means `ON DELETE CASCADE` and one audit row, but a lesson edit mutates `Course` structurally, which [Domain Model § Education Catalog](../architecture/02-domain-model.md#education-catalog) says a published course never is; its own root means `RESTRICT`, its own `row_version` and its own audit subject | Contract: a dated phase-doc statement; no Accepted ADR holds the `Course` / `CourseVersion` hierarchy, so a new ADR only if the answer needs a cross-root write ([ADR-0042](../decisions/0042-tenant-provisioning-cross-aggregate-transaction.md)). Detail: the Education spec's data model; an interim note in [Domain Model § Learning Content](../architecture/02-domain-model.md#learning-content) where the answer departs from it; the class count in [Database Standards § Foreign keys between tenant-owned tables](../standards/05-database.md#foreign-keys-between-tenant-owned-tables) if `Lesson` cascades | P02d-1 (the lessons foreign-key target, `ON DELETE`, `row_version`, the root mapping and satellite `deleted_at`) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): G2 | -| G3 | Which of `courses` and `lessons` carry a publication state, with which values and transitions, and what does "published" mean to an anonymous reader — publicly readable, or only listed? Which command sets it, which states does the seed write, and may a course with no lessons, or untranslated in an enabled locale, be published? And for any transition or deletion this phase does not ship (unpublishing a course or lesson, deleting either), which phase owns it? | `courses` `draft` / `published`, meaning publicly readable (Phase 05 adds catalog visibility as its own concept); lessons carry a state and show only when both are published; draft → published only; an empty course may be published, since publish validation is Phase 05's. One review leaned "listed in the catalog" | Contract: a new ADR, or a dated phase-doc statement recording why a two-value, one-transition column is not the state machine Decision Timing reserves for a decision record; no Accepted ADR decides publication ([ADR-0018](../decisions/0018-tenant-driven-customization-model.md) reserves the lifecycle to LearnStack). Detail: the `CHECK` ([Database Standards § Constraints](../standards/05-database.md#constraints)), the Education spec's state diagram, the publish row [Audit Coverage Standards](../standards/18-audit-coverage.md) makes MUST | P02d-1 (column presence and value set), P02d-2 (publishing commands and seeded states; transition contract closed in P02d-1) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): commands and seed states; independent lifecycle retained. Anonymous access superseded by [ADR-0050 / dated G3 record](#g3-supersession-2026-10-02); original P02d-1 answer retained as history | -| G4 | Where does a lesson body's binding to the content-type key and `schema_version` it was validated against live — on `lessons` or on each translation row — and where does the body live: its column, type, per-locale placement, and how non-translatable field values are carried? May a constraint cross into the Customization chain? What becomes of Localization Standards' `isLocalized` marker, which nothing implements? | A value pin `(content_type_key, schema_version)` on `lessons`, as Phase 04 plans for `ContentEntry`, with no foreign key; the field document per locale in `lesson_translations`, every locale validated against the one pin, duplicated non-translatable values accepted until Phase 05's lesson items retire them; the marker removed or given its introducing phase | Detail: this document's § Localization schema, the Education spec, [Localization Standards § Pattern A](../standards/08-localization.md#pattern-a--side-translation-table-default-for-content-shaped-entities) in the same diff. Contract: a dated ADR-0043 amendment if a localization keyword enters the schema profile; its own ADR or amendment if a cross-chain foreign key is chosen, as ADR-0044 § 9 did, with Phase 04 and [Database Standards § Migrations](../standards/05-database.md#migrations) in the same diff | P02d-1 (the first `lessons` and `lesson_translations` DDL; a pin added later needs a backfill that guesses between two Active content types) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): G4 | -| G5 | Before Phase 05's `Level` exists, how does a course or lesson carry the level band criterion 1 shows? Does the reference pin a taxonomy revision, how is a band validated on write, and what renders when the resolved revision no longer declares the stored band? | The reviews split: (a) a nullable, non-translatable `(taxonomy_key, band_key)` on `courses`, resolved against the live revision, because the criterion names the catalog; (b) a revision-pinned triple; (c) no column, the band shown through a lesson-page `x-taxonomy` field, with the criterion reworded. No shipped path validates a band value under any of them | Detail: a phase-doc statement, the Education spec, and a Phase 05 inherited row if a reference ships. Contract: a dated ADR-0010 amendment or a new ADR if an Education table takes a foreign key into Customization | P02d-1 (whether and where a column exists), P02d-2 (validation, seeded references), P02d-4 and P02d-6 (the unresolved-band state) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): column; [Accepted — 2026-10-02](#p02d-2-accepted-answers): validation and seeded references; [Accepted — 2026-10-03](#p02d-4-accepted-answers): unresolved public-band response. [Accepted — 2026-10-09](#p02d-6-accepted-answers): renderer state | -| G6 | Locale identity on the content path. (a) What spelling and column type do the satellites' `locale` columns store, and which rule replaces Localization Standards' "Lowercase", which the shipped `LocaleTag` does not follow? (b) Is the `locale` parameter canonicalized before lookup, the membership check and every cache or cursor key, or is a non-canonical spelling refused? (c) What does a non-canonical `/{locale}/` segment get? | (a) `LocaleTag`'s canonical case (`tr-TR`, `zh-Hans`) in `varchar(35)`, as `tenant_locales` stores it — [ADR-0018](../decisions/0018-tenant-driven-customization-model.md)'s 2026-09-04 amendment already makes case variants one locale; (b) well-formedness, then canonicalization, then lookup; (c) a redirect to the canonical segment, decided with G36 | Detail: [Localization Standards § Locale Codes](../standards/08-localization.md#locale-codes) and the Database Standards satellite fence in the same diff. No ADR: ADR-0008 states no casing rule | P02d-1 (a: the first stored rows), P02d-4 (b: validators, cursor binding), P02d-5 (c, with G36) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): (a); [Accepted — 2026-10-03](#p02d-4-accepted-answers): (b); URL-segment redirects (c) remain P02d-5; [Accepted — 2026-10-08](#p02d-5-accepted-answers): (c) URL redirects; prior (a,b) answers retained | -| G7 | Organization write scope. (1) Does a lesson carry its course's organization scope? (2) What forces a satellite's — and a lesson's — mirrored `organization_id` to equal its parent's at insert: writer derivation alone, or that plus a database backstop, and which? (3) May an organization-scoped session `INSERT` a tenant-wide row through the `organization_id IS NULL` arm of `WITH CHECK`, which [ADR-0003](../decisions/0003-tenant-isolation-defense-in-depth.md)'s Amendment 5 and Database Standards say it cannot and which it can at `HEAD`? | (1) Identical scope for a course, its lessons and every translation. (2) Writers derive the child's organization from the authorised parent; the reviews split on the backstop — a stored generated scope column with an organization-inclusive composite key, which structural sweeps can see, or a `BEFORE INSERT` trigger reading the parent under the caller's policies — and one review requires database enforcement. A nullable three-column key is already excluded, because `MATCH SIMPLE` skips the check. (3) Tighten, after the pass confirms no audit writer composes a null-organization row under an announced organization | Contract: one dated ADR-0003 amendment for (2) and (3), with an ADR-0041 erratum beside any sentence the pass finds false when it entered the record; the template replaced in place in [Database Standards](../standards/05-database.md) with its disclosure; forward migrations for `tenant_settings` and `audit_log` if (3) tightens. Detail: [Database Standards § Translation satellite tables](../standards/05-database.md#translation-satellite-tables); a catalogue row with a planted offender if a database mechanism is chosen | P02d-1 (policy SQL, the generated column or trigger, aggregate factories), P02d-2 (child derivation in the commands) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): database controls and factory derivation; [Accepted — 2026-10-02](#p02d-2-accepted-answers): command derivation | -| G8 | Which structural guards does the Education chain register, so its tables cannot regress with the suite green: every foreign key between two tables carrying `tenant_id` includes it; every table carrying `organization_id` has the immutability trigger (and how `audit_log`'s append-only guard counts); the Pattern A rule, which would make [ADR-0008](../decisions/0008-localization-schema.md)'s "the migration linter rejects ad-hoc per-locale columns" true? And how does `fn_organization_id_immutable` — which reads `OLD.id` and is declared only in the Tenancy chain — serve satellites that have no `id`? | Three rows, each with a planted-offender companion; the function replaced by a Tenancy-chain migration that reports `OLD.organization_id` or reads the row key through `to_jsonb(OLD)`, which (as in the audit append-only guard's row comparison) never names a column the table may lack, with the cross-chain dependency recorded under Database Standards § Migrations | Detail: Standards 21 rows Registered and Implemented in the packet; the Database Standards immutability fence and § Migrations; `MigrationRollbackTests`. Contract, only if ADR-0008's sentence is left untrue: an ADR-0041 erratum if it was false when entered, otherwise a dated amendment | P02d-1 (a guard shipped with its first new subject is the only point its companion is written against real tables) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): G8 | -| G9 | Education schema detail: the content slug's character shape, normalization, width and database backstop — including whether a GUID-shaped slug is refused, which G26's shared-slot path needs; whether an Education table holds a foreign key into `tenants`, `organizations` or `tenant_locales`; and each runtime role's privileges on the four tables | `UrlSlug`'s shape with its own width constant and a `ck_<satellite>_slug_format` backstop, since restrictive now is the reversible choice (ASCII-only slugs exclude native-script URLs, a product choice); no foreign key into Tenancy; `learnstack_app` `SELECT, INSERT` plus exactly what G11's commands need, `learnstack_platform` `SELECT` | Detail: Localization Standards § Pattern A for the shape; the Database Standards satellite fence and [§ GRANT matrix](../standards/05-database.md#grant-matrix); § Migrations only if a cross-chain key is chosen | P02d-1 (the creating migration writes the `CHECK` and the grants; the grants couple with G11) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): G9 | -| G10 | What is the catalog's default order and tie-breaker, and what is the cursor it mints: its payload and version; what it binds (tenant, organization, locale, sort, filters, endpoint); its integrity (none, a MAC with a key version, or server-side state); its direction; what happens when a row changes between pages; which list parameters the endpoint binds; where it is decoded; whether the codec is this endpoint's or the kernel's; and which cursor classes answer `400`? | The reviews split between a keyless versioned payload with a binding fingerprint, decoded at binding so a garbage cursor opens no transaction, and an HMAC-authenticated cursor with key rotation. Both keep tenant and organization out of the cursor, and bind `CursorPaginationRequest` rather than `ListRequest`, whose `q` is Phase 04's search | Contract: a phase-doc statement if the codec is endpoint-local and keyless; a new ADR if it becomes a kernel rule later lists follow, or a MAC adds a secret and a rotation posture. Detail: [API Standards § Pagination](../standards/04-api-design.md#pagination), which drops "Nothing validates its *shape* yet"; Standards 21 rows | P02d-1 (the order part: an ordering column, publication timestamp or collation), P02d-4 (the codec part) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): order; [Accepted — 2026-10-03](#p02d-4-accepted-answers): resource-local cursor codec | -| G11 | The write surface the seed needs. Which Education commands write courses, lessons and their translations; is a translation written separately from create; is publishing its own command; which command reports a slug collision as `business_rule_violation` rather than a raw unique violation, and does Localization Standards' "from the publish command" still hold? What shape do the Tenancy commands raising `tenancy.locale.write` and `tenancy.setting.write` take? How are the non-baseline writes classified, and how does a re-run converge? | Create course, write course translation, add lesson, write lesson translation, publish course (MUST); one locale command over `Tenant.AddLocale` and `SetDefaultLocale`; a create-or-update setting command keyed on context scope and key; ordering taxonomy → content type → course → lessons; idempotent by conflict, with an ownership check per act and a second-run test. None has a route | Contract: a phase-doc statement plus the Education spec (README write sequence, `audit.md`, `permissions.md` as a forward declaration on [the Tenancy precedent](../modules/tenancy/permissions.md)). Detail: catalogue sources, the Tenancy `audit.md` and `permissions.md`, Localization Standards § Pattern A if the collision sentence changes. An ADR only if a handler must write two roots | P02d-2 (commands, handlers, catalogue sources, seeder acts) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): commands, failures, audit classifications and convergence | -| G12 | Through which `Customization.Application.Contracts` surface does an Education write obtain the schema a body is validated against — exact `(key, schema_version)` including Deprecated revisions, or a key that binds the Active one — and is it an interface or a MediatR query, classified how? Which revisions may a writer bind, and what refusal answers an absent, cross-tenant or ineligible one? On the read side: what the cache keys on, whether the lesson response carries the binding or resolved field descriptors, and what the API and the page show when a binding cannot be resolved | One exact-revision query, Deprecated included, never falling back to Active; only Active revisions bindable for new writes, since a Draft's body can still change; absent and cross-tenant refused indistinguishably as `validation_failed` naming the binding; resolved descriptors in the response; an unresolvable binding shows a bounded placeholder with a warning log, never a `500` and never another revision's fields ([ADR-0013](../decisions/0013-page-block-schema-versioning.md)'s placeholder rule) | Detail: the Customization spec's contract and § Primary read flow, the Education spec's invariants, a phase-doc statement. No ADR: ADR-0010 settles the mechanism. A dated ADR-0013 amendment only if the unresolvable outcome departs from the placeholder rule | P02d-2 (the contract and write eligibility: the lesson writer is its first caller), P02d-3 (the cache key), P02d-4 (descriptors, the unresolvable outcome), P02d-6 (the page state) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): contract and write eligibility. [Accepted — 2026-10-02](#p02d-3-decision-package-2026-10-02): cache key; [Accepted — 2026-10-03](#p02d-4-accepted-answers): public response; [Accepted — 2026-10-09](#p02d-6-accepted-answers): page state | -| G13 | May an Education translation be written for a locale absent from, or disabled in, `tenant_locales`, and how is membership checked across the module boundary? Does a read resolve under a disabled locale? What does a tenant with no locale rows serve — [Localization § Tenant Locale Configuration](../architecture/12-localization.md#tenant-locale-configuration) promises platform `en`, and nothing implements it? Does a platform registry bound the enabled set, as Localization Standards names one in a namespace that does not exist? What happens to translations when `RemoveLocale` runs? | A Tenancy application contract checks membership on write; a read resolves only an enabled locale, checked once per request; no cross-chain foreign key; no platform registry in this phase; a tenant with no locale rows serves nothing until it has one | Contract: a phase-doc statement over ADR-0010's application-contract mechanism. Detail: the Tenancy and Education specs; Localization architecture and Localization Standards § Locale Model reconciled in the same diff; Database Standards § Migrations only if a key is chosen | P02d-2 (the translation command's check and the locale command the seed uses; the read half is written to the same answer in P02d-4) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): write eligibility, no platform registry and no implicit no-row locale; public reader implementation remains P02d-4 | -| G14 | Seed inventory. At what scope is each seeded row class written — courses, lessons, translations, branding settings — and from what seeder context, given that `SeedTenantContext` requires an organization? Where do the rows the criteria need live — a sibling-organization course, an organization-scoped course on the tenant host, a `(locale, slug)` held in both tenants, draft and wrong-course rows, more courses than one catalog page, a disabled locale holding translations — `make seed` or test-owned data? Which key the yoga taxonomy uses, which tenant is bilingual, what state do the built-in `card` / `plain` keep, which record holds it all, and how do the Packet 7 fixture's raw settings rows coexist with seeded ones? | English content tenant-wide; the yoga studio gets a tenant-wide, a Studio One and a Studio Two course; a seed context that announces no organization; branding tenant-wide; rows in the seed with `SeedData` as the record; built-ins stay Active and are never selected implicitly; expectations recomputed as enumerated sets. An English organization-scoped row is still needed for the tenant-host criterion, seeded or test-owned — the demo database's contents are the owner's preference | Detail: a phase-doc statement, the `SeedData` remarks, the `seed-tenant` skill, the writers delivery record. No ADR: [Security Standards § Forbidden](../standards/11-security.md#forbidden) already makes scope come from context | P02d-2 (seeder steps, the seed-context constructor, `SeedData`, `SeederTests`; moving placement later rewrites the seed and every request-level case) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): inventory, ownership and test-owned controls | -| G15 | `SeedRunner` calls `IUnitOfWork.SetTenantContextAsync` on its own transaction, and neither [ADR-0040](../decisions/0040-ambient-unit-of-work.md)'s closed setter set nor [Security Standards § The out-of-band setters](../standards/11-security.md#the-out-of-band-setters) lists it. Is that method's caller set mechanically closed, and is the seeder's call reconciled by routing its ownership check through `ISender`, or by admitting the seeder? | Route the ownership check through `ISender`, and add a source scan that admits `TransactionBehavior` (and Phase 02b's transport) with a planted offender | Contract: a dated ADR-0040 amendment plus a setters-table row only if the seeder is admitted. Detail: a Standards 21 source-scan row with its companion | P02d-2 (the Education seed acts reach the ownership check's refusal arm today) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): contextual verification and Registered caller fence | -| G16 | The branding token contract. (a) Where does the settings key registry live, what does a descriptor carry, and does `tenancy.setting.write` refuse keys outside it? (b) Which branding keys exist — per-token keys or one theme document — and is a layout option among them? (c) What value does each accept, fonts and logos included, and what happens to a stored value that fails it? (d) Does a failed contrast check refuse the write or record a warning — [Accessibility Standards § Color and Contrast](../standards/16-accessibility.md#color-and-contrast) says a Studio warning? (e) What does an organization-scoped branding row do here — refused, ignored or applied? (f) Which tokens may leave an anonymous response? (g) Does `tenancy.white_label_branding` — which reads true under `NullEntitlementProvider`, whose projection grants every registered feature, falls back to its catalog default `false` from a projection that omits it, and which the Hub's Starter plan sets false — govern applying theme tokens or only removing LearnStack attribution? | (a) a registry beside `FeatureKeys` and `LimitKeys`, as `Tenant.SetFeatureFlag` already refuses unregistered keys; (b) per-token keys, at most one enumerated layout option or none; (c) `#rrggbb` colours, one font key from a closed self-hosted set, no remote logo; (d) refuse; (e) tenant-wide only, keeping Phase 06's override and ADR-0017's `OrganizationBranding` true; (f) a closed projection of publicly readable keys; (g) not gated — tokens are baseline presentation, and the key's meaning is agreed with the Hub. That token values are tenant settings is settled by [Frontend Architecture Standards § Tenant Branding](../standards/07-frontend-architecture.md#tenant-branding) | Contract: a phase-doc statement plus Frontend Architecture Standards § Tenant Branding; a new ADR if the registry becomes an admission rule for every `tenant_settings` key; a dated ADR-0017 amendment if (e) applies overrides; Accessibility Standards if (d) replaces the warning. Detail: the Tenancy spec and permission matrix, [Frontend Architecture § Theming](../architecture/14-frontend-architecture.md#theming), the `FeatureKeys` descriptor with a matching note in the Hub repository for (g) | P02d-2 (a–e: validation and the seeded keys, which Phase 06's editor later edits), P02d-4 (f, g: the anonymous projection the OpenAPI baseline freezes), P02d-6 (g: whether rendering consults the flag) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): (a–e); [Accepted — 2026-10-03](#p02d-4-accepted-answers): public projection and attribution (f/g); [Accepted — 2026-10-09](#p02d-6-accepted-answers): injection and attribution (g) | -| G17 | Does `TenantSetting.Value` carry `[PiiSensitive]`? [Phase 03](phase-03-identity-admin.md) sequences the decision before the first command writing `tenant_settings`, and this phase ships that command | Not marked, provided `tenancy.setting.write` admits only G16's closed key set, so the answer cannot stretch to keys a tenant invents; modelling a sensitive part as its own property stays open to Phase 03 | Contract: a dated phase-doc statement, reflected in `TenantSetting.cs`, the Tenancy spec and `audit.md`. Whole-value redaction of `jsonb` is settled by [ADR-0044](../decisions/0044-audit-write-path.md) Amendment 4 § 1 | P02d-2 (the first MUST-class settings audit row is written by the seed, and rows cannot be redacted retroactively); closes with G16 (a) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): generic whole-value PII redaction before the writer | -| G18 | How is a tenant content type presented? `json_schema` is `jsonb`, which keeps no key order, and the schema profile collects only `x-renderer`, `x-taxonomy` and `x-language`. How are field order, a label per enabled locale and a composite's field roles carried; which registered composite draws a lesson for each seeded type; which primitives does this phase implement, and does `markdown` render; how do types with no primitive row (`integer`, `number`, `boolean`, enums) map; may a rendered type declare a field outside the subset; and is a presentation entry naming a missing property refused at save? | A LearnStack extension — `x-order` and `x-label`, or one ordered `x-fields` list — carrying Pattern B labels, resolved at write like `x-taxonomy`; one composite already in both registries; the reviews split on the subset — `text`, `list` and `link`, with `markdown` without raw HTML, or a placeholder until Phase 05's sanitiser; the seed uses only the subset | Contract: a dated ADR-0043 amendment for a keyword or a save-time refusal; a dated ADR-0018 amendment for a presentation column; a phase-doc statement for `title` plus `required`, which cannot carry two locales. Detail: [Tenant Customization Model § 2](../architecture/32-tenant-customization-model.md) and § 8.1, the Customization spec, the profile's extension and reference-graph skip lists, `composites.ts` | P02d-2 (the seed publishes both content types as `schema_version` 1 with their renderer keys and field kinds; a later answer needs successor revisions) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): ADR-0051 profile and first-render subset. Component placement/fallback remains G41 | -| G19 | URL and markup policy for tenant-authored values on an anonymous page: which schemes (`https` only, or `http` too), credentials and `target`, which media origins, whether the rule is enforced on write — in the Education command, or as a validation gate Phase 04's entries share — whether the public API filters too, and whether URLs inside markdown fall under it. The write-time check constrains structure, not schemes: `format: uri` admits `javascript:` and `data:` | The reviews split on `http`; all refuse `javascript:`, dangerous `data:` and credentials; checked on write by a LearnStack rule and again on render; no third-party media in the seed | Detail: one home for the scheme list — [Security Standards § XSS & Output Encoding](../standards/11-security.md#xss--output-encoding) or [Frontend Architecture Standards § Security](../standards/07-frontend-architecture.md#security), not both; the Education spec's write rules; Tenant Customization Model § 8.1 if checked on write. Contract: a dated ADR-0043 amendment if it becomes a shared validation gate | P02d-2 (the lesson command's validation and the seed values; the render-time check reuses the answer) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): no active sink in the seeded text profile; future URL/markup contracts precede Phase 04/05 sinks | -| G20 | What mechanically backs "no production code branches on which tenant it serves"? The shipped domain-term scan strips literals and exempts seed data. (a) The mechanism and its literal source; (b) its subjects, matching and the platform built-ins; (c) its exemptions, including development hosts in frontend or infrastructure configuration; (d) whether a ban on production references to `LearnStack.Tools.Seeder` and a behavioural same-code, different-data test accompany it | A Standards 21 sibling row scanning production backend and `frontend/` sources, comments stripped, for exact identity literals read from `SeedData` (slugs, ids, hosts, display names, customization keys), built-ins excluded, with planted offenders; plus the behavioural test. The exemption policy is the owner's judgement | Detail: a Standards 21 row Registered in the first pass that uses it and Implemented before exit; a phase-doc statement in § Genericity proof. No ADR | P02d-2 (a: every seed literal lives where the source reads it), P02d-5 (c: the first host outside `SeedData`), P02d-6 (b: frontend subjects), P02d-7 (Implemented and required) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): (a) SeedData literal source and Registered guard. [Accepted — 2026-10-08](#p02d-5-accepted-answers): (c) exemptions; [Accepted — 2026-10-09](#p02d-6-accepted-answers): (b) frontend subjects; implementation and behavioral proof remain P7; [Accepted — 2026-10-11](#p02d-7-decision-package-2026-10-10): matching, canonical built-ins, Seeder-reference fence and behavioral ownership; Step 2 implements the required fences and schema-replacement companion | -| G21 | Does the anonymous public path set any cookie — the [Frontend Architecture Standards § Tenant Resolution](../standards/07-frontend-architecture.md#tenant-resolution) flowchart sets them — and may a public page load any cross-origin subresource, such as the CDN-hosted logo and font assets Frontend Architecture describes? | No cookies, since the locale is already in the path and a locale-less request redirects ([Localization Standards § URL Strategy](../standards/08-localization.md#url-strategy)); same-origin subresources only; both asserted by a check. Whether tenant branding may point visitors' browsers at third-party hosts is a data-protection choice for the owner | Detail: a phase-doc statement; the Standards 07 flowchart and Frontend Architecture § Theming reconciled in the deciding pass | P02d-2 (subresources, if G16 admits a URL-valued token), P02d-5 (cookies: the middleware replacement is the first code that could set one) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): subresources. Cookies remain open for P02d-5; [Accepted — 2026-10-08](#p02d-5-accepted-answers): cookies; prior subresource answer retained | -| G22 | How does the customization definition projection load and stay correct? In the request's ambient transaction, or as a ninth out-of-band tenant-context setter (ADR-0040's set is closed at eight)? In what order are the generation and the rows read; what does an absent generation row mean; how is a cache filled inside a transaction that bumped and rolled back kept unreachable, when the bump is an upsert increment that can reissue a number; what does an absent definition set return; which families are registered, and how does the adapter's exact-tuple `cache.name` mapping match generation-embedded names; what do the TTLs bound; and is the contract batched so a public read issues a bounded number of statements? | Load in the ambient transaction; read the generation first, then the rows; fill only from non-bumping transactions; treat cache faults as misses; restate the module's cache-hit budget; a batched contract, with statement-count assertions cold and warm | Contract: the Customization spec § Primary read flow and a [Tenant Customization Model § 8.2](../architecture/32-tenant-customization-model.md#82-cache-strategy) statement on how a request learns the generation; a dated ADR-0040 amendment and a setters row only if the loader is out-of-band. Detail: the [Infrastructure Stack Standards](../standards/20-infrastructure-stack.md) cache table, the `cache.name` mapping, the Observability Standards metrics family list | P02d-3 | [Accepted — 2026-10-02](#p02d-3-decision-package-2026-10-02) | -| G23 | The typed settings accessor and its freshness. With no declared settings-invalidation event and the seed writing from its own process, what bounds staleness: a TTL with a stated bound, a writer-coupled Tenancy settings generation counter, or no settings cache here? What are the accessor's name and glossary headword; how is a cached read keyed so tenant-wide and organization rows never cross organizations — a settings read depends on `app.organization_id` today, and the policy's tenant-scope read gains a carrier in Phase 03; and does its loader run in the ambient transaction? | The reviews split on freshness — a TTL bound, a counter, or no cache. For keys: tenant-wide rows loaded with an explicit `organization_id IS NULL` predicate under `CacheKey.ForTenant`, each organization's overrides under `CacheKey.ForOrganization`, merged in memory; an ambient loader. The documented tenant-only key is rejected, because it would serve one organization's overrides to another | Detail: if settings are cached, the Infrastructure Stack Standards cheat-sheet rows and `cache.name` mapping; the Tenancy spec's event catalogue and budget; a glossary headword. Contract only for a counter (the Tenancy spec, Database Standards § Table classes and § GRANT matrix) or an out-of-band loader (an ADR-0040 amendment) | P02d-2 (a counter is bumped inside the setting command's transaction), P02d-3 (name, keys, loader) | [Accepted — 2026-10-02](#p02d-2-accepted-answers): no settings cache in P02d-2/3. [Accepted — 2026-10-02](#p02d-3-decision-package-2026-10-02): typed ambient accessor/scoped merge | -| G24 | Display fallback. Which document owns the chain — [Localization § Fallback Rules](../architecture/12-localization.md#fallback-rules) or [Localization Standards § Locale Model](../standards/08-localization.md#locale-model), which state different chains, while the shipped `LocalizedText.Resolve` narrows one subtag at a time and ends at the first authored value? What is the terminal state of a nullable Pattern A field and of a Pattern B label? Does a response say which locale a fallback value resolved in, so the page can mark its language (WCAG 3.1.2)? | Localization architecture owns the chain and Localization Standards links it, both recording the shipped narrowing and the first-authored terminal for labels; a nullable Pattern A field renders absent; each fallback-capable field reports its resolved locale | Detail: Localization Standards § Locale Model linking its owner, reconciled with `LocalizedText` in the same diff; the Customization contract's signature; the response schema under G26. No ADR | P02d-3 (the first caller that passes a fallback chain), P02d-4 (response fields) | [Accepted — 2026-10-02](#p02d-3-decision-package-2026-10-02): internal fallback; [Accepted — 2026-10-03](#p02d-4-accepted-answers): public response locale fields; renderer language attributes remain P02d-6 | -| G25 | Site data and the page set. How does the renderer get the per-host data none of the Education reads returns — enabled and default locales, branding tokens, taxonomy display values, content-type field lists: fields embedded in the course reads (which cannot supply a default locale before a locale is known), a separate `[PublicSurface]` read resolved from the effective host, or the edge host lookup [Frontend Architecture Standards § Tenant Resolution](../standards/07-frontend-architecture.md#tenant-resolution) and [Infrastructure Stack Standards § Host → Tenant Resolution](../standards/20-infrastructure-stack.md#host--tenant-resolution) prescribe today, which must then state the effective host over the hop? Does the frontend ever hold a tenant or organization id? And which `(public)` pages ship — catalog, course with ordered lesson links and lesson, or two pages with bounded lesson links in the catalog response? | One `[PublicSurface]` site-data read with no host parameter, returning a closed projection and no ids, and three pages, which gives the course-detail read a consumer; one review keeps two pages with an explicit catalog outline. The first two options change what two Active standards prescribe | Contract: a phase-doc statement in § Read API and § Public renderer; for the first two options, edits to the two standards named, with an ADR if the pass judges the change non-trivial (no ADR carries the edge-lookup rule). Detail: the API Standards § Public surface rows; the Frontend Architecture sketch, sequence diagram and cache rows; the Localization architecture's edge locale sentence; the glossary; Phase 06 § What Phase 02d already shipped; Phase 05's inherited row if the course-detail read changes | P02d-4 (the endpoint set and DTOs the OpenAPI baseline freezes; a two-page answer changes the catalog response) | [Accepted — 2026-10-03](#p02d-4-accepted-answers): bootstrap and page set; page implementation remains P02d-6 | -| G26 | The v1 public read contract. The path shape beside Phase 05's authoring `/courses/{id}` — a shared slot, a distinct public prefix, or `/courses/by-slug/{slug}`; each response as an allow-list and what it never carries; the embedded lesson list's fields, order and bound, and whether an empty list is valid; per-locale alternates; how enums and envelopes stay additive; and which Problem Details responses each operation documents, given that no non-idempotent operation documents any today and a baseline of `200`s cannot see a status change | Fields limited to what the pages render; object envelopes, extensible enums, a deny-list contract test (`tenantId`, `organizationId`, `createdBy`, `updatedBy`, `deletedAt`, `rowVersion`, `slugKey`); the embedded list carries title, slug and order under a cap; `alternates` for enabled, translated locales; one shared transformer declaring each operation's statuses as `application/problem+json`. No review settled the path | Contract: a phase-doc statement recorded before the breaking-change check stores its baseline. Detail: the OpenAPI snapshot; [API Standards § URL Structure](../standards/04-api-design.md#url-structure) for a prefix class, § Pagination for an embedded list, § OpenAPI; the gateway's public-band row. [ADR-0024](../decisions/0024-api-versioning-policy.md) settles that later additions are non-breaking | P02d-1 (whether the slug grammar must refuse GUID shapes, with G9), P02d-4 (route templates, records, snapshot) | [Accepted — 2026-09-14](#p02d-1-accepted-answers): slug grammar; [Accepted — 2026-10-03](#p02d-4-accepted-answers): route and response contracts | -| G27 | The cache posture of public reads. What directive do anonymous responses carry — the `200`s, the Problem Details `400`s and `404`s, the tenancy edge's unmapped-host `404` — what freshness do a newly published or unpublished course and a not-found have, and do anonymous reads emit an `ETag` and honour `If-None-Match`? [API Standards § Optimistic Concurrency](../standards/04-api-design.md#optimistic-concurrency) says mutable resources expose an `ETag`, and [ADR-0039](../decisions/0039-optimistic-concurrency-token.md) fixes one derivation, which a composite read cannot use without publishing `row_version` | An explicit `Cache-Control: no-store`, asserted by a test, and no `ETag` on anonymous reads — a response without explicit freshness may be cached heuristically by a shared cache. One review proposed no directive, stated | Contract: a phase-doc statement. Detail: API Standards — the directive, and a § Optimistic Concurrency sentence on anonymous read contracts, owed under either answer. A dated ADR-0039 amendment if a body-hash validator ships; [Performance Standards § Caching](../standards/15-performance.md#caching) if the answer caches | P02d-4 (the header-setting code and the headers the snapshot documents) | [Accepted — 2026-10-03](#p02d-4-accepted-answers): no-store without response validators | -| G28 | Public-surface controls. (a) What audit class do `[PublicSurface]` requests register, and does a rule make `Off` the only permitted one? (b) `GET` only, or `GET` and `HEAD`, and what does the catalogue's permitted-methods leg compare a row against? (c) What mechanically stops a marked request from writing — a `READ ONLY` unit of work, a structural scan, or both? (d) What control beyond review keeps a controller dispatching only through `ISender` — a controller taking a module `DbContext` fails loudly, SQL on `IUnitOfWork.Connection` reads zero rows, and code that announces the tenant itself reads real rows? | (a) `Off` for every marked type — a SHOULD or MAY class would make every anonymous `GET` a best-effort write a caller controls — with a sibling rule and companion; (b) one review `GET` only, one the standard's `GET` / `HEAD`; (c) a `READ ONLY` transaction for marked requests, which three shipped setters already open before announcing, and which refuses any in-transaction MUST write, so it is checked against (a); (d) a type-reference rule over controller bodies with a planted offender | Detail: the API Standards § Public surface rows; Standards 21 rows and companions, including the two legs of `PublicSurface_Marker_Set_Is_Enumerated` not yet implemented; an [Error Handling Standards § Controller Mapping](../standards/09-error-handling.md#controller-mapping--resultt--iactionresult) sentence for (d). Contract: a dated ADR-0040 amendment if the unit of work gains a read-only mode | P02d-4 (the first marked query's registration, method attributes and handler; if P02d-3 writes on the read path, (c) closes there) | [Accepted — 2026-10-03](#p02d-4-accepted-answers): Off, GET/HEAD, mandatory dispatch and read-only controls | -| G29 | Which rows do the anonymous reads serve, and what does every hidden row answer? The rule covers course state, lesson state (G3), the lesson's membership in the course its URL names — lesson slugs are unique per tenant, so a lesson resolves without its course segment unless the read checks — and soft deletion. Does every hidden cause (draft, deleted, wrong course, untranslated, other tenant, sibling organization, nonexistent) answer one `not_found` body with no per-cause detail, compared with `instance` and `correlationId` masked? | One eligibility rule used by every read; a lesson resolves only under its eligible parent, only when it belongs to it, only in the requested locale; lists show only eligible entries; deleted rows excluded now; one masked-equal body | Contract: a phase-doc statement whose single record is the Education spec. Detail: the failure constant. Settled and linked: a cross-tenant row is a `404` ([Security Standards § Error Messages](../standards/11-security.md#error-messages)), and an organization-scoped row is served only on its own organization's host ([Localization § Slugs and URLs](../architecture/12-localization.md#slugs-and-urls)) | P02d-4 (handlers, the failure constant, documented `404`s); the fixture rows close with G14 in P02d-2 if they live in the seed | [Accepted — 2026-10-03](#p02d-4-accepted-answers): explicit eligible reads and uniform masking | -| G30 | The locale error matrix and transport. On each read, what answers an empty, repeated, malformed, over-length, non-canonical, not-enabled or enabled-but-untranslated locale? Does a not-enabled locale answer the Active `unsupported_locale` `400` or the not-found body? Is `X-Locale`, which [Frontend Architecture Standards § Locale Resolution](../standards/07-frontend-architecture.md#locale-resolution) still names as the API carrier, withdrawn, so that locale reaches the API only as the query parameter? | Missing or malformed → `400` `validation_failed` naming `locale`; untranslated → an empty catalog page; the query parameter only. The reviews split on not-enabled — not-found, amending the Error Handling row, or the Active `400`; a uniform answer after the enabled check hides pre-launch rows under either | Detail: a phase-doc statement; the [Error Handling Standards](../standards/09-error-handling.md) table only if not-found; Standards 07 § Locale Resolution; the Frontend Architecture SDK sketch; the API Standards § Pagination example gains `locale` | P02d-4 (validators, OpenAPI parameters and responses), P02d-5 (the server SDK's header set) | [Accepted — 2026-10-03](#p02d-4-accepted-answers): query/error matrix; trusted server header transport remains P02d-5; [Accepted — 2026-10-08](#p02d-5-accepted-answers): header transport; prior API query-locale answer retained | -| G31 | Contract checks and the SDK surface. The committed OpenAPI snapshot's path, and how the contract suite proves it equals the served document; how the base copy is read; how the first run behaves; which `oasdiff` version and fail level, and which ADR-0024 rows that level detects (a tightened validator or a changed status may be invisible to any diff); what is uploaded on failure. The drift gate's source — the committed snapshot through `LEARNSTACK_OPENAPI`, or a running API — and its job. Whether an activated deferred job keeps its `if: vars.ENABLE_*` condition, given that GitHub treats a skipped required job as passing, or loses it as the integration job's did. And what the SDK surface becomes when regeneration makes `paths` non-empty: a hand-written transport over `paths` or a typed client library, the fate of `createClientSdk`, and whether the package root keeps re-exporting the server entry | A committed snapshot the contract suite asserts equal, diffed against the base ref's copy with `oasdiff` pinned; drift generated from the snapshot in the required `frontend` job; the condition removed on activation; a thin hand-written transport, and no root re-export of the server entry | Detail: [Testing Standards § API Contract Tests](../standards/06-testing.md#api-contract-tests), the API Standards § OpenAPI links, `ci.yml`, [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) (its activation procedure follows the answer), [Frontend Architecture Standards § SDK](../standards/07-frontend-architecture.md#sdk); a package pin with its licence verdict if a client library is chosen | P02d-4 (the first operation, its snapshot and assertion, the drift gate, and the regenerated types the factories must compile against) | [Accepted — 2026-10-03](#p02d-4-accepted-answers): snapshot, SDK, diff/drift and approved required-check activation | -| G32 | **The development-transport part of [Phase 02b](phase-02b-events-auth.md#the-decision-register)'s G12.** Which development hostnames and transport serve the two seed tenants — keep `*.learnstack.local`, with a hosts-file step and local TLS with a trust step, or move the seed hosts under `*.localhost`? What does a reviewer do between a clean checkout and both sites, and which carriers move, including host rows already on warm databases, where the host is the primary key and the seeder removes no mapping? | `*.localhost` over HTTP, provided the pass verifies in each browser the team uses and in CI's Chrome that both hosts resolve with no hosts entry and that a `Secure` cookie set on them is stored and returned; otherwise `*.learnstack.local` with local TLS and a named trust step. Tenants are never told apart by port: the effective host strips it | Detail: a dated phase-doc statement in [§ Host-based tenant resolution, end to end](#host-based-tenant-resolution-end-to-end), with `SeedData`, `scripts/seed.sh`, the README Quickstart, the `seed-tenant` and `local-dev-setup` skills and `apps/web`'s dev script and Next configuration in the same packet; Infrastructure Standards only if a TLS proxy publishes a port. No ADR | P02d-5 (the development transport, and the hop configuration a TLS proxy would change), or the first earlier packet that writes a seed-host literal outside `SeedData` | [Accepted — 2026-10-08](#p02d-5-accepted-answers): local hosts and TLS | -| G33 | The server-rendering topology and its evidence. Where do Next.js and the API run relative to each other — the workstation loopback, containers, gated APISIX; which networks are trusted; how does one hop secret reach both processes; what is the server-only API origin — and the same for the CI job that renders the pages? What evidence discharges ADR-0036's "Phase 02d's browser test" and its matrix rows "a direct socket bypassing the hop" and "the Phase 02d anonymous two-host browser render", given that Testing Standards gate this phase on a human? And ADR-0036 § Consequences says the root refuses to start outside Development when the secret list is empty or short, while the shipped rule, in every mode, refuses a half-configured hop, a network entry that is not CIDR and a blank secret or one under 32 characters (characters, not bytes), and admits both lists empty: is that recorded or restored, and is non-development hop configuration this phase's or Phase 11's? | Both processes on the loopback, networks `127.0.0.1/32` and `::1/128`, one generated secret from a single source and never under `NEXT_PUBLIC_`, with networks and secrets arriving together (committing networks without secrets breaks every Development-environment fixture); the API called directly; a per-run secret in CI. Evidence: request-level hop tests as `learnstack_app` — no `X-Tenant-Id`, a non-hop peer, a wrong secret, a repeated header — beside the human walkthrough, with one review adding an automated browser smoke. Record the shipped startup rule; non-development hop configuration is Phase 11's | Contract: one dated [ADR-0036](../decisions/0036-tenant-resolution-trusted-inputs.md) amendment if the evidence departs from the ADR's words, recording the startup rule, and carrying G34 if G34 changes the key or budget. Detail: `.env.example`, `apps/web/.env.local.example`, `appsettings.Development.json` or the demo recipe; a Standards 21 row for the hop runtime test; a Testing Standards § End-to-End Tests sentence only if ownership moves; a Phase 11 scope row | P02d-5 (the hop configuration and the fixture shape — in-process test hosts have no socket peer), P02d-7 (the CI part) | [Accepted — 2026-10-08](#p02d-5-accepted-answers): local topology, shared source and ingress; [Accepted — 2026-10-11](#p02d-7-decision-package-2026-10-10): shared CI lifecycle/topology; ADR-0056 measurement Accepted on the same date; Step 3 local proof passes; Step 4 owns real CI receipts | -| G34 | How does the pre-classification anonymous limiter treat a request arriving over the authenticated trusted hop? Every server-rendered call reaches the API from the renderer's peer, so every visitor of both tenants shares one partition, and one client sending random `Host` values through the renderer can starve both sites. The partition key, the budget and how the renderer derives any visitor identity it states — while unknown-host floods stay bounded before database work, and a direct peer is still limited per peer | The reviews differ: a visitor address stated over the hop, in a dedicated single-valued header or through `X-Forwarded-For` with the peer captured first, as ADR-0036 anticipates; a separate hop budget with limiting in the renderer; or an explicitly sized shared quota. A per-host ceiling as the only backstop multiplies under a random-`Host` flood | Contract: a dated ADR-0036 amendment if the hop changes the key or the budget, stating the new input's trust rule and whether it may be logged or audited; otherwise a phase-doc statement. Detail: API Standards § Request and Response Limits, [Security Standards § Rate Limiting](../standards/11-security.md#rate-limiting), the catalogue's per-peer rule. `P02b-0` re-verifies Phase 02b's G14 against the answer | P02d-5 | [Accepted — 2026-10-08](#p02d-5-accepted-answers): authenticated visitor and peer budgets | -| G35 | The server SDK transport. Its options — visitor host, locale, an optional assertion, never a tenant id as selector; where the host comes from; how the API origin is configured; the server-only guard, timeouts and cancellation; and whether it forwards W3C `traceparent`. With it: which parts of [Observability Standards § Frontend Observability](../standards/10-observability.md#frontend-observability) — Next.js error capture, web vitals — ship here, and which phase owns the rest, since no phase names them | Host and locale plus an optional assertion; hop headers and origin from server configuration, never from request input; a `server-only` guard; Problem Details mapped to the `AppError` union [Error Handling Standards](../standards/09-error-handling.md) already fixes; `traceparent` forwarded; Next.js error capture and web vitals assigned to Phase 11, whose § Observability lists error tracking | Detail: Frontend Architecture Standards § SDK and the Frontend Architecture SDK sketch; a pin and licence verdict if a guard package is added; an exclusion row naming frontend observability's owner, with an Observability Standards sentence | P02d-5 (the transport's headers and configuration read); the ownership half closes by exit, because a deferral names its phase | [Accepted — 2026-10-08](#p02d-5-accepted-answers): configured caller, deadlines and observability owners | -| G36 | The edge middleware and entry behaviour. Does the middleware resolve anything (with G25)? What does it carry inward, and under which header name — the Frontend Architecture sketch reuses `x-learnstack-host`, the hop header's own name? Which inbound internal headers are removed or overwritten, including `x-organization-id` when resolution has none — a deny-strip or an allowlist rebuild? What does the matcher exclude? What do `/` and a locale-less path answer, with which status, target and default-locale source; what do a disabled, malformed or non-canonical locale segment (G6 c), a platform host and an unknown host answer; does this run in middleware or the route tree, and may an i18n library own the middleware? Does this phase build the locale-less redirect [Localization Standards § URL Strategy](../standards/08-localization.md#url-strategy) requires, or keep the standards index's i18n-runtime carve-out while Phase 06 claims redirect handling? | Normalise the host; strip every client-supplied `x-tenant-id`, `x-organization-id`, `x-locale` and `x-learnstack-*`; drop the scaffold's `503` guard and TODOs; `/` redirects to the tenant's default locale; a disabled locale is a `404` before any content call; a platform or unknown host gets a `404` with no platform text; the redirect built minimally here, with Phase 06's rows reworded to "deepens" | Detail: a phase-doc statement; the Standards 07 § Tenant Resolution flowchart and the Frontend Architecture middleware sketch; Phase 06's rows in the same diff; if less is built, a dated narrowing of the standards index row for Localization Standards naming the owning phase | P02d-5 (the middleware replacement rewrites the scaffold's locale fallback, so every placement answer changes it first) | [Accepted — 2026-10-08](#p02d-5-accepted-answers): membership-first entry and redirects | -| G37 | How do tenant-varying `(public)` routes render, and which Next.js caches may hold tenant data — the full-route cache, the fetch data cache, `unstable_cache`, `generateStaticParams` — so one host's page is never served on the other? A public URL carries no tenant, and both tenants send the same request line over the hop, so a path-keyed cache leaks. What freshness does a page have after a customization or content write? | All three reviews: dynamic rendering with uncached SDK fetches — no `revalidate`, no `generateStaticParams`, no `unstable_cache` — relying on the API's generation-keyed cache; no ISR here | Detail: [Frontend Architecture Standards § Public Site Renderer](../standards/07-frontend-architecture.md#public-site-renderer), which prescribes `revalidate` today, and [Frontend Architecture § Rendering Strategies](../architecture/14-frontend-architecture.md#rendering-strategies), rewritten with the `add-frontend-route` skill; [Performance Standards § Caching](../standards/15-performance.md#caching) if the answer caches; an ADR if the pass judges the Standards 07 change non-trivial | P02d-5 (one mechanism: a host-bearing rewrite target is middleware code and fetch cache options are transport code, both written before the renderer) | [Accepted — 2026-10-08](#p02d-5-accepted-answers): dynamic no-store renderer policy | -| G38 | The frontend test set. (a) Which predicates of the middleware and the server SDK does Vitest cover, and in which packages — `pnpm -r test` runs only packages with a test script, which `packages/sdk` lacks? (b) How are async Server Component pages and field components covered below the browser, given vendor guidance that Vitest does not render async Server Components? (c) What automated evidence, if any, re-proves the page-level two-host claim after exit — an HTTP smoke against `next start`, one narrow Playwright smoke pulled forward from Phase 06, or a dated manual record? (d) By what mechanism does the `frontend` job refuse skipped and todo cases, which it does not today, since `No_Architecture_Test_Is_Skippable`'s runner leg reads only the backend `.trx` files? | (a) host normalization and header stripping, locale parsing and entry answers, hop headers with no tenant selector, `not_found` mapping — each with an inversion companion; (b) async pages covered through their synchronous children; (c) the reviews split three ways; (d) a reporter-output check or a lint ban on disabled tests, failing also on a package with tests and no script, proven with a planted skip | Detail: a phase-doc statement; the test files; the Standards 21 entry `No_Architecture_Test_Is_Skippable` extended rather than a second name; `ci.yml`. Contract for (c) only if a browser smoke moves: a Testing Standards § End-to-End Tests edit citing this row, with its carriers | P02d-5 (a; d at the latest), P02d-6 (b, c), P02d-7 (c's job) | [Accepted — 2026-10-08](#p02d-5-accepted-answers): (a,d) tests and non-skippability; [Accepted — 2026-10-09](#p02d-6-accepted-answers): (b,c) synchronous tests and required production HTML/RSC product proof; P7 owns the browser/demo job; [Accepted — 2026-10-11](#p02d-7-decision-package-2026-10-10): narrow browser-job scope; ADR-0056 measurement Accepted on the same date; browser proof delivered in Step 3; CI receipts owned by Step 4 | -| G39 | Is [ADR-0027](../decisions/0027-frontend-i18n.md), the frontend i18n library, Accepted in this phase rather than Phase 04, or do this phase's pages meet a library-neutral message contract under the standards index's carve-out? Where does the one UI string catalogue live — the carriers name three paths? | The reviews differ: Accept at first use (`next-intl` composed with the tenant middleware, with its pin and licence verdict), or move only the minimum slice — catalogue loading, lookup, layout locale, `lang`. A third option, no platform-authored text, is hard for a skip link or a not-found page | Contract: ADR-0027 Accepted, with the decisions index row, Phase 04's ADR-0027 lines and the standards index row in the same diff — which, under [the decisions index SLA](../decisions/README.md#open-adr-drafts), makes it an exit blocker here — or a narrowed carve-out plus a phase-doc statement. Detail: [Localization Standards § Strings in Code](../standards/08-localization.md#strings-in-code), [Localization § UI String Catalogue](../architecture/12-localization.md#ui-string-catalogue), the `add-i18n-key` and `add-frontend-route` skills | P02d-6 (the first platform string, message loading and catalogue files) | [Accepted — 2026-10-09](#p02d-6-accepted-answers): ADR-0027, exact pin and one checked UI catalogue home | -| G40 | Route files, page states and site chrome. What happens to `(public)/page.tsx`'s platform placeholder, and to `/studio` and `/portal` on tenant hosts; is the `courses` segment fixed, and which phase owns localized section names? Does this phase ship `(public)` loading, error and not-found files — [Frontend Architecture Standards § Routing](../standards/07-frontend-architecture.md#routing) requires `loading.tsx` and `error.tsx` per route group, and a not-found page is this phase's own choice; how do SDK `not_found`, a cursor `validation_failed`, unavailable and `429` map to page states; what do an empty catalog and a course with no eligible lesson show; does the catalog render a next-page link? Does a minimal chrome ship? Are `hreflang`, canonical and `og:locale`, which [Localization Standards § SEO](../standards/08-localization.md#seo) requires on translated public pages, built here or carved out? | The placeholder leaves the public tree; a fixed `courses` segment with the section-name owner named; minimal state files in tenant tokens; `not_found` → an HTTP `404` page; unavailable or `429` → the route group's error page without disclosure; an explicit empty state; a next-page link over enough seeded courses; in-page links rather than chrome, keeping Phase 06's navigation rows true | Detail: a phase-doc statement; Phase 06's § What Phase 02d already shipped rows reworded; a dated carve-out in the standards index row for Frontend Architecture Standards or Localization Standards, naming the owning phase, for whatever this phase builds less of | P02d-6 | [Accepted — 2026-10-09](#p02d-6-accepted-answers): product routes, approved status/URL chain, page states and metadata | -| G41 | How does the lesson page draw what the subset does not implement — an out-of-subset `x-renderer`, a missing optional field, an array of objects, a stored value whose type differs from its declaration, an `x-taxonomy` value and its missing band? And where do composite and primitive components live — Frontend Architecture Standards names `packages/blocks`, Frontend Architecture names `components/blocks/`, and the registry sits in `apps/web/src/lib/customization/`? | A safe placeholder, never an exception and never raw JSON; a missing optional field renders nothing; `integer`, `boolean` and enums as text; an `x-taxonomy` value as the band's display name in the requested locale. No review addresses the component home | Detail: Tenant Customization Model § 2 (the implemented subset, not a second list) and § 8.1; Frontend Architecture Standards § Public Site Renderer and the Frontend Architecture tree. A new primitive would be an ADR-0018 release, which this row must not assume, since Phase 04 owns the field-type set | P02d-6 | [Accepted — 2026-10-09](#p02d-6-accepted-answers): ordered plain-string components and bounded fallbacks | -| G42 | How do validated branding tokens reach the server-rendered HTML — a `style` attribute on the root element, which needs `unsafe-inline` or `unsafe-hashes`; a nonce-compatible `<style>` element built from validated values; or a per-tenant stylesheet route — without constraining [Security Standards § HTTP Headers](../standards/11-security.md#http-headers)' nonce-based target before Phase 11 documents it per surface? | A `<style>` element built only from registry-validated values, emitting only the `--ls-*` vocabulary, never a `style` attribute; a nonce would force dynamic rendering (G37) | Detail: Frontend Architecture Standards § Tenant Branding for the mechanism; Frontend Architecture § Theming | P02d-6 (the layout's token injection; closes with G37's answer and G16's grammar) | [Accepted — 2026-10-09](#p02d-6-accepted-answers): atomic four-token style-element injection | -| G43 | Which accessibility checks on this phase's pages fail a build — route tests asserting `lang`, one `<main>`, the heading outline, a skip link and a descriptive title; `jsx-a11y` at error severity, where most of the shipped config's rules warn; or jsdom axe, which Testing Standards puts through Playwright in Phase 06? Is catalog → lesson a critical flow that needs [Accessibility Standards § Testing](../standards/16-accessibility.md#testing)' screen-reader smoke test? | Route tests in the `frontend` job for the checkable semantics; keyboard, focus and 320 CSS px reflow in the manual record; failing `jsx-a11y` with a planted companion. No review addresses the screen-reader question | Detail: a phase-doc statement; [Accessibility Standards § Tooling](../standards/16-accessibility.md#tooling) if lint severity or component axe becomes a rule; the lint configuration. Whether failing lint enforces the standard couples with G44; its index row changes only in the enforcing pull request | P02d-6 (page components and their tests) | [Accepted — 2026-10-09](#p02d-6-accepted-answers): failing lint/semantics and mandatory manual assistive-technology proof | -| G44 | The Lighthouse job. Does it activate in this phase, and on what full-stack harness — a migrated stack, a seed written as `learnstack_app`, the API as a process over the hop with a per-run secret, `next start` on a production build, both seed hosts reachable from CI's browser, a readiness and tenant-marker check before the audit — or does activation move to the phase that brings a browser harness? What does it assert: the URL set and which [Performance Standards](../standards/15-performance.md) row each page answers to (its LCP row names a landing page this phase does not ship); which rows, under which throttling preset; the 200 KB budget or the 250 KB forbidden line; hard or warning, run count and aggregation; categories, including the accessibility audit [Accessibility Standards § Tooling](../standards/16-accessibility.md#tooling) requires; the runtime ceiling, tool install and report destination; and what the standards index rows for Performance and Accessibility say afterwards? | Activate here, reusing the `make demo` entrypoint; catalog, course and lesson on both hosts plus the bilingual tenant's second locale; hard assertions on deterministic audits (script transfer size, CLS, the accessibility category or contrast over both palettes) and median-of-N timings as warnings, with TBT rather than a lab INP; tooling from the lockfile; reports to workflow artifacts only; Accessibility promoted if asserted hard, Performance kept Adopted as a pre-baseline check unless a hard budget makes it Active for what ships. The budget authority is settled: [Frontend Architecture Standards § Performance](../standards/07-frontend-architecture.md#performance) names Performance Standards | Contract: a phase-doc statement plus a committed Lighthouse configuration. Detail: `ci.yml`, CONTRIBUTING's activation edits, the `run-tests-locally` skill; Performance Standards only if a number or lab profile changes; the standards index rows and status headers in the enforcing pull request. Moving activation edits `ci.yml`, CONTRIBUTING and the skills, and leaves Phase 01's and 02a's records as written | P02d-5 (whether it activates, as an input to G32: the hosts must work in CI's browser), P02d-7 (the harness and assertions) | [Accepted — 2026-10-08](#p02d-5-accepted-answers): whether: activate in P7; harness details stay P7; [Approved — 2026-10-11](#p02d-7-approval-and-exit-boundary): bounded seventh-check activation after real success; [Accepted — 2026-10-11](#p02d-7-accepted-answers): ADR-0056 measurements and serial feasibility gate; local enforcement passes; live CI/protection receipts owned by Step 4 | -| G45 | What does `make demo` start and guarantee on a clean checkout? The process model — a foreground supervisor over detached compose, or detached processes with a stop target; the web app's mode; how environment reaches host processes, given `dotnet run` reads no `.env` and nothing creates `apps/web/.env.local`; readiness waits before Phase 11's `/readyz`; stale-`.env` detection; re-run and stop behaviour; whether its seed step keeps `make seed`'s wait on every default-profile service and both Keycloak realms; and what it prints, including the bilingual tenant's second-locale URLs | The reviews differ on attached versus detached processes; both reject a destructive reset, wait on both processes, keep re-runs idempotent and have CI reuse the entrypoint | Detail: the `Makefile` targets with help lines and a dated phase-doc statement; README § Quickstart, `scripts/seed.sh`'s closing output and the `local-dev-setup` and `seed-tenant` skills in the same packet; Infrastructure Standards § Healthchecks if the seed's gate narrows. No ADR | P02d-7 (with G44, whose job invokes the same entrypoint; if G44's harness moves earlier, this row moves with it) | [Accepted — 2026-10-11](#p02d-7-demo-lifecycle): shared foreground lifecycle; implemented with both review rounds complete in Step 1 | - -Gates that define one mechanism are answered against each other. Where their parts shape -different packets' code, the mechanism is split as -[Roadmap § Decision Timing](README.md#decision-timing) splits a gate: parts that block -the same packet close together in its pass, and a part that blocks a later packet closes -with or after the earlier one, never contradicting it: - -- G2 and G3 — the aggregate boundary decides where the state lives. -- G4 and G12 — the pin and the contract that resolves it. -- G7 — one ADR-0003 amendment — with G14's seed context in `P02d-2`. -- G8 and G9 — the Education chain's detail and the guards that hold it. -- G11, G14 and G15 — the writers pass. -- G16, G17 and G21 — the closed key set the PII answer rests on, and what a token may - point at. -- G18 and G19 — what the seed may publish. -- G22, G23 and G24 — the read internals. -- G25 through G31 — one public contract and one OpenAPI baseline. -- G32 through G37 — one hop; G33 and G34 share any ADR-0036 amendment. -- G39 and G40 — routing and strings. -- G44 and G45 — one stack entrypoint. - -### Pending Course Marketplace proposal - -**Pending direction review — 2026-09-17.** At the maintainer's request, P02d-2's -decision pass first considers institution sites alongside a -[Course Marketplace](../decisions/0049-institution-sites-and-course-marketplace.md). -ADR-0049 is Proposed; this note accepts no gate and assigns no marketplace delivery -scope to P02d-2. Its -[acceptance checklist](../decisions/0049-institution-sites-and-course-marketplace.md#implementation-notes) -records the unresolved product, delivery and commercial decisions. - -**Review follow-up — 2026-10-01.** The -[scoping companion](../architecture/34-course-marketplace-scoping.md) separates -live-product delivery, operations, privacy, regional topology and commerce recovery -from this packet. Public-only P02d-2 has no technical dependency on those capabilities; -the maintainer's planning hold remains until they resolve or release it. No review -recommendation selects protected authoring or accepts marketplace delivery scope. - -**Historical boundary before exact acceptance.** G3's publication answer was accepted -on 2026-09-14 under ADR-0048; direction endorsement alone did not reopen it. The -maintainer's subsequent exact approval of ADR-0050 supplies the superseding contract -and [dated G3 supersession](#g3-supersession-2026-10-02) below. The original question, -accepted answer and delivery record remain intact. - -**Maintainer endorsement — 2026-10-02.** The maintainer approved following the -recommendations and completing preparation. The hybrid direction and proposed -[Phase 09a](phase-09a-course-marketplace-pilot.md) are planning targets, not accepted -commerce contracts. The preparation hold is released. Protected authoring is prepared -in ADR-0050. The subsequent exact approval is recorded below; it does not accept -marketplace commerce. Future commerce feasibility does not block this packet. - -### P02d-2 decision package (2026-10-02) - -**Accepted — 2026-10-02.** The maintainer approved ADR-0050, ADR-0051 and the exact -packet statements, inventory and four-step plan below, then requested documentation -updates and a wait. Current gate cells and ADR lifecycle/index records are updated; -new source proofs were Registered at acceptance. The original G3 question, -P02d-1 accepted answer and delivery record are preserved. At acceptance, implementation -had not started; the [delivery record](#p02d-2-implementation-delivery-2026-10-02) -tracks the subsequently resumed work. - -#### G3 supersession (2026-10-02) - -ADR-0050 supersedes ADR-0048's public-only implication. Independent `draft → published` -states, one-root publication and no version snapshot remain unchanged. Explicit -Course content policy is inherited by lessons: `public` or `enrollment_required`. -Legacy rows backfill restricted; the migration was planned for P02d-2 and is now -recorded in the Step 1 delivery below. - -This dated entry governs the current P02d-2/4/6 criteria wherever the inherited -packet text below describes publication as sufficient for anonymous body access: - -- P02d-2 requires explicit policy, restricted legacy backfill, six separate Education - commands and exact seed convergence; publication does not grant access. -- P02d-4 admits published marketing fields under either policy but exposes no - restricted lesson inventory, count, descriptor, body or media URL. Direct hidden - lesson lookup remains indistinguishable `not_found`; eligibility precedes public - serialization, caching and conditional responses. -- P02d-5/6 preserve that public DTO boundary and render a bounded locked state with - no invented payment or enrollment action. Credentials never unlock anonymous reads. -- Phases 04/05/07 own protected media, version/policy evolution and grant evaluation; - unsafe live rollback is prohibited under ADR-0050's containment contract. - -The accepted inventory and text-card subset below govern seed and rendering scope -where older packet planning differs. Remaining transport/cache/OpenAPI/renderer -gates stay open for their named packets; acceptance claims no implementation. - -<a id="p02d-2-proposed-answers"></a> - -#### P02d-2 accepted answers - -| Gate part | Accepted answer and detail owner | -|---|---| -| G3: access, commands and seed states | [ADR-0050](../decisions/0050-publication-and-course-content-access.md) separates publication/access, backfills restricted policy and denies protected lesson inventory. Lifecycle stays independent draft → published. [Education writer plan](../modules/education/README.md#p02d-2-accepted-writer-contract) names six commands; seed states are explicit below | -| G5: level validation | New course binding requires the exact Active taxonomy revision and declared band; never resolve a live key. The [Customization contract](../modules/customization/README.md#p02d-2-accepted-exact-write-contract) owns eligible revision rules. Unresolved public labels remain G5's P02d-4/6 decision | -| G7: child derivation | Scope comes from trusted context and authorized parent; missing/cross/sibling parent is `not_found`, visible but unwritable parent scope is `resource_scope_violation`. No request tenant/organization authority; database guards remain unchanged | -| G11: writers, failures and convergence | Separate create, translation-add and publish commands per Education root; translation insertion reports known slug uniqueness as `business_rule_violation`. Tenancy locale and whole-theme commands write one root. The specs own matrices; seed never treats a generic lifecycle failure as success | -| G12: contract | Uncached Customization application interface returns immutable value DTOs for exact revisions; new binds Active, existing-pin writes Active/Deprecated. No foreign Domain/Infrastructure reference, FK, public marker or cache. Snapshot eligibility is at validation read, not a claim of Active-at-commit | -| G13: locale | Uncached Tenancy application contract requires canonical enabled membership. No platform locale registry; use existing LocaleTag grammar/canonicalization/35-character bound. No rows means no content locale, not implicit `en`; label fallback does not change URL/body eligibility. Removal/disable retains Education data and later reads recheck membership; the lifecycle commands belong to Phase 03 | -| G14: seed | Inventory and test-owned controls below; all literal identities and expected counts move into `SeedData` with implementation. Tenant-wide branding/content announce null organization. Built-in `card`/`plain` stay unchanged and Active | -| G15: setter fence | Ownership verification becomes contextual `ISender` queries, explicitly audit Off; no direct seeder transaction/context setter. [Caller fence implemented in Step 4](../standards/21-architecture-tests-catalogue.md#seeder_does_not_call_tenant_context_setters) has a planted-caller companion; no new ADR-0040 setter admission | -| G16(a–e): branding | One tenant-wide `branding.theme` document, four closed color fields, complete replacement and contrast refusal; exact version for replacement. Command-local registry preserves generic settings. Organization overrides refused; no fonts, logo, URL or layout setting in this packet | -| G17: PII | Mark generic `TenantSetting.Value` `[PiiSensitive]` before its writer, including whole JSON audit redaction. Public branding allowlisting is a separate boundary, not permission to expose generic settings | -| G18: presentation | [ADR-0051](../decisions/0051-ordered-text-card-presentation.md) extends ADR-0043 with optional strict root `x-fields`; seed opts into ordered localized plain-string cards. Legacy schemas remain valid, unchanged; no renderer-key or presentation-column change | -| G19: active content | The seeded profile has no active URL/markup sink; output is escaped text, never linkification or Markdown/HTML. ADR-0051 names first-sink owners; generic schema validation is not navigation/media authorization | -| G20: literal source | `SeedData` owns all demo identities, literals and expected inventory. The [Registered literal guard](../standards/21-architecture-tests-catalogue.md#production_code_does_not_branch_on_demo_tenant_literals) consumes that declaration when implemented; production subjects/exemptions and behavioral genericity proof stay with their later packet parts | -| G21: subresources | No new remote asset/font/logo or cross-origin subresource from seed/theme/text cards. Cookie behavior remains P02d-5; public output still needs later transport/render gates | -| G23: freshness bound | No settings cache in P02d-2/3: no seed-process staleness, generation migration or out-of-band loader. P02d-3 owns the ambient typed accessor and scoped merge; latency is a later measurement, not a passed budget | - -G18/G19's selected vehicles are accepted ADR-0051 and append-only ADR-0043 -Amendment 5. The original register's Leaning/Vehicle text remains review history; -this acceptance records the selected vehicle explicitly. Existing ADR decisions -are preserved; ADR-0048's Status and dated supersession are lifecycle bookkeeping. - -#### Seed inventory and ownership - -Step 4 delivers this inventory; both review rounds and final verification passed. -Exact IDs, schema/body literals, slugs, labels, palettes and computed counts live -in `SeedData`; no -production branch knows `demo-english`, `demo-yoga`, `grammar-topic` or `asana-pose`. -The existing fixed tenant, organization, host and built-in customization IDs stay. - -| Data | English tenant | Yoga tenant | -|---|---|---| -| Host context | Existing tenant host, organization null | Existing Studio One host | -| Locales | `en`, enabled default | `tr-TR`, enabled default; `en`, enabled | -| Tenant content type | `grammar-topic`, revision 1 Active, `default-card`; plain-string `concept`/`example` | `asana-pose`, revision 1 Active, `default-card`; plain-string `pose`/`instruction`/`breathing` | -| Taxonomy | `cefr`, revision 1 Active; six declared bands | `yoga-difficulty`, revision 1 Active; three declared bands | -| Branding | One tenant-wide `branding.theme`, complete valid palette | One tenant-wide `branding.theme`, distinct complete valid palette | -| Courses | Four: tenant-wide published public, tenant-wide draft public, tenant-wide published restricted, Kadıköy-scoped published public | Four: tenant-wide published public, Studio One published public, Studio Two published public, Studio One published restricted | -| Lessons | Five: two under public tenant-wide course (published/draft), one published under draft parent, one published under restricted parent, one published Kadıköy-scoped | Five: one tenant-wide, two Studio One public, one Studio Two, one Studio One restricted; published | -| Translations | One `en` translation per course/lesson | Both `tr-TR` and `en` per course/lesson; genuinely different translated slugs/labels | -| Cross-tenant positive control | Published public tenant-wide course uses `en` slug `foundation` | Published public Studio One course also uses `en` slug `foundation`; no uniqueness across tenants | - -All eight courses and ten lessons have explicit pins and access/state choices; -lesson policy is inherited. The declared translations total 27: nine English and -18 Yoga. No remote media is seeded. Wrong-course proof uses the two visible Yoga -courses; organization controls are hidden/visible against the appropriate host. - -Pagination uses **test-owned** courses and a test-selected bounded page size in -P02d-4, not arbitrary mass demo data or a premature G10 default. A retained -disabled-locale translation is also a P02d-4 historical-state fixture, with an -explicit test setup; `make seed` does not bypass locale admission to fabricate it. -Schema mismatch, absent presentation, missing labels and unresolved pins are negative -test fixtures rather than invalid demo rows. Packet 7's raw `tz`/organization `theme` -fixtures remain legal and are counted separately from the new seed theme. - -Every act derives a fresh composed trusted seed scope, with nullable organization. -Tenant locales, customization definitions, branding and tenant-wide courses run in -tenant-wide context; organization courses/lessons run in their exact organization. -Translations and publication use the root's write scope. No admin role, superuser, -RLS bypass, direct EF mutation or ad hoc seed SQL supplies normal writes. - -Seed order is provisioning/organizations/hosts, enabled locales, built-ins and tenant -types/taxonomies (create then publish), branding, course/lesson drafts and translations, -then each selected root's publication. Translation precedes publication on a new root. -Restricted controls depend on accepted ADR-0050 and its applied migration. - -Before skipping an existing act, the ownership query verifies exact ID, parent, scope, -pins, enabled locale, translated slug/text, semantic JSON, policy and state as relevant. -Absent acts are written; exact completed acts are skipped without mutation/audit. -Creation verification accepts only the declared draft intermediate state or intended -final publication state, with identical immutable data; later acts still verify all -translations and final state. It does not demand draft on a completed published root -or accept arbitrary states. This rule also covers customization create/publish acts. -A typed uniqueness, concurrency or lifecycle race triggers one fresh-scope ownership -check against that act's completed postcondition, never blind retry or -matching by display name. Mismatch fails nonzero without editing, unpublishing, -rebinding or selecting another revision. Existing published translations are checked -and skipped before calling the draft-only translation command. A published mismatch -is not accepted merely because that command returns `translation_requires_draft`. -If a competing runner has not completed the exact postcondition, fail safely for a -later explicit rerun rather than returning false success or spinning indefinitely. -Interrupted partial seeds converge; a second completed run adds no roots or audit rows. - -#### Implementation steps and review loop - -All steps run on **development**. No branch switch, push or PR is part of preparation. -Each implementation step follows the maintainer's requested loop: implement and -commit; first fresh independent multidisciplinary review; verify/fix valid findings -and commit; second fresh review agents; verify/fix and commit; continue automatically. -Agent models/effort follow complexity and available models. Unverified findings are -rejected with evidence; an unresolved material defect blocks that step's completion. - -| Step | Coherent change | Required evidence before step completion | -|---|---|---| -| 1 — policy and contract foundation | Education access value/configuration and additive migration; exact Customization/Tenancy read DTO contracts; ADR-0051 profile parser/resolver; module-scoped seed verification queries | Domain/profile positive and negative cases, exact revision and locale isolation, policy/default/legacy preservation, migration forward/down/reapply and pending-model check; unsupported schemas remain valid but not implicitly renderable | -| 2 — Tenancy writers | Locale commands and pre-mutation guards; default-enabled CHECK migration; whole-theme registry/command, contrast and concurrency; PII capture; matrices/composition | Disabled-first→enabled-second, disabled promotion leaves root/audit unchanged, invalid legacy refusal, injected second-save rollback, scoped writes, palette and concurrent replacement/create conflicts, whole-value audit redaction | -| 3 — Education writers | Six separate commands, validation against exact schema/taxonomy and enabled locale, parent scope, named-constraint failures, audit and ambient transaction | Body/pin/locale/slug failures, one-root lifecycle, publication audit atomicity, RLS mirrors, uniqueness races, stale versions, and swallowed nested failures cannot later flush dirty state | -| 4 — convergent seed and packet closeout | Contextual verification replaces direct setter; complete SeedData acts; source guard and planted companion; seed tests and Packet 7 counts recomputed; documents match delivery | Fresh seed, second-run no-change, interrupted recovery, concurrent seed convergence, mismatches fail nonzero without writes, host/scope positive controls, no caller-fence escape, full required verification and two review rounds | - -Checks scale to each step's change. Final closeout runs Release build/format and all -required unit, architecture, contract, Docker-free and Docker integration suites with -zero skips; applicable EF chains' pending-model/forward/rollback/reapply checks; -seed convergence; Markdown links/anchors and `git diff --check`. Record actual commands, -counts and results in the delivery record, not a speculative passing total here. - -#### Approval boundary and readiness - -**Preparation verification — 2026-10-02.** The reviewed documentation commit is -`7bc8e63`, against `6bbcb1e`; no implementation is included. First-round security -and governance findings were verified and fixed: post-build extension resolution, -explicit lesson seed states, no platform locale registry and endorsed participation -wording. Two fresh second-round agents independently returned Approve, with no -remaining actionable findings. Reviews used `gpt-6-astra` (high) for security and -`gpt-6.1-sol` (xhigh) for governance/seed/corpus consistency. - -- Architecture: 177 passed, zero failures/skips, Release `--no-build --no-restore`; - the TRX execution-count check passed. This verifies existing guards, not future - policy migrations, writers or public readers. -- Documentation: 33 Markdown files, 1,715 local references and 444 fragments checked; - added prose wrapping and `git diff --check` passed. External provider/legal evidence - was not reassessed in this preparation pass. -- Accepted ADRs were unchanged. The entire P02d-1 decision/delivery suffix was - compared byte-for-byte with the baseline and is unchanged. -- Commit hooks, including staged Leakwatch and commit-message validation, passed. - Work remains on development; no push or PR was performed. - -**Exact acceptance and wait — 2026-10-02.** The maintainer approved ADR-0050/0051 -and this package, with the explicit instruction to complete documentation and wait. -Lifecycle, dated G3 supersession, current gate statuses, corpus references and new -Registered source-proof rows are updated. P02d-2's decision pass is complete and -the document is ready for Step 1 when implementation is resumed. No code, migration, -handler or new seed data has been delivered; the packet is not marked complete. - -The marketplace's company/country, provider, selected region, legal roles, seller -corridors and detailed Phase 09a contracts remain its own first-consumer gates. -ADR-0049 and Phase 09a remain Proposed. They neither expand P02d-2 nor hold its -independent protected-content work. No implementation, push or PR follows this update. - -**Acceptance verification — 2026-10-02.** Two independent reviewers returned Approve -after verified bookkeeping findings were fixed: `gpt-6.1-sol` (xhigh) for governance -and `gpt-6-astra` (high) for security/corpus consistency. Both checked the final scope, -partial gate closure and absence of implementation claims. - -- Existing Release architecture suite: 177 passed, zero failures/skips; the TRX - execution-count guard passed. Future Registered proofs are not included in that count. -- Documentation: 33 changed Markdown files, 2,117 local links and 486 fragments checked; - added prose wrapping and `git diff --check` passed. -- ADR-0043's pre-existing text and ADR-0048's original decision body are unchanged; - additions are dated lifecycle/extension disclosures. The complete P02d-1 suffix - remains byte-for-byte unchanged against `3f849d1`. -- The two new catalogue rows remain Registered; all 144 Implemented entries are - unchanged. No backend/frontend implementation or deployment operation is included. - - -### P02d-2 implementation delivery (2026-10-02) - -The maintainer resumed implementation after exact approval. The earlier acceptance -and wait record remains historical; work now follows the four accepted steps on -**development**. No public endpoint, marketplace commerce or authorization grant -is introduced by P02d-2. - -**Step 1 — policy and contract foundation, complete.** Course creation takes -an explicit closed policy. The additive Education migration defaults/backfills -`enrollment_required`, preserving existing content and scope; technical Down is -proved only in a disposable database, not approved as a live public-reader rollback. -Exact revision/locale ports, ordered text-card semantic resolution and contextual -seed verification queries are registered in both composition roots. Read queries -are Off; no seed context-setter change or writer completion is claimed yet. - -**Step 1 pre-review verification.** Release build completed with zero warnings/errors. -Docker-free tests: 1,489 unit, 177 architecture, 171 integration and one contract, -all passing with zero skips. Fifteen focused Docker integration cases passed, -including both composition roots, exact revision/locale reads, Education persistence -and migration forward/down/reapply. Full format verification and the TRX execution -count/zero-skip checks passed. Markdown validation checked 2,137 local references -and 487 fragments across 34 files against the preparation baseline; P02d-1's frozen -record and all Accepted ADR bodies remain unchanged. `git diff --check` passed. - -**Step 1 review round 1.** The policy/contract implementation is `682f858`. Two -independent agents found no production defect. Verified gaps in positive/sibling/foreign -setting proofs and disabled/foreign locale proofs were corrected independently of -invalid-default configuration checks. All five strengthened foundation tests pass, -including a disposable predecessor-schema proof for a disabled legacy default. -Current README, glossary and module/standard -status statements were aligned with the delivered foundation. A broader Docker -regression run passed all 228 cases, with zero skips. Fixes are `a8a51ce`. - -**Step 1 review round 2.** Fresh agents independently returned Approve for -`45805c8..a8a51ce`, with no actionable findings. Security review used `gpt-6-astra` -(high); profile/corpus review used `gpt-6.1-sol` (xhigh). Independent runs passed 116 -profile/registration unit cases, six foundation/migration Docker cases and all 177 -architecture cases, with zero skips. Links/anchors and the frozen P02d-1 suffix passed. -Step 1 is complete after both requested rounds. - -**Step 2 — Tenancy writers, complete after both review rounds.** -Three unrouted tenant-wide commands implement locale addition/default selection and -complete branding creation/exact replacement. Existing locale configurations are -validated before mutation; the first enabled locale is promoted even after disabled -rows. Two-pass default saving also handles newly Added defaults. The additive CHECK -refuses disabled defaults and never repairs legacy data automatically. Generic setting -JSON is wholly redacted at capture. Palette fields and CSS mappings share a closed -registry, with per-pair contrast admission and no entitlement gate. Failed saves after -mutation mark the ambient unit rollback-only. Steps 3–4 remain pending. - -**Step 2 pre-review verification.** Release build passed with zero warnings/errors. -Docker-free tests passed: 1,538 unit, 177 architecture, 171 integration and one -contract. The expanded Docker regression group passed all 75 cases, including -composition, locale/default and branding writers, whole-value audit redaction, -concurrent creates/replacements, MUST audit failure, injected second-save rollback, -invalid legacy refusal and migration forward/down/reapply. Execution-count checks -confirmed zero skips. The broader group also exposed a test-isolation defect in -Step 1's writing foundation case: its independent audit rows survived the business -rollback in the shared fixture. That case now owns a disposable database; the full -75-case group passes without leaking rows into other tests. - -**Step 2 review round 1.** Security (`gpt-6-astra`, high) found one verified -classification defect: the shared EF helper wrapped unknown unique constraints with -a business error before the handler could distinguish them. New Tenancy writer -methods now supply owned constraint sets; unowned failures stay database faults. -Two planted PostgreSQL constraints prove `500 internal_error`, unchanged state and -no successful audit. Existing helper callers retain their contract. The corpus/theme -review (`gpt-6.1-sol`, xhigh) found two Minor documentation gaps; prose wrapping and -public contract XML documentation are corrected. Palette key-order and exact/over-cap -input proofs also cover its optional test suggestion. After fixes, Release build -passed with zero warnings/errors; 77 Docker regression cases, 185 focused unit and -177 architecture cases passed with zero skips. The implementation is `1b98352`; -first-round fixes are `63ed4bc`. - -**Step 2 review round 2.** Fresh security (`gpt-6-astra`, high) and corpus/theme -(`gpt-6.1-sol`, xhigh) agents independently returned Approve for -`a8a51ce..63ed4bc`. Each independently passed 160 focused unit and 12 PostgreSQL -writer/migration cases, with zero failures/skips. The one verified Minor was a stale -Tenancy component description; its root/writer claim, command/store inventory and -table count now match code. Links/anchors, wrapping and the frozen P02d-1 record pass. -Step 2 is complete; Steps 3–4 remain pending. - -**Step 3 — Education writers, complete with both review rounds.** -Six separate commands write one Course or Lesson and its contained translations. -New binds resolve exact Active revisions; existing lesson pins remain eligible after -deprecation. Enabled locale admission and schema evaluation precede mutation. Visible -but incompatible write scope is refused; hidden roots remain indistinguishable misses. -Translation insertion reserves its tenant-local slug; diagnostics identify only visible -conflicts. Publication remains independent and MUST-audited. Known post-save failures -poison the ambient unit, including when an outer handler absorbs the refusal. -No public endpoint, protected reader or seed execution is claimed by this step. - -**Step 3 pre-review verification.** Release build passed with zero warnings/errors. -The full Docker-free run passed 1,557 unit, 177 architecture, 171 integration and -one contract case, without failures/skips. The focused database regression run -passed 249 cases, including all 14 Education writer cases, the existing Education -isolation suite, Tenancy writers and migration reversal. Both known post-save -refusal variants were absorbed by an outer handler that saved another root; the -owning transaction still refused commit and rolled back both writes. Concurrent -publication and localized-slug insertion produced one durable winner. Unknown -unique constraints retained `internal_error`; hidden collisions disclosed no root -identity. Full format verification, Markdown links/anchors and `git diff --check` -passed. This step changes no EF model or migration. Two fresh review rounds follow. - -**Step 3 Round 1.** Fresh GPT-6 Astra (high) security/transaction and Claude Sonnet 5 -(high) contract/validation/corpus reviews both returned Approve. The security reviewer -independently reran all 14 Education writer database cases. Two verified Minor test -findings were fixed: validator tests now resolve the registered internal validators -through DI, and organization-scoped translation/publication attempts against a visible -tenant-wide Lesson explicitly assert refusal and unchanged state. The optional -unreachable policy-switch suggestion is not a defect: the composed validator admits -exactly the two explicit values, and the domain guards its closed enum. No production -change was justified. Round 2 uses new review sessions after the fixes. -Release build, all 16 validator cases and all 14 writer database cases passed again, -without failures/skips. Full format verification exited zero; links/anchors and the -unchanged P02d-1 suffix check passed. - -**Step 3 Round 2.** Two fresh read-only Codex review sessions (high and xhigh) -reviewed `8b981c7..a4a29d3`. The security reviewer returned Approve; the contract -reviewer requested changes. All findings were verified against current code. -Internal parent and collision ports now retain module-local typed IDs; conversion -occurs at the command boundary and unwraps only for exported diagnostics. The -aggregate-write census excludes typed keys without exempting the reader by name; -its planted companion still detects direct, nested generic, array, by-ref and mixed -object writes. The existing 1 MiB instance cap now has one shared owner, and the -Education validator checks UTF-8 size before any JSON parse. Inclusive ASCII and -multibyte boundary tests and a composed writer refusal/unchanged-state proof cover -it. New null suppression is removed or justified by the exception filter. README, -Database Standard and the old Backend Coding publication example now name the -shipped writer contract. Additional focused review follows these production fixes. -The attempted fresh Claude sessions reached the provider's session limit and -produced no review; they are not counted as completed rounds. - -**Step 3 fix verification and closeout.** Fresh xhigh read-only review of -`a4a29d3..2e498ce` returned Approve with no blocking findings. Its two low-priority -suggestions were verified and applied: the oversize proof now counts every audit -outcome, and a stale XML description no longer attaches the old size limit to -`BuildOptions`. The fixed census passes all 178 architecture cases; its planted -controls also cover inherited interface signatures. Release build has zero -warnings/errors, 1,559 unit cases and the contract case pass, and all 780 integration -cases pass, including 15 Education writers. No failures/skips remain; format, -local links/anchors and the frozen P02d-1 suffix check pass. Step 3 is complete; -Step 4 follows below. - -**Step 4 — convergent seed, complete after both review rounds.** -The fixed identities remain unchanged. SeedData owns every declaration and expected -count: two tenants, four organizations, two hosts, three locales, four content types, -four taxonomies with fifteen bands, two distinct whole themes, eight courses, ten -lessons and twenty-seven translations. Published/draft and public/restricted cases -include tenant-wide and both organization scopes. English and Yoga have their own -schemas, labels and bodies; Yoga has complete tr-TR/en translations. No remote media, -marketplace fields or P02d-4-only historical/negative fixtures are introduced. - -Every verification and write goes through contextual ISender requests. Completed acts -skip before a writer, partial declared acts resume, and a typed race gets exactly one -fresh postcondition read. Mismatches fail without overwrite; no private transaction, -setter or direct persistence path remains. Internal reader ports retain typed IDs. -The caller-fence guard and planted companion are Implemented; G20(a) reads all literal -sources from SeedData, while the full production branch guard remains P02d-7's owner. -The seed skill, host/isolation projections, catalogue and current-state documents -now match implementation. Tests own disposable databases rather than shared cleanup. - -**Step 4 verified consumer defects.** Concurrent seed execution exposed a real -Customization publication race: a competing publish between two READ COMMITTED reads -caused EF to return the already-tracked Draft as its own Active incumbent. Both -handlers now return typed concurrency before mutation. A failed publication save now -marks rollback-only even without an incumbent, so an absorbing outer request cannot -flush dirty publication state later. Six controlled database cases cover both roots, -the precise race and post-save conflict/concurrency absorption. An old unit expectation -that assumed no retirement meant no dirty state was corrected against these proofs. -No new ADR or schema decision is introduced. - -**Step 4 pre-review verification.** The 49 focused database cases pass without -failures/skips: thirty-five Seeder, eight host/isolation and six Customization race -cases. These include full inventory/scopes, all-outcome audit neutrality on repeat, -two real interruption points, coordinated concurrent seed, seventeen mismatch cases, -semantic JSON equivalence and the executable's actual zero/nonzero exit behavior. -A fresh complete seed produces ninety successful audit rows; provisioning writes two -aggregate audit rows, and all counts derive from SeedData. Full verification and -both fresh review rounds were still required at this pre-review stage. - -**Step 4 broader regression corrections.** The complete Docker run exposed two -inherited audit groups tied to the old seed: fixed counts and direct repeat writers -had been inferred from a runner that now skips completed acts, and shared cleanup -could not remove the new restricted dependencies. AuditPipelineTests and -AuditWorkflowTests now own disposable databases and focus their declaration on -provisioning/built-ins. Rollback audit proof sends explicit refused commands and -retains the two provisioning intents plus the standalone organization refusal. -All eighteen cases pass; the expanded 67-case seed/host/Customization/audit group -passes without failures/skips. Complete Docker regression then passed 638 cases. - -The two seeded schemas now differ in property count, as the inherited phase criterion -requires: Yoga also declares ordered, bilingual plain-string breathing text. The -inventory proof checks actual persisted schema shape, beyond changed names/labels. -A verified publication mismatch could otherwise retire a different Active revision -under the same key. Seed sets both publish commands' optional `RequireNoIncumbent` -precondition, which refuses before mutation and retains ordinary succession by default. -Two additional seed cases prove unchanged definitions/versions/generations and no -successful audit on that refusal; normal failed-command audit remains legitimate. -The two new cases and six controlled race/rollback cases pass. Release build has -zero warnings/errors; all Docker-free suites pass again. At that stage, fresh review -closure and final complete verification remained pending. - -**Step 4 Round 1.** Fresh read-only Codex xhigh security review requested changes; -Claude Sonnet 5 high contract/corpus review returned Approve with one cosmetic Minor. -The security finding is verified: publishing the declared revision could retire an -incompatible Active revision. Contextual Off queries now check the logical key's -Active identity before registration, and publication checks `RequireNoIncumbent` -inside its transaction before retirement. Four pre-existing absent/Draft cases and -two coordinated different-revision winners accompany the same-ID race proofs; -failed seeds preserve existing content, versions, generations and audit successes. -The cosmetic extra blank line is removed. The earlier 67-case regression corrections -and schema-shape proof are included in this fix set; a fresh second round follows. - -**Step 4 Round 2 and packet closeout.** Two fresh read-only Codex review sessions -(high for contracts/corpus; xhigh for security/transactions) reviewed -`951acd2..fecdc76` and independently returned Approve. No Blocker or Major remained. -Both found the stale README bootstrap statement; the contract review also found the -old Step 4 review heading. Both verified Minor findings are fixed, and current-state -carriers and the seed skill now name completion. No additional production change was -required. The implementation is `5081724`, with first-round fixes at `fecdc76`. - -**Final verification — 2026-10-02.** All required local checks pass: - -- Release build: `dotnet build backend/LearnStack.slnx --no-restore -c Release`, zero - warnings/errors. Full format verification uses `dotnet format` with - `--no-restore --verify-no-changes` and exits zero. -- Backend: Release `dotnet test --no-build --no-restore` with separate - `Requires!=Docker` and `Requires=Docker` runs; 1,559 unit, 181 architecture, - one contract, 171 Docker-free integration and 644 Docker integration cases pass. - Total: **2,556**, zero failures/skips. TRX counters were inspected for failures; - `scripts/assert-tests-ran.py` also proves execution and zero skips per assembly. -- The focused seed/host/Customization/audit group passes all 73 cases: 39 Seeder, - eight host/isolation, eight controlled publication and eighteen audit cases. - Actual CLI exits, interrupted/concurrent recovery, exact repeat neutrality, - incompatible Active winners and transaction absorption are covered. -- All five EF chains report no pending model changes using the pinned tool in - `backend/`, Release `--no-build` and a design-time-only placeholder connection. - The complete Docker run includes every-chain forward/down/reapply, populated - access-policy preservation and disabled-default migration refusal. This is - disposable-database reversal evidence, not approval to remove live access policy. -- Frontend: frozen install, typecheck, lint, build and all thirteen Vitest cases pass. - Four default/gated dev/e2e compose combinations and actionlint pass. These surfaces - did not change after verification; no browser-rendered demo is claimed. -- The PR documentation sweep checks 45 Markdown files, 2,868 local links and 571 - fragments. Added prose wrapping and `git diff --check` pass. Analysis-directory - hits are the existing prohibition/history wording, not links to scratch material. - The complete P02d-1 suffix is byte-identical to the acceptance baseline. Accepted - ADR bodies have no implementation-time edits. -- Commit hooks pass, including staged Leakwatch, formatter and strict message checks. - The pre-closeout PR range's seventeen non-merge commits pass the same strict hook. - Final closeout is checked with the resulting PR range before publication. - -**Disposition.** P02d-2 implementation, both review rounds per step and required -verification are complete on development. PR review and merge remain the maintainer's -next step. Phase 02d remains in progress. P02d-3 owns generation-keyed customization -read internals and the uncached ambient typed settings accessor; its remaining gates -open before that work. P02d-4 owns public reads and hidden-response/query-plan proofs; -P02d-5–7 own transport, rendering and the running two-site demo. No marketplace, -authentication, enrollment, public API or browser-delivery completion is inferred. - -#### PR review corrections (2026-10-02) - -External PR #23 findings were verified against `6fce655` before changes. Current -carriers now separate delivered P02d-2 policy, migration, writers, presentation -resolution and seed from P02d-4 public reads, P02d-6 rendering and Phase 07 grants. -ADR-0050/0051 retain their acceptance-time Status and Decision text; dated -implementation disclosures and Amendment 1 record delivery. The indexes, glossary, audit -review state, implemented setter fence, contrast refusal and unrestricted default -entitlement provider are aligned. No access, branding, marketplace or governance -decision changes. - -The exact presentation reader now returns `/properties` validation failures for missing -or non-object members and non-object roots. Eleven regressions preserve its Result -contract and optional legacy profile behavior. Migration reversal locates the policy -migration by stable ID; both Up applications prove the restricted backfill. Lesson and -Course post-save refusal absorption, both Customization MUST-audit replacement rollbacks -and the incumbent rollback-only branch have direct proofs. A controlled non-provisioning -translation race witnesses two real save attempts, one successful act and one audited -refusal, fresh completed-state recovery and an unchanged all-outcome repeat snapshot. - -Theme replacement-version requirements do not apply to create-only seed writes. -Reference admission remains with the authoritative exact-revision writers; no new -whole-declaration preflight contract is introduced. Existing inventory comparisons -already prove both tenants' shared English slug and foreign-tenant invisibility. -Existing repeat snapshots include every audit outcome; the new race additionally retains -an observed failed audit. These findings require no production expansion. - -Release build has zero warnings/errors; 1,570 unit, 181 architecture, 171 Docker-free -integration, one contract and all 69 affected database cases pass with zero skips. -Relative links, fragments, added prose wrapping, format and `git diff --check` pass; the -P02d-1 suffix remains byte-identical. - -**Independent review round 1.** The correction commit is `40d207d`. A fresh Codex -reviewer at xhigh effort traced parser callers, migration targeting, rollback and seed -race evidence; a fresh Sonnet 5 reviewer at high effort checked corpus/governance and -source claims. Both returned Approve with no material findings. A separately detected -89-column prose line is wrapped without changing its meaning. - -**Complete backend verification.** After the corrections, all 2,573 cases pass: 1,570 -unit, 181 architecture, one contract, 171 Docker-free integration and 650 Docker -integration. TRX counters show zero failures/errors/skips; the execution guard passes -for every assembly. All 69 affected database cases pass within the full run. Release -build has zero warnings/errors, and full format verification exits zero. The PR -documentation sweep checks 45 Markdown files, 2,892 local links and 577 fragments. No -frontend or operational surface changed in this correction. The second independent round -and its correction are recorded below. - -**Independent review round 2.** Fresh Codex (xhigh) and Sonnet 5 (high) sessions -reviewed `6fce655..a436a51`. Sonnet approved the corpus. Codex found one valid proof -gap: identical translation contenders did not falsify removal of the loser's required -post-race recheck. All other code/security, rollback, migration and documentation -boundaries were clean. - -The test now covers identical and divergent payloads for the same course/locale. A -conflicting loser must refuse its exact state before reporting the act completed; the -independent later final-state check cannot supply this proof. A controlled mutant that -skipped only the losing-race recheck passed the identical case and failed the divergent -case at the completion assertion. `SeedRunner.cs` was restored byte-for-byte; no -production seed behavior changes. Both positive variants and the complete backend suite -then passed. The standards index's current-state date now matches the delivered -2026-10-02 table. - -**Targeted follow-up review.** A fresh Codex session at high effort reviewed -`a436a51..163eb90` and returned Approve: the completion assertion kills the missing -recheck mutant, winner selection is arrival-order independent, real save/audit witnesses -and cleanup remain intact, and the revised documentation counts agree. The correction -and both independent review rounds are complete; the only verified second-round finding -is fixed and independently rechecked. Final hooks, wrapping, links/fragments and the -frozen-record check pass. PR #23 carries the updated range and validation; merge remains -the maintainer's decision. - -#### Additional PR review corrections (2026-10-02) - -The subsequent review was verified against `eaa72aa`; findings and suggested edits -were treated as evidence, not instructions. No decision, public route or migration -changes were needed. The following corrections retain the accepted packet scope: - -- The tenant write lookup excludes soft-deleted roots, preserving both navigations, - identity matching and cancellation. A real application-role test proves retained - locales/flags on a live root and refusal of locale writes after deletion. -- The aggregate census shares its production predicate with planted fused-port, - two-port, notification, non-public-constructor and negative controls. Key-only - writes remain visible; read exemptions enumerate methods rather than all typed IDs. - Four controlled mutants (first construction only, omitted notifications, blanket - key exclusion and public-only constructors) each fail the intended companion. - The source is restored byte-for-byte before positive verification. -- Both runtime hosts build application pools through the shared role guard. Direct - seed execution now refuses owner/bypass credentials and transitive bypass access; - malformed credential exceptions carry no raw inner parse exception. Unit canaries - inspect full exception text; real direct/transitive refusal runs through both callers. -- The exact presentation resolver converts invalid JSON syntax into a root-located - validation failure. The seed fence also checks IL for direct EF mutation and ad hoc - commands, while admitting immutable data construction and request dispatch. -- Additional proofs cover foreign-context Education writes, locale tenant isolation - and concurrent exact-version changes, identifier-conflict details, renderer-registry - non-emptiness, CHECK removal on Down and refusal of an undeclared persisted locale. -- Current documentation records accepted/delivered branding and writers, the exact - current/planned route boundary, the Tenant locale audit subject and accepted anchors. - ADR-0050/0051 show their dated disclosure inside `#status` and preserve the original - acceptance text under Amendment 2. The catalogue records delivered presentation - proofs separately from Registered public projection/rendering obligations. - -**Verified dispositions.** No remaining item is silently assigned to a later packet: - -| Finding | Disposition and reason | -|---|---| -| Inline tenant lookup / ADR-0049 / permissions | Fixed against the current store, delivery record and Phase 02c route contract. | -| M1 | Fixed; the same production census now has permanent planted controls and four failing mutants. | -| m2–m4 | Fixed: current-state references, JSON syntax refusal and the shared seed/runtime role guard. | -| m5 | Documented per-act durability: a competing Active revision may appear after a registration pre-read, leaving a committed Draft/generation/audit before refusal. Explicit reconciliation is required; seed never rolls back completed acts. | -| m6 | Added the narrow requested proofs, retaining real application-role transactions. | -| m7 | Skipped: ADR-0051 requires existing localized messages plus offending JSON Pointers, which the resolver already supplies; distinct cause keys are not required. | -| m8 | No missing registration found. Both roots are exercised by composed writer/publication tests; a separate parity scanner is optional protection, not a current correction. | -| m9 | Skipped: ADR-0050 explicitly permits disposable Down/reapply and denies live rollback authorization; the forward-only operational rule already applies. | -| m10 | Fixed: the existing seed caller fence now includes direct persistence writes, with positive and negative planted controls. | -| m11 | Refuted: every existing locale must match a declaration under `SeedVerification.Tenant`; the new persisted-extra-locale test proves refusal without a write. | -| m12–m14 | Fixed: audit subject, unused proposed anchor aliases and Status navigation with dated historical disclosure. | -| s1–s5 | No defect: supported calls validate the closed policy; repeated subject designation is sanctioned; titles/summaries map to unbounded text; no unchanged-version promise exists for default-setting commands; parent reads already use `AsNoTracking`. | -| s6 | Skipped: an admitted named race still requires exact fresh-scope postconditions, already mutation-proved; it never accepts a refusal alone. | -| s7–s8 | Ambient is the sanctioned trusted origin. Exit codes are documented; malformed credential failure text is now proven secret-free. | -| s9 | No current public oracle: explicit-ID writers are unrouted trusted operations and replacement lookup hides foreign roots. Phase 03 owns authoring authorization before reachability. | -| s10–s11 | No supported incumbent-deprecation uniqueness collision or registered authoring route found. Unexpected faults already poison the transaction; anonymous admission remains fenced. | -| s12 | Fixed: delivered profile/exact-order evidence and future renderer/sink obligations are catalogued separately. | -| s13–s15 | No current defect: no production lock incident/online-migration mandate; seed DTOs are private verification contracts; raw foundation inserts intentionally model isolated/legacy fixture states, not provisioning. | -| s16 | Historical counts are retained. Supplemental link counts count occurrences outside fenced blocks across PR-changed Markdown and linked ADR/phase carriers; CI's changed-target audit has a different scope and excludes fragments. | -| Legacy profile boundary | Compatibility applies to schemas without root `x-fields`. Its presence explicitly opts into ADR-0051's profile; a formerly inert annotation at that location is now semantic. | -| PR-external follow-ups | Unchanged scripts and legacy conflict helpers are outside this correction. G20's remaining branch fence stays P02d-7; public reads/rendering/grants retain their existing named owners. | - -The shared [seed workflow](../../.claude/skills/seed-tenant/SKILL.md) records direct -role enforcement, failure codes and the committed-Draft race boundary. - -**Positive verification.** Release build has zero warnings/errors. All 2,590 backend -cases pass: 1,577 unit, 184 architecture, one contract, 171 Docker-free integration -and 657 Docker integration. TRX counters show zero failures/errors/skips, and the -execution guard passes for every assembly. Full format verification exits zero. -Eight controlled mutants fail the intended guard; both source files are restored -byte-for-byte and the positive structural suite is re-run before commit. -The supplemental documentation sweep checks 45 Markdown files, 2,901 local link -occurrences and 580 fragments; `git diff --check` passes and the frozen P02d-1 -suffix remains byte-identical. Independent reviews follow the correction commit. - -**Independent correction review — round 1.** Fresh GPT-6.1-sol (`xhigh`) -reviewed the backend/security/proof boundary at `05682d8`; fresh GPT-5.5 (`high`) -reviewed documentation/governance. Neither found a correctness or isolation defect. -The code reviewer found one unused API redaction helper left by extraction; it is -removed, leaving the shared implementation as the only caller-backed helper. The -parent also corrected one added catalogue prose line exceeding 88 columns. -Release build remains warning/error-free; credential guard tests pass 20/20, -architecture passes 184/184 and scoped format verification exits zero. Links and -the frozen suffix remain unchanged. Fresh round 2 reviews the complete correction -range after this fix commit. - -**Independent correction review — round 2 and closeout.** Two new GPT-5.5 -sessions (`xhigh` for backend/security/proofs, `high` for documentation/governance) -review the full `eaa72aa..15123ca` correction range and both approve without an -open actionable finding. They independently inspect the positive TRX, mutation -and restoration evidence; the documentation reviewer also verifies the unchanged -1,799-line frozen suffix. The reviewed production code is complete. This closeout -adds only the review record; the PR remains open for maintainer review and merge. - -#### Branding tenant-existence correction (2026-10-02) - -The outside-diff finding is verified against `3a4bb5d`. Branding now refuses a -missing or soft-deleted announced tenant with the existing `not_found` result, -after scope validation and before any setting lookup or write. A scalar, uncached -Tenancy reader is registered in both runtime composition roots; the handler still -holds one aggregate write capability. Live Trial tenants remain supported. - -Four application-role regression cases cover missing/deleted tenants and -create/replace intent. A throwing setting store proves refusal precedes any -setting access; fresh reads prove unchanged values/versions and no additional -successful setting audit. The existing seeder-root deletion proof also covers both -branding writes. Unit scope guards prove no existence read before scope admission. - -Release build has zero warnings/errors. Final suite runs pass all 2,594 backend -cases: 1,577 unit, 184 architecture, one contract, 171 Docker-free integration and -661 Docker integration. TRX counters and execution guards report no failures, -errors or skips. Full format, local links/fragments and the frozen P02d-1 record -check pass. Two fresh independent review rounds follow the correction commit. - -**Independent reviews and closeout.** Two fresh GPT-5.5 (`high`) read-only -sessions review the exact `3a4bb5d..50518e7` correction range independently. Both -approve without an actionable Blocker, Major or Minor finding. They verify scope -ordering, live Trial support, both DI registrations, refusal before setting access -and the positive build/TRX evidence. No further production change is required; -this documentation-only closeout records the completed rounds. PR #23 remains -open for maintainer review and merge. - -### P02d-2 merge and closeout (2026-10-02) - -[PR #23](https://github.com/HodeTech/LearnStack/pull/23) merged into `main` at -**11:41:47 UTC**, with final PR head `161314313eeb0d87758fb38c20af5e4c4c1b5766` -and merge commit `8edbb032b81313aae7e635b2782af511a9fe02cc`. Their trees are -identical. `development` was fast-forwarded to the merge commit without switching -branches or rewriting history. This closeout changes documentation only. - -- [x] Accepted P02d-2 gate parts and all four implementation steps are complete; - each step and the subsequent verified PR corrections completed both review rounds. -- [x] ADR-0050's policy, restricted backfill and Education writers are delivered; - ADR-0051's profile parsing and resolution are delivered. Public-read enforcement - remains P02d-4, rendering P02d-6 and course access grants Phase 07. -- [x] Three Tenancy and six Education writers, exact-definition/locale validation - and convergent two-tenant seed execution are delivered and registered. -- [x] The final tenant-existence correction refuses both branding write intents - before setting access; live Trial tenants remain supported. -- [x] The final PR head passed all five required checks; CodeRabbit also succeeded. -- [x] The merge commit passed the same five required checks. - -| Verified revision | CI evidence | Result | -|---|---|---| -| Final PR head `1613143` | [Run 36986675925](https://github.com/HodeTech/LearnStack/actions/runs/36986675925) | All five required jobs succeeded | -| `main` merge commit `8edbb03` | [Run 37002423112](https://github.com/HodeTech/LearnStack/actions/runs/37002423112) | All five required jobs succeeded | - -Final implementation verification records **2,594 passing backend cases**: 1,577 -unit, 184 architecture, one contract, 171 Docker-free integration and 661 Docker -integration, with zero failures or skips. Release build has zero warnings/errors; -format and link/fragment checks pass. The historical P02d-1 record remains unchanged. - -The live required-check list still contains the five recorded contexts with -`strict: true`. The documentation closeout also passes 184 architecture cases, -execution/zero-skip guards, added-prose wrapping and relative-link/anchor checks. - -**P02d-2 is closed. Phase 02d remains in progress.** P02d-3 through P02d-7 have -not started. No public business endpoint or browser demo is delivered by this merge. -ADR-0049 and the Course Marketplace pilot, Phase 09a, remain Proposed. - -#### P02d-3 entry readiness - -P02d-2's merged definitions, settings and seed satisfy the implementation dependency. -The next action is P02d-3's decision pass, followed by read internals with no HTTP: -generation-keyed Customization projections/cache families and a typed Tenancy -settings accessor. The packet table and decision register remain authoritative: - -- G12's cache-key part, G22's ambient loader/generation/rollback/cache contract and - G24's display fallback remain to be accepted. -- G23's no-settings-cache bound is already Accepted. The accessor's name, ambient - loading and tenant/organization scope contract remain P02d-3's decision work; - organization branding overrides and their token merge remain Phase 06. -- Cold/warm statement-count, cache-fault and rollback safety proofs belong with - these readers. Public contracts/eligibility remain P02d-4; transport, rendering - and the final browser/CI demo remain P02d-5, P02d-6 and P02d-7 respectively. - -### P02d-3 decision package (2026-10-02) - -**Accepted — 2026-10-02, verified against `0dec43b`.** The maintainer approved -the three decisions and implementation steps below before source changes. This -closes G12's cache-key part, G22, G23's accessor part and G24's internal fallback -part; it claims no implementation. Detail owners are synchronized in this first -commit. Original questions and shipped delivery records remain intact. Public -response and page-state decisions remain with P02d-4/6. - -#### Verified premises and document review - -The review baseline is `0dec43b` on `development`, following merged PR #23. -The required context reading, relevant module specs, localization/cache/isolation -architecture, ADR-0008/0010/0013/0038/0040/0043/0050/0051 and governing standards -were checked against the current adapters and composition roots. Two fresh -read-only review sessions independently examined cache/transaction safety and -settings/localization boundaries. A third reviewed the completed proposal and -verified no blocker or major finding. These sessions ran no tests and changed -no source. - -- The four Customization writers bump the durable tenant generation inside their - business transaction. A rollback discards that increment; a later commit can - reuse its value. An uncommitted cache fill would then become reachable. -- The ambient unit opens the default PostgreSQL isolation level. Under - [READ COMMITTED](https://www.postgresql.org/docs/18/transaction-iso.html#XACT-READ-COMMITTED), - successive queries may see different committed states; a generation-first - query alone does not prove a coherent definition snapshot. -- `ICacheService.GetOrSetAsync` has a shared factory lifetime. An ambient - connection must not be captured by a factory that may outlive its request or - be shared with another request. This contract uses awaited get/load/set calls. -- P02d-2's exact writer reader is uncached and purpose-aware. It remains so; - display reads must not weaken NewBinding eligibility or change stored pins. -- G23 already rejects settings caching in P02d-2/3. Standards 20's stale TTL rows - are corrected to a reserved, unused family; its metric spelling remains intact. -- The localization architecture, standard and `LocalizedText.Resolve` describe - different fallback chains. G24 below reconciles them before the first caller. -- Organization branding/token merge remains Phase 06. The glossary now states - that ownership explicitly; generic setting scope is not branding authorization. - -The selected vehicles remain the ones assigned by the register: module specs, -architecture/standard details and this dated package under existing ADRs. No new -ADR is required by the accepted ambient design. A different setter, transaction -mode, access policy or cross-module mechanism requires its decision record and -maintainer approval before implementation. - -#### Accepted gate answers - -| Gate part | Accepted answer | Detail owner | -|---|---|---| -| G12: cache key | Cache immutable, untranslated definition families per tenant/generation; indexes inside each family use exact `(key, schema_version)`, including Active and Deprecated, excluding Draft/deleted. Never substitute Active for an unresolved pin. The writer reader stays uncached | Customization spec, Education pin invariant; architecture 32 § 8.2 | -| G22: loader and correctness | Ambient caller transaction only; fresh generation probe per batch, coherent generation/rows snapshot on a miss, mutation-scope cache bypass, bounded statements, cache-fault fallback and generation-driven freshness as specified below | Customization spec § Primary read flow; architecture 32 § 8.2; standards 10/20 | -| G23: accessor | `ITenantSettingsAccessor`, uncached and ambient; typed registered settings, explicit tenant/current-organization selection and whole-value precedence. `branding.theme` remains tenant-wide. No caller-supplied tenant/organization authority | Tenancy spec and glossary; standards 20's existing no-cache answer | -| G24: display fallback | Localization architecture owns the chain; the standard links it. Exact requested tag, progressive narrowing, exact tenant default, platform `en`, then deterministic first-authored Pattern B label. Every resolved label carries its actual locale. Nullable Pattern A display fields end absent; URL/body lookup never falls back | Localization architecture § Fallback Rules; standard 08; SharedKernel and Customization contract; public fields remain P02d-4 | - -#### Customization projection and cache contract - -`ICustomizationDefinitionProjectionReader` is an application -interface returning immutable values through mechanism 1 of ADR-0010. This is an -in-memory projection, not a new `public_*` table or an integration-event consumer. -It resolves a batch of exact content-type and taxonomy revision pins with one -caller-provided display-locale context. No foreign Domain/Infrastructure type, -public marker, HTTP endpoint, schema validator or compiled-validator cache is added. - -Unresolved/ineligible individual pins remain identifiable as missing members of -the batch, without substituting another revision or failing unrelated members. -The API's placeholder/refusal contract, warning attribution and protected-content -eligibility remain G12/G5/G26 in P02d-4. Stored labels stay immutable in the cache; -resolved labels are produced per call, so a locale is not needed in these keys. - -Two families contain all eligible revisions, including taxonomy bands. Loading -both sets together prevents N+1 work for lists and gives one coherent snapshot: - -| Family | Key via `CacheKey.ForTenant` | Stable `cache.name` | -|---|---|---| -| Content types | `{tenant_id}:customization:content-types:v{generation}` | `customization:content-types` | -| Taxonomies | `{tenant_id}:customization:taxonomies:v{generation}` | `customization:taxonomies` | - -The generation is a separate logical-name component passed to the existing -multi-part factory, never a hand-built separator. These templates replace -architecture 32's generation-embedded names and per-key taxonomy example in -this decision pass; the registry, metrics list and adapter mapping change together. -`TenantPageBlock` and its cache family remain Phase 04 work. - -- Require a resolved real tenant and an active, correctly announced/enlisted - transaction before every read, including cache hits. Keys come from that - trusted context, never from a request tenant id. RLS remains effective. -- Read the durable generation afresh for every batch; do not memoize or cache it. - A fully warm read uses one generation SELECT and no definition query. -- On any miss/fault, load generation and both eligible sets in one read-only SQL - statement snapshot on the same connection. Use parameterized, explicit tenant - predicates over Customization-owned tables only, following - [Database Standards § Raw SQL](../standards/05-database.md#raw-sql). - Use that statement's generation for both returned sets and cache fills; - discard earlier cache hits if the probe's generation changed. Cold/partial-hit - reads use at most two SELECT statements, independent of the number of pins. -- An absent counter with no definitions yields an empty projection; no built-in - values are synthesized. Do not cache the absent-counter result. A nonempty - definition set with no counter is a bounded configuration refusal and is not - cached. A present counter with empty sets is valid. -- Before a supported Customization store mutation or generation bump, mark this - scoped reader state dirty. Dirty or rollback-only scopes bypass cache get and - set entirely; they can read their saved database changes through the ambient - snapshot. The flag is sticky for the DI scope, avoiding transaction-object - reuse and nested-frame resets. Pending tracked changes are not auto-flushed by - the reader. A fresh scope regains normal caching. -- A clean scope can fill before its own read transaction commits because its - snapshot contains committed Customization data only. Rolling that read back - cannot publish speculative definitions. Fill safety must be proved for reads - before and after nested writers and for rollback/reissued generation values. -- Await each cache operation in the caller's lifetime; do not pass the ambient - loader to `GetOrSetAsync`, spawn work or parallelize module queries. Concurrent - cold callers may each load the bounded snapshot; this trades coalescing for - explicit transaction ownership without changing the cache port. -- Cache read/write faults degrade to database results with a bounded diagnostic; - caller cancellation propagates. Database errors are not cache misses. No - partial cache result may make a batch look complete. -- L1 TTL is 60 seconds; future L2 remains 15 minutes on Phase 11's trigger. - Generation reads bound definition freshness, while TTLs reclaim stranded keys. - Each instance's L1 follows the same durable counter; no event or L2 is required - for this family's invalidation correctness. - -The warm/cold statement counts are acceptance proofs, not measured latency. -The existing `< 1 ms` hit target must distinguish in-memory resolution from the -mandatory generation database probe. Record end-to-end timings and query plans -for the seeded fixture; do not claim a production p95 from a small local sample. -The family-wide load has a data-volume cost: it includes retained revisions, not -just the bounded requested pin list. Report rows/bytes with the measurements; -Phase 04's larger authoring workload re-evaluates that cost before expanding it. - -#### Typed settings and display fallback contract - -`ITenantSettingsAccessor` exposes typed registered reads through Tenancy contracts, -without a raw string-key/JSON export or a generic settings HTTP surface. The -production registration initially admits only the delivered `branding.theme` -palette. Reuse its grammar/contrast policy; return a typed four-color value and a -bounded absent/invalid outcome, never a partial palette or raw JSON. P02d-4 owns -safe public defaults/allowlisting; P02d-6 owns CSS injection. - -For a registered setting that permits organization scope, select tenant-wide and -exact current-organization rows explicitly, excluding soft-deleted rows; no -organization context selects tenant-wide only. Merge the organization value over -the tenant value as one whole value, without deep JSON/token merge. Invalid selected -values return a typed configuration refusal, without silently adopting another -scope. Synthetic test registrations prove this generic precedence; no speculative -production setting key or organization-branded palette is added. Even a future -`app.scope = 'tenant'` hatch cannot introduce sibling overrides into this selection. -The branding registration selects tenant-wide only in every organization context. - -The accessor opens no transaction, announces no context and caches neither values -nor per-scope snapshots; a supported write is visible to the next read under the -ambient database isolation. Audit and permissions matrices identify this internal -interface as unrouted, not as a new audited write. Any request used only by tests -stays test-only; any production MediatR query added must be classified Off. - -For G24, add a locale-carrying resolution result to `LocalizedText` and retain the -existing string-returning API as a compatible wrapper over the same algorithm. -First-authored means canonical locale keys ordered ordinally, as the shipped -`ImmutableSortedDictionary` implements; it does not mean JSON insertion order. -Do not widen `tr` to `tr-TR` or narrow the tenant/platform default candidates -implicitly. The platform `en` candidate is for display labels only; it authorizes -no content locale. The caller supplies the tenant default once for the batch. - -Pattern A rules concern optional display fields after an exact routable translation -has been found. They never locate another slug/translation/body. Required content -fields keep the authored translation; a nullable field with no permitted display -fallback remains absent. P02d-4 specifies field-level response applicability and -resolved-locale fields; P02d-6 emits the corresponding language attributes. - -#### Implementation steps and required review loop - -| Step | Scope and evidence | -|---|---| -| 1 | Locale-carrying fallback and uncached typed settings accessor. Unit fallback/grammar tests; app-role tenant/org/no-org selection, invalid/missing/soft-deleted settings, future tenant-scope hatch, read-after-write and no-cache proofs; register both API and Seeder roots | -| 2 | Batched exact-pin display contract and coherent ambient snapshot loader, initially uncached. Active/Deprecated versus Draft/deleted, mixed missing pins, tenant separation, empty/missing generation, no validation on read, resolved locales and coordinated generation/row race proofs | -| 3 | Generation cache families, scoped mutation bypass and metrics. Cold/warm counts, partial/cache-fault/cancellation behavior, cross-tenant warm alternation, nested write/read, rollback/reissue and independent-process freshness proofs; measured budgets, composition parity, full validation and packet closeout | - -Each step: implementation and focused validation, commit on `development`, fresh -independent security/correctness/contracts/documentation review, verify findings, -fix and commit; then a second fresh review round and verified fix commits before -the next step. Models/effort follow the complexity of each review surface. No -branch change. Packet completion updates the current-state docs and delivery -record; the PR is opened for maintainer review after all three steps pass. - -Relevant workflow skills are `add-integration-test`, `add-architecture-test`, -`update-glossary`, `standards-check`, `code-review`, `run-tests-locally` and -`commit-and-pr`. No new handler, entity or migration is planned; if implementation -requires one, dispatch its matching skill before the change. - -At acceptance, synchronize the Customization/Tenancy specs and matrices, glossary, -architecture 09/12/32, standards 08/10/15/20 and any catalogue rows for new guards. -Preserve existing Accepted ADR bodies and dated P02d-1/P02d-2 delivery history. -README, CLAUDE and roadmap index follow the actual decision/implementation state. -The full backend validation includes Release build, formatting, positive unit, -architecture, contract and both integration populations, with zero failed/skipped -cases. Documentation checks cover links/anchors, prose width and frozen delivery -history. No frontend behavior or public endpoint changes in this packet. - -#### Maintainer approval - -The maintainer approved the package together: - -1. G12/G22's ambient coherent-snapshot cache contract, batched exact pins, - two family keys, dirty-scope bypass and bounded database statement counts. -2. G23's uncached typed accessor, whole-value generic scope precedence - and explicitly tenant-wide branding registration. -3. G24's architecture-owned fallback, ordinal-first label terminal and - actual resolved-locale metadata while retaining exact content/URL admission. - -The three-step plan is part of the accepted package. This decision commit precedes -implementation, as required by the maintainer and -[implement-task Step 1](../../.claude/skills/implement-task/SKILL.md#step-1--scope-and-alignment). - -### Delivery record: P02d-3 - -**Complete, unmerged — 2026-10-02.** The accepted decision commit is `307bbcd`. - -#### Step 1: typed settings and locale resolution - -Implemented `ResolvedLocalizedText` and the compatible string wrapper, plus the -registered typed settings accessor in both composition roots. The sole production -registration is tenant-wide branding; synthetic tests prove generic whole-value -organization precedence. Explicit predicates, soft deletion and ambient admission -protect reads without a cache or raw configuration export. - -Release build: zero warnings/errors. Unit: 1584 passed; architecture: 184 passed; -integration: 241 passed (Docker/settings, writer/seed and Docker-free cases). -All three populations have zero failed/skipped; formatting and document checks pass. -Both independent review rounds passed; Step 2 follows. Public consumers/metadata -remain P02d-4/6. - -**Step 1 review round 1.** Two fresh GPT-5.5 high sessions reviewed -`307bbcd..9293202`. No verified Blocker/Major. Two verified Minor findings were -fixed: the localization illustration used a second stale fallback helper, and -both composition roots overstated feature flags as the only module-facing read. -The illustration now calls the shipped resolver; comments describe their own -read. No behavior changed. - -**Step 1 review round 2.** Two fresh GPT-5.5 xhigh sessions reviewed -`307bbcd..5848066`. Both approved the code; no verified Blocker/Major. -They independently identified the same stale delivery-status sentence above, -which is corrected in this closeout. Related current-state carriers now record -both rounds as passed. Documentation link/fragment and diff checks pass. - - -#### Step 2: batched coherent definition reads - -Implemented the immutable exact-pin display contract and ambient loader in both -composition roots. One SQL statement returns the generation, both eligible -families and taxonomy bands using their composite revision key. Individual -invalid/ineligible pins remain missing without revision substitution or dropping -valid neighbors. Actual display locales and authored descriptor order survive; -raw schemas stay inside the loader. The writer's purpose-aware reader is unchanged. - -The reader is deliberately uncached in this step. Every batch probes the durable -counter and loads the coherent statement snapshot; cache, dirty-scope behavior -and warm counts remain Step 3. The no-validation-on-read architecture guard walks -module helper dependencies and has planted direct/helper and clean controls. -Release build has zero warnings/errors; 1584 unit, 186 architecture and 21 focused -Docker integration cases pass with zero failures/skips. The real guard rejects a -planted validator dependency in the production snapshot helper, then passes after -restoration. Formatting and documentation checks pass. Both review rounds passed. -No cache implementation is claimed. - -**Step 2 review round 1.** Two fresh GPT-5.5 high sessions reviewed -`4829414..77197b9`. No verified code or SQL finding; two Minor document carriers -still treated G23 or Step 1 review as pending. Both are synchronized. The root's -additional guard check demonstrated a concrete validator adapter escaped the -interface-only ban; a planted concrete probe failed before the fix and passes -with the adapter census. The full architecture suite passes after the fix. -Round 1 is complete. - -**Step 2 review round 2.** Two fresh GPT-5.5 xhigh sessions reviewed -`4829414..94a84ab`. Both approved, with no verified findings. Current-state -carriers record both rounds as passed; link/fragment and wrapping checks pass. -Step 3 follows. No public consumer or cache implementation is claimed here. - - -#### Step 3: generation cache and read safety - -Implemented the two untranslated immutable definition families, awaited cache -get/load/set and stable metric names. Every read probes the durable generation; -a miss loads both families and generation from the same statement snapshot. -Supported stores and generation bumps mark a sticky scoped dirty flag before -mutation. Dirty and rollback-only reads bypass cache get/set entirely. Cache -fault diagnostics omit private exception/key payloads; cancellation and database -failures propagate with their own meaning. L1 is 60 seconds; L2 remains Phase 11. - -Release build: zero warnings/errors. Unit: 1586 passed; architecture: 186 passed; -focused Docker integration: 33 passed, including 23 projection/cache/composition -cases and ten publication-failure/concurrency cases. All have zero failures/skips. -The tests prove cold/warm statement counts, partial-hit publication coherence, -locale-neutral families, tenant alternation, independent L1 freshness, nested -write/read, store-save-before-bump, absorbed post-save refusal, rollback/reissued -keys, faults/cancellation, missing-counter admission and API/Seeder root parity. -An attempted test-only transaction reopen after rollback was correctly refused; -the proof uses a fresh scope, preserving ADR-0040's irreversible rollback-only rule. -The first full run passed unit, architecture, contract and Docker-free suites. -It exposed four missing scoped-state registrations in two legacy test fixtures; -those fixtures now supply the new state. A separate Seeder case encountered a -connection-open timeout before reaching its seeded race. All six focused fixture -and seed-race cases passed after the fix; the full Docker rerun was pending at -the implementation commit. No retry -or weakened -assertion was added. The review closeout below records completion of both rounds. - -**Local seeded measurement.** The executable -`Seeded_local_measurement_records_statement_plans_payload_volume_and_end_to_end_timings` -case uses a disposable PostgreSQL database through `learnstack_app`, the full -P02d-2 seed and 20 observations after warmup. Tenant `demo-english`, generation 8: -two content types, two taxonomies and nine bands. UTF-8 JSON payload from the -coherent statement is 1984 bytes; this measures wire JSON, not managed heap size. - -| End-to-end path | Minimum / median / maximum, ms | SELECT statements | -|---|---|---| -| Cold | 0.736 / 0.781 / 0.975 | 2 | -| Warm | 0.235 / 0.259 / 0.304 | 1 | -| Typed branding setting | 0.259 / 0.300 / 0.352 | 1; uncached | - -**Measurement erratum — 2026-10-03.** The historical “median” column above -reported upper medians, not the average of both middle observations. The routine -is corrected; the new sample and its limits are recorded in -[PR #24 review remediation](#pr-24-review-remediation-2026-10-03). - -`EXPLAIN (ANALYZE, BUFFERS, FORMAT JSON)` on the actual parameterized statements -uses `pk_customization_generations` for the probe and composite tenant/key/version -indexes for both families; bands use `ux_tenant_level_taxonomy_items_taxonomy_sort`. -Probe execution: 0.007 ms, two shared-buffer hits. Snapshot execution: 0.117 ms, -12 shared-buffer hits; both have zero shared-buffer reads. The snapshot's nested -band aggregate remains one SQL statement. These small local observations are not -production p95 evidence, do not isolate the in-memory `< 1 ms` target and do not -prove the cold `< 20 ms` or settings `< 5 ms` production budgets. Retained revision -volume, concurrent load and Phase 04's larger authoring workload require renewed -measurement before extending the families. No latency threshold is hard-coded -into the test. - - -**Step 3 review round 1.** Two fresh GPT-5.5 xhigh read-only sessions reviewed -`287318f..7ac197f`, covering transaction/cache safety and contracts/test evidence, -performance and corpus consistency. Both approved with no verified findings. -No source fix was necessary; Round 2 was pending at that milestone. - -**Complete backend verification after fixture repair.** Release build: zero -warnings/errors; formatting passes. All 2637 cases passed with zero failures/skips: -1586 unit, 186 architecture, one contract, 171 Docker-free integration and 693 -Docker integration. Positive TRX counters confirm `passed = executed = total` in -each suite; the full Docker rerun includes the earlier seed timeout case and -legacy fixture cases. Markdown links/fragments, diff checks and frozen P02d-1 -suffix checks pass. This evidence precedes the second independent review round; -it does not mark the packet merged. - - -**Step 3 review round 2 and packet closeout.** Two fresh GPT-5.5 xhigh read-only -sessions independently reviewed `287318f..5b50995`. No verified code, security, -transaction, cache, performance or test finding. One reviewer identified a Minor -status ambiguity in the phase's opening P02d-2 milestones, which still described -P02d-3 as next/open. Those sentences now explicitly describe their historical -moment; the current completion note and packet table name the accepted, delivered -P02d-3 state. Current-state carriers record both rounds as passed. The verified -fix changes documentation only; the complete backend execution evidence above -still applies to the unchanged source. Final links/fragments, formatting, diff -and architecture metadata checks pass. - -All three implementation steps and both review rounds per step are complete. -No new ADR, migration, HTTP endpoint, context setter or transaction mode was -required. P02d-3 is ready for PR review and remains unmerged. Phase 02d remains -in progress; P02d-4 owns the next decision pass for public eligibility, response -contracts, locale/cursor/cache rules, Off classification and read-only controls, -OpenAPI/SDK drift gates and request-level Education isolation. P02d-5/6 provide -SSR and rendering; P02d-7 provides the full-stack demonstration and exit proof. - - -**PR documentation correction — 2026-10-02.** After PR #24 opened, two CodeRabbit -Minor findings were verified against the current files: the Education spec still -named P02d-3 as next, and the roadmap index lacked a sentence terminator. Both -are corrected. Education now records P02d-3 complete/unmerged and P02d-4 next. -The fix changes no backend source or test; the 2637-case execution evidence -remains applicable. Final Markdown link/fragment and diff checks pass; required -CI is rechecked against the final documentation head before handoff. - - -#### PR #24 review remediation (2026-10-03) - -The maintainer supplied two independent reviews of `8edbb032..a317d389`. -Findings were verified against current source before changes; two additional -read-only agents checked documentation scope and runtime contract claims. -No new ADR, endpoint, migration or accepted decision is introduced. - -- **B1/M1/M14:** the validator guard now follows assembly-scoped references across - every production project, including Customization Domain/Contracts and core - helpers. Planted controls cover parameter/return/generic/event attributes, - wrapped generics, constraints, catches, lambdas and state machines. A narrowed - production census mutant fails on the planted Domain helper; the wrapped - generic control failed before the IL correction. Restored source passes. -- **M2:** the old probe barrier legitimately allowed a caller to warm the other. - The test now parks both independent snapshot loaders before either fills, - proving exactly two SELECTs and complete values per caller without flakiness. -- **M3–M8:** recoverable cache faults still fall back with bounded diagnostics; - fatal process exceptions propagate. Invalid setting-token values return a - bounded failure, settings admission checks its context's enlistment, branding - uses one canonical key, redundant cached revision fields are removed and - malformed-pin comments describe the actual per-revision behavior. Internal - definition refusals use neutral `lockey_invalid_value`, not a schema-extension - message. Malformed band labels omit their entire pin and preserve neighbors. -- **D1/D2/M10–M12:** editable Scope and current-state carriers now identify the - delivered locale/accessor/fallback work, planned organization branding and - generation-driven L1 consistency. Frozen P02d-1 accepted answers and delivery - record, and dated P02d-2 closeout/readiness, remain unchanged. - -**Disposition of remaining suggestions.** The accepted registry is an explicit -server-owned value, not an additive DI-registration API; its replacement rule is -now documented rather than inventing a new extension mechanism. The Phase 04 -`blocks-v{generation}` example is a legal, explicitly unimplemented target. -Public surface enforcement remains P02d-4's G30, not a delivered P02d-3 gate. -L2/serialization, cache-fault metrics and cold-load coalescing are not claimed by -this packet. Missing-counter detection intentionally includes Draft/deleted roots; -nonpositive generations remain invalid. Test-only non-null assertions fail loudly -if required measurement commands are absent; they do not hide a skipped proof. - -**Measurement correction.** The earlier table's historical “median” values were -upper medians (the eleventh of twenty observations). The routine now averages -both middle observations. A new twenty-observation sample after warmup, from -`learnstack_app` and the same 1984-byte fixture, records: - -| End-to-end path | Minimum / median / maximum, ms | SELECT statements | -|---|---|---| -| Cold | 0.598 / 0.738 / 0.973 | 2 | -| Warm | 0.184 / 0.209 / 0.275 | 1 | -| Typed branding setting | 0.190 / 0.235 / 0.292 | 1; uncached | - -Probe/snapshot execution is 0.008/0.146 ms with 2/12 shared-buffer hits and zero -reads. These observations still prove no production percentile or latency budget. -The measurement case asserts statement/data invariants, not unstable timings. - -**Local validation:** Release build has zero warnings/errors. Unit 1586, -architecture 187, contract 1, Docker-free integration 171 and Docker integration -697 pass: **2642 cases, zero failed or skipped**, with positive TRX execution -counters checked. Full format, Markdown links/fragments and diff checks pass. -Fresh correction review rounds follow the implementation commit; PR #24 remains -unmerged. - - -**Correction review round 1 — 2026-10-03.** Two fresh read-only reviewers, -GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed `a317d38..ab2a8b3` across -architecture/test proof and runtime/documentation. Both approved with no verified -findings. They ran no builds or tests; the primary executed the checks above. - -**Correction review round 2 — 2026-10-03.** Two new read-only reviewers using -the same models/effort independently reviewed that range with the lenses -exchanged. One Minor was identified and confirmed by both: Standards 20's new -“other families” sentence still generalized L2 to no-L2/uncached families. The verified -fix now links the -canonical per-family policy instead. No further finding or backend change. -Required CI and CodeRabbit passed on reviewed code head `ab2a8b3`; there are no -unresolved review threads. Links/fragments, metadata and diff checks pass after -the wording fix. Final documentation-head CI is rechecked before handoff. -PR #24 remains unmerged. - - -#### PR #24 depth and settings correction (2026-10-03) - -The maintainer's review of `8edbb032..825e4f57` identified two valid reader -defects. Both were verified against current source and reproduced through real -PostgreSQL as `learnstack_app` before the production correction. - -- **Snapshot depth:** the accepted raw JSON limit remains 64. The SQL snapshot - adds two containers around content-type schemas and four around taxonomy band - metadata. Explicit, bounded reader limits of 66 and 68 preserve that source - contract. No schema admission, publication, tenant predicate or cache policy - changes. -- **Settings parsing:** `JsonException` and `InvalidOperationException` from the - selected registration's parser return the existing bounded `validation_failed` - outcome. An invalid organization override never falls back to the tenant value. - Existing unsuccessful results remain refusals; cancellation and unrelated I/O - failures still propagate. - -Nine new database cases cover the two reported inputs, both raw-64 boundaries, -raw-65 write refusal, unrelated cold pins, warm reads, either partial-cache -direction, malformed setting roots/fields and non-shape parser failures. Before -the correction, the four depth and three shape cases fail at the expected parser; -the two non-shape controls pass. No Accepted ADR, migration or public API changes. - -**Local validation:** Release build has zero warnings/errors. Unit 1586, -architecture 187, contract 1, Docker-free integration 171 and Docker integration -706 pass: **2651 cases, zero failed or skipped**. Positive TRX execution counters -and all nine new regression outcomes are verified. Full format, Markdown -links/fragments and diff checks pass. Two fresh independent review rounds follow -the correction commit. PR #24 remains unmerged. - -### P02d-3 merge and closeout (2026-10-03) - -The maintainer merged [PR #24](https://github.com/HodeTech/LearnStack/pull/24). -GitHub records final PR head `79d1539c681e5188ae57fb3af47bdf6f5049990a` and merge -commit `d1a47369d82f8b6d91cb325f56d4c42382ec77b6`. The merge contains that head and -has the identical tree; the JSON-depth/settings correction above is included. - -- All five required checks pass on the - [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37111808188). - CodeRabbit's check succeeds and no review thread remains unresolved. The - [merge-commit CI run](https://github.com/HodeTech/LearnStack/actions/runs/37120044890) - also succeeds. Deferred OpenAPI/Lighthouse jobs are not executed proof. -- Local Release build, format and **2651 tests** pass with zero failures/skips: - 1586 unit, 187 architecture, 1 contract, 171 Docker-free integration and 706 - PostgreSQL integration. TRX verifies positive execution, including all nine new - boundary/parser cases. The historical delivery totals above remain unchanged. -- The packet delivers internal exact-pin display reads, coherent snapshots, - generation-keyed caching, typed tenant settings and locale-carrying fallback. - Its source dependencies and approved G12/G22/G23/internal-G24 parts are complete. - No public endpoint, authentication, browser renderer or marketplace ships here. - -**Next: P02d-4 — Public read API and contract checks.** Its implementation has not -started. The [packet gate table](#packets-and-decision-gates) owns the complete -prerequisite list. Its open decisions cover unresolved bands, public response and -branding projections, entitlement/attribution, canonical locale handling, the cursor, -site data/route set, HTTP cache policy, public-surface/read-only/audit fences, -eligible-row refusals and the OpenAPI/SDK drift checks. -Publication and content access remain governed by -[ADR-0050](../decisions/0050-publication-and-course-content-access.md); protected -content cannot become anonymous merely because a row is published. - -P02d-5 owns server rendering and the trusted transport; P02d-6 owns the public -renderer; P02d-7 owns the two-host demo, full-stack CI and phase exit. Phase 02d -therefore remains in progress. No new decision is accepted by this merge closeout. - -**Correction/closeout review round 1 — 2026-10-03.** Fresh read-only reviewers, -GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed the source correction -`825e4f57..79d1539`, its evidence and the closeout documents. Source review has no -findings. One Minor incomplete P02d-4 gate summary was verified and fixed by linking -the canonical packet prerequisites; both reviewers approve. They inspected the -stored execution evidence and ran no builds/tests. A second fresh round follows -the closeout commit. - -**Correction/closeout review round 2 — 2026-10-03.** Two fresh read-only -reviewers, GPT-6-astra and GPT-6.1-sol at xhigh effort, reviewed -`825e4f57..2276edf` across runtime correctness, isolation, parser boundaries, -regression evidence and document consistency. Both return Standards Pass and Code -Review Approve, with no actionable findings. They independently inspect the -stored TRX and live merge/check metadata; neither reruns builds/tests. The final -closeout documentation passes the corpus metadata, relative-link/fragment and -diff checks. Development remains the working branch; P02d-4 awaits its own -accepted decision package. - -### P02d-4 decision package (2026-10-03) - -**Status: Accepted — 2026-10-03.** The maintainer approved this complete package, -ADR-0052, its two dated clarifications, the four-step review plan and the exact -sixth required-check addition. This decision pass closes only the listed gate -parts; implementation starts after the decision/carrier commit. P02d-5/6/7 gates -remain open, and no endpoint, runtime proof or external setting is delivered by -acceptance. - -#### Verified premises and document review - -Reviewed against LearnStack `100bfefd6518df879fb9121499a70d7ceb6409ef`, on -`development`. P02d-1/2/3 are merged; production public controllers, a non-empty -OpenAPI snapshot and browser consumers do not exist yet. - -- Foundation: guidance/skills, principles, vision/MVP scope, glossary, roadmap and - ADR index; this phase's register, earlier delivery records, read contract, - criteria and risks. Proposed ADR-0049/Phase 09a do not govern this packet. -- Authority: ADR-0003/0010/0017/0033/0036/0040/0044, tenant resolution and audit - rules; API/gateway/isolation architecture and standards; factory, middleware, - ambient UoW, transaction/audit behaviors and request-surface guards. -- Content: ADR-0008/0043/0050/0051, Education/Tenancy/Customization specs and - matrices; locale/fallback, profile, exact-pin projection, settings and seed code; - frontend, accessibility, errors, database, cache and performance guidance. -- Contract: ADR-0023/0024/0035, SDK source/generator/lockfile, served OpenAPI - transformers and contract fixture; CI, CONTRIBUTING and architecture catalogue. -- Entitlement: ADR-0021/0034/0045, feature/license architecture, effective feature - evaluation and Null provider. Hub's contract pointer, key and Starter/Growth - plans were checked at `6adf93638e76114eda9c18a5095d0fe3c0fd43b1`, without edits. - -The read-only review found these implementation-relevant premises: - -- Normal organization context can come from a claim on a tenant host. Preserve - host provenance independently; never replace the reconciliation matrix. -- Host mapping admission does not check Tenant/Organization lifecycle. Tenancy - must own that check through an application contract. -- The existing locale writer port collapses several failures. Its contract stays - unchanged; a typed public configuration read distinguishes valid emptiness, - unavailable scope, unsupported locale and invalid stored configuration. -- RLS has no publication/access term. Eligible-body SQL must check the parent and - `public` policy itself before loading a body. -- Existing PublicSurface tests prove names and selected audit exclusions. They do - not yet prove actual methods, Off-only registration or controller write barriers. -- SDK factories returning `{}` stop compiling when generated paths become - non-empty. Their unused placeholder authority options must not enter v1. -- The pinned generator does not implement `x-extensible-enum` unknown branches. - New policy/state enums therefore use ADR-0024's closed-set default. -- Oasdiff defaults differ from ADR-0024. Explicit policy overrides and planted - changes are required; a fail level alone is insufficient. - -No build/test run is claimed by this document review. The implementation plan -below names the runtime proof, including real database HTTP requests and plans. - -Preparation used independent authority/UoW, locale/branding and contract/CI review -tracks (GPT-6-astra and GPT-6.1-sol, xhigh). Draft rechecks verified fixes for the -Education slug owner, required-field outcomes, cursor payload, sticky rollback-only -and the first-statement ordering exception. No remaining actionable finding in -those document scopes was reported. These are preparation reviews, not the two -implementation reviews required for each step below. - -The maintainer-supplied ADR review was checked against the current implementation -and Accepted contracts. ADR-0052 now states mandatory marked dispatch, limits the -runtime barrier to the enlisted transaction and names Registered guards. A focused -independent authority recheck found no remaining actionable issue. This preparation -record precedes maintainer approval; implementation proof remains pending. - -Baseline fact corrections are separate in `cdca081`: the glossary follows ADR-0045 -Amendment 3, and frontend architecture records the delivered P02d-2/3 theme -foundation. They do not form part of the public-read decision. - -Pre-acceptance preparation validation against `100bfefd`: all eight changed/new Markdown -files -pass local link and anchor checks (975 links, 331 fragments), changed-prose -wrapping and diff hygiene. -At that preparation boundary, frozen P02d-1 records and existing Accepted ADR -files remained unchanged. Acceptance appends only the approved dated clarifications. No -runtime/build proof is substituted for the implementation evidence below. - -#### P02d-4 accepted answers - -| Gate part | Accepted answer | Decision/detail owner | -|---|---|---| -| G5 unresolved band | No pin: null level. Missing exact vocabulary/band: bounded unavailable level, never rebound or raw key text | This contract and Education public-read spec | -| G6(b) | Canonicalize the shipped bounded locale grammar before membership, lookup and cursor binding; no trimming | Locale contract below and localization owners; URL redirects remain P02d-5 | -| G10 codec | Resource-local, keyless, forward keyset cursors for catalog and outline; bounded, versioned, context-bound, without confidentiality or MAC claims | Pagination contract below and API/Education detail; no SharedKernel codec or signing secret | -| G12 response | Exact Active/Deprecated pins, allowlisted text descriptors and bounded unavailable content; no raw body/schema or revision rebinding | Public DTO contract below, ADR-0050/0051 and module detail; page states remain P02d-6 | -| G16(f/g) public part | Whole typed four-color theme or null; baseline colors independent of entitlement; effective WhiteLabelBranding removes attribution only | Theme contract below, descriptor and architecture/standards detail; existing Hub pointer authority replaces a duplicated matching note | -| G24 response | Exact Pattern A content; Pattern B display labels report actual authored locale through `{value,locale}` | Locale/display contract below and localization owner; renderer language attributes remain P02d-6 | -| G25 | Host-resolved site bootstrap plus catalog/course/lesson reads; no edge tenant-ID lookup or route/query/body host/tenancy selector; effective host remains ADR-0036's input | ADR-0052 and frontend/infrastructure detail; three page consumers delivered P02d-6 | -| G26 route/response | Dedicated public prefix, four logical reads with explicit GET+HEAD, bounded pageable outline and closed DTO allowlists | Public contract below, API/module specs and OpenAPI; slug grammar remains the accepted P02d-1 contract | -| G27 | No-store on all public-prefix successes/errors; no ETag, Last-Modified or 304; internal definition cache remains independent | Cache contract below and API/performance detail; ADR-0039 validator derivation is unchanged | -| G28 | Mandatory PublicSurface requests through ISender, Off-only classification, GET+HEAD equality, structural bypass detection and READ ONLY on the enlisted ambient transaction | ADR-0052, ADR-0040 Amendment 8 below and Registered catalogue rows before code | -| G29 | Shared explicit eligibility; hidden Education outcomes use identical masked not_found; credentials never widen public access | Eligibility contract below, ADR-0050, ADR-0036 Amendment 8 and Education spec | -| G30 | Required single query locale on Education, validation_failed vs unsupported_locale 400; headers cannot choose content | Locale/error contract below and standards; trusted-hop header transport remains P02d-5 | -| G31 | One served/committed snapshot, policy-complete pinned diff check, typed SDK/drift proof and sixth required live check | Contract/CI plan below, standards, workflow and CONTRIBUTING; Lighthouse remains G44 | - -G5/G12/G16 renderer parts, G6(c), G30 header transport and G32–G45 retain their -named later packet boundaries. No marketplace or enrollment gate is reopened. - -#### Public routes and DTO contract - -All paths are relative to `/api/v1/public`. Each explicitly supports GET and -HEAD: **four logical read contracts, eight method/path OpenAPI operations**. -Every institution public-data endpoint dispatches a `[PublicSurface]` MediatR -request through `ISender`; its data access uses the enlisted read-only ambient -transaction. ADR-0052 owns that mandatory boundary, its bypass limits and proposed -guard names. Structural controls detect bypasses; real HTTP/database tests prove -the dispatched runtime path. No direct persistence path through a controller, -minimal API handler or helper is admitted. - -| Path | Query parameters | Response | -|---|---|---| -| `/site` | None | `PublicSite` | -| `/courses` | Required `locale`; optional `cursor`, `limit` | Catalog page | -| `/courses/{slug}` | Required `locale`; optional `lessonCursor`, `lessonLimit` | Course detail and optional outline page | -| `/courses/{slug}/lessons/{lessonSlug}` | Required `locale` | Lesson detail | - -No host, tenant, organization, actor, filter, search or sort selector is published -in route, query or body. The effective host still follows ADR-0036's direct-request -and authenticated trusted-hop rules. -Unknown query parameters and repeated single-valued parameters are rejected with -bounded `400 validation_failed`. Slugs retain the accepted -[Education slug grammar](../standards/08-localization.md#education-slug-grammar): -1–160 characters, with UUID N/D spellings excluded. An invalid slug returns -`400 validation_failed` naming `slug` or `lessonSlug`; do not synthesize a slug. - -DTOs are purpose-built public contracts; never reuse seed or internal projection -DTOs. Names below also specify the serialized allowlist: - -- `PublicSite`: `displayName` (Tenant's display name), `enabledLocales`, - `defaultLocale`, `theme`, `showPlatformAttribution`. A successful bootstrap has - at least one enabled locale and exactly one enabled default. Locale order uses - configured sort then canonical tag as a deterministic tie-breaker. -- `theme`: either null or exactly `primary`, `background`, `foreground`, `muted` - from the validated typed whole value. Null means the renderer's safe CSS - defaults; do not copy another palette into backend DTO code. -- Course summary: `slug`, `title`, nullable `summary`, `contentAccess`, nullable - `level`. No root identifier, timestamp, version, scope or authoring pin is needed. -- Level: `{state:"ready",label:{value,locale}}` or - `{state:"unavailable",label:null}`. An absent optional pin gives `level:null`. -- Catalog: `{locale,items:[course summary],pageInfo}`. Use the shared PageInfo - field vocabulary, without pretending backward navigation exists. -- Course detail: `{locale,course,alternates,lessons}`. Course is the summary above. - Alternate items contain only `{locale,slug}`. Restricted courses return - `lessons:null`, with no count, title, slug, order, descriptor or truncation flag. -- Public-course outline: `{items:[{slug,title,sort}],pageInfo}`. It contains no - body, definition or count. A public course without eligible lessons has a real - empty page, distinct from restricted `lessons:null`. -- Lesson detail: `{locale,course:{slug,title},lesson:{slug,title},alternates,content}`. - Alternate items contain `{locale,courseSlug,lessonSlug}`; both translations must - exist in that enabled locale. Exclude the current locale and order consistently. -- Ready content: `{state:"ready",rendererKey,label:{value,locale},fields}`. - `fields` are descriptor-ordered `{name,label:{value,locale},value}` plain strings - from the selected supported text-card profile. Missing optional fields are - omitted; unknown body properties are omitted. Missing required fields, - non-object stored body and selected non-string values make the whole content - unavailable. Derive requiredness as internal presentation metadata from the - admitted schema's `required` list; carry it through Customization's field - projection without exposing a public required flag or evaluating JSON Schema. - No coercion or schema evaluation occurs on read. -- Unavailable content: `{state:"unavailable"}`. Missing/deleted/Draft exact pins, - malformed definitions, unsupported renderer/profile, zero presentation fields - or invalid selected values expose neither body nor descriptor, and never use - another revision. Record bounded operator diagnostics without payload values. - -Policy values `public`/`enrollment_required` and state values `ready`/`unavailable` -are closed enums. Additions and removals are breaking under ADR-0024. `rendererKey` -is a string; `default-card` is the currently supported value, not a closed future -renderer registry. Rendering an unknown key remains G41's bounded fallback. - -Recursively exclude tenant/organization/actor IDs, root IDs/versions, audit columns, -settings keys/raw JSON, JSON Schema, arbitrary body objects, taxonomy metadata, -internal pin/revision/status/generation data and unpublished translations. A cursor -is the separately documented protocol exception: it contains seek identifiers, -not exposed authority or a secrecy guarantee. - -#### Host authority, eligibility and public errors - -The normal resolved context and host ceiling both apply. A nullable immutable -`HostScope` contains host TenantId and OrganizationId, constructed only by -`TenantContextFactory` from the attempt's existing host signals after its current -agreement/membership gates. Claim-only, ambient and unresolved contexts have none. - -Every public request requires a real matching host scope. Explicit host predicates -intersect with normal EF filters and RLS: tenant host means tenant-wide rows only; -organization host means tenant-wide plus that organization's rows. An org claim on -a tenant host cannot expose org content; a platform-host claim cannot turn that -host into an institution public site. Keep the factory independent of routing. - -The API hashes the normalized effective host from `HostClassification` for cursor -binding. Only the digest enters the query's pagination input. Do not put the host -string into the resolution attempt/context, public response or retained logs. - -Tenancy's typed internal configuration contract checks Tenant and, where present, -Organization under the current announced scope, on the same connection. Serve only -nondeleted Trial/Active tenants and nondeleted Active organizations. Missing, -Suspended, Archived or deleted scope gives generic `404 not_found`. This explicitly -selects Suspended behavior for public content; it is not an existing resolver check. - -Eligible course marketing requires matching scope, published/nondeleted course, -enabled canonical locale and its exact translation. Eligible lessons additionally -require published/nondeleted child, URL-parent membership, exact translation and -parent `content_access = public` before inventory, body or descriptor reads. -The protected-body SELECT includes all those parent/access conditions itself. -READ COMMITTED does not promise linearizable revocation across later statements. - -Nonexistent, draft/deleted, wrong-parent, untranslated, sibling-org, other-tenant -and restricted lesson outcomes share one `not_found` body after masking dynamic -`instance`/`correlationId`. Hidden course outcomes likewise match a nowhere slug. -Credentials do not produce grants or unlock this anonymous contract. Preserve -existing resolver outcomes: platform host retains HTTP 404 `tenant_mismatch`, -unknown host HTTP 404 `not_found`, and assertion/claim failures are not bypassed. - -Valid no-locale/all-disabled configuration remains representable internally. It -returns bootstrap `404 not_found` because no navigable public site is configured; -every well-formed Education locale is unsupported. Do not synthesize `en`. -Malformed stored tags or enabled locales without exactly one enabled default give -generic `503 dependency_unavailable` plus bounded internal diagnostics. Missing or -invalid theme alone yields `theme:null`, not a site failure. Unexpected database -faults retain the existing exception path; do not swallow cancellation or all errors. - -Success is 200; business/input errors publish 400/404/503 as applicable. Document -framework 405/429 and the existing unexpected 500 path in the shared Problem -Details component. HEAD has identical admission, status and applicable headers -with no response body, including errors. Tests observe the documented HTTP outcomes. - -#### Locale and display applicability - -Site bootstrap takes no locale. Each Education read requires exactly one `locale` -query value. Missing, empty, repeated, malformed or longer-than-35 values return -`400 validation_failed` with `errors.locale`, before opening the ambient read -transaction. Do not trim whitespace or extend the accepted LocaleTag grammar. -Canonicalize valid case variants before membership, SQL and cursor binding. - -Well-formed absent/disabled tags return uniform `400 unsupported_locale`, including -when historical translations remain stored. Enabled but untranslated gives an -empty catalog, detail 404 and omitted outline/alternate entries. Neither `X-Locale` -nor `Accept-Language` selects content. P02d-5 owns how its transport sets headers. - -Pattern A title, summary, slug and body are exact requested-locale data; a null -summary remains null. Pattern B labels use the existing single-owner chain in -[Localization § Fallback Rules](../architecture/12-localization.md#fallback-rules), -and carry the actual authored locale. A fallback label never authorizes reading -another content translation. Resolve the validated tenant default once per request -and reuse it in batched definition reads; do not evaluate JSON Schema on read. - -#### Catalog and outline continuation - -Use resource-local keyless codecs, not a new SharedKernel codec or signing-key -lifecycle. Catalog order is `(created_at ASC,id ASC)`; outline order is -`(sort ASC,id ASC)`, matching the existing lesson invariant. Seek/fetch `limit+1` -eligible rows using PostgreSQL timestamp precision and UUID ordering. - -Both page sizes default to 20, reject malformed/non-positive/repeated input and -clamp above 100. `pageInfo` is `{nextCursor,previousCursor:null,hasNext, -hasPrevious:false}`; nextCursor exists only when an additional eligible row exists. -Outline continuation stays on the course endpoint, so every lesson is reachable. -Restricted courses never produce an outline cursor or touch lesson inventory. - -Codec version is **1**. Encode UTF-8 JSON using canonical unpadded base64url, with -at most 1024 encoded ASCII characters and 768 decoded bytes; no compression. -Catalog payload has exactly `{v,scope,createdAt,id}`; outline payload has exactly -`{v,scope,parent,sort,id}`. UUIDs use canonical lowercase D format and are nonempty; -outline sort is a nonnegative Int32. `createdAt` is a representable UTC timestamp -with exactly six fractional digits (`yyyy-MM-dd'T'HH:mm:ss.ffffff'Z'`), preserving -PostgreSQL microsecond precision. No token logs or input reflection. - -`scope` is lowercase hex SHA-256 of a UTF-8 JSON array in this exact component -order: `[1,endpoint,hostDigest,tenantUuid,organizationUuidOrNull,locale,order]`. -UUIDs/locale are canonical, null remains JSON null, endpoint is `catalog` or -`course-outline`, and order is `created_at:id:asc` or `sort:id:asc`. `hostDigest` is -SHA-256 of UTF-8 normalized effective host, represented as lowercase hex. Tagged -components avoid concatenation ambiguity. Both scopes come from the preserved -host ceiling, not a claim-selected organization. Outline `parent` must match the -resolved eligible course UUID. Page size is excluded so it can change. Decoded -identifiers are continuation data, never selectors. - -Reject noncanonical encoding, excessive length, duplicate/unexpected fields, -wrong types, unknown version, invalid UTC timestamp/order/UUID, truncated data and -fingerprint mismatch with bounded `400 validation_failed` naming `cursor` or -`lessonCursor`, never reflecting the token. Validate syntax and known host/locale/ -endpoint binding before transaction entry; check outline parent binding after the -eligible parent resolves, without loading any body or outline before refusal. - -The fingerprint is not authenticated. A deliberately edited, otherwise valid -anchor may skip/repeat within the requesting host's independently eligible set; -it cannot enlarge it. Do not promise tamper rejection, confidentiality or stable -snapshot pagination. No anchor-row lookup is required. Earlier additions are not -rediscovered, later eligible additions can appear and deletes can shorten a page. - -#### Branding, entitlement and cache boundary - -Resolve theme through the existing typed accessor; it remains tenant-wide even on -an organization host. Null/invalid whole theme uses `theme:null`, never partial -colors. P02d-6 owns safe CSS injection and the existing frontend default palette. - -Baseline validated colors apply regardless of plan. Derive only -`showPlatformAttribution = !IFeatureFlags.IsEnabledAsync(WhiteLabelBranding)`; -do not expose flags, inspect provider storage or contact Hub directly. Null provider -grants hide attribution; false/omitted/degraded effective grants show it. Existing -authoring and provider/overlay failure contracts are unchanged. - -G16's vehicle is explicitly reconciled with Hub's pointer-only contract policy: -core owns the first-consumer meaning; Hub's existing contract pointer is the -matching authority, not a second duplicated rule. Its shipped key/boolean and -Starter/Growth values need no wire or endpoint change. No sibling branch is edited. -The observed Hub degraded-summary drift is a separate existing documentation -correction owned by Hub before Phase 02c's real provider consumer, under its own -branch authorization; it neither changes current Null behavior nor blocks P4. - -Set `Cache-Control: no-store` at the public-prefix boundary before middleware can -short-circuit, including 200/400/404/405/429/503 and existing exception responses. -Do not emit ETag or Last-Modified, expose versions or honor If-None-Match/304. -No Education response or site bootstrap cache is introduced. Internal generation -cache remains independent; it cannot decide publication, access or locale admission. -API/performance standards need a scoped exception, without changing write validators. - -#### Accepted ADR clarifications - -The maintainer approved the following clarifications with ADR-0052 on 2026-10-03. -They are appended to ADR-0036 and ADR-0040; existing bodies remain unchanged. -ADR-0052 owns the new public decision and bounded read-only setup-order exception; -the amendments disclose its composition rather than authorizing it independently. - -**ADR-0036, Amendment 8 — public host provenance (2026-10-03).** -The Decision and reconciliation matrix are unchanged. P02d-4 needs to distinguish -the host's public scope from a valid context narrowed/selected by claims. Under -ADR-0052, `ITenantContext.HostScope` is nullable and immutable. Only -`TenantContextFactory` constructs it from existing `HostTenantId` and -`HostOrganizationId`, after all existing reconciliation/membership checks succeed. -Claim-only, unresolved and ambient contexts carry null. No host string, route or -new lookup enters `TenantResolutionAttempt`; no context-accessor writer or SQL -setter is added. Public query admission requires real matching host scope and -explicit host predicates intersect with normal filters/RLS. Row 7 cannot expose -organization content through a tenant host; row 14 has no institution host scope. -Claims/assertions retain their refusals and never widen the anonymous response. -Carrier updates: API/security standards, context/gateway/isolation architecture, -frontend standards, Education/Tenancy public specs, glossary and catalogue; the -phase package owns the concrete public route/eligibility contract. - -**ADR-0040, Amendment 8 — read-only public frames (2026-10-03).** -Connection/transaction ownership, shared module contexts, the tenant setter set -and default writable behavior are unchanged. ADR-0052 authorizes a bounded -public-only exception to the Decision sketch's first-statement ordering; this -amendment does not authorize it independently. ADR-0052 adds -explicit ReadOnly/ReadWrite intent to `BeginTransactionAsync`; existing callers -remain ReadWrite by default. TransactionBehavior chooses ReadOnly for PublicSurface -requests before dispatch. A physical ReadOnly owner opens READ COMMITTED, executes -and awaits `SET TRANSACTION READ ONLY`, then returns its owner frame. The existing -tenant/organization announcement follows before any data SQL or handler dispatch; -that mode-control statement is its only permitted predecessor. Default writers -retain first-statement tenant announcement. Begin cleans up its partial transaction -on setup failure/cancellation, marks rollback-only and rethrows before returning a -frame; it cannot rely on TransactionBehavior's later cleanup try block. -A same-mode join uses existing frame ownership. A -mixed-mode join is refused before invoking the inner handler and marks the unit -rollback-only even if an outer caller absorbs it. It never promotes/demotes the -existing transaction or opens a second connection. Direct application-contract -reads inherit the ambient mode. READ COMMITTED stays unchanged. Mode belongs to -one physical transaction and resets on completion/rollback/disposal; no pooled -session state leaks. This never clears sticky rollback-only poisoning: successful -read-only commit permits a later writer on the same reusable unit; owner rollback, -cancellation or mixed-mode failure requires a fresh unit/scope. Verify pooled -connection mode reset separately. Normal Off reads write no audit row; independent -rejection audits retain their sanctioned path. PostgreSQL app-role proofs and -planted guards cover EF/SQL write attempts, both nesting directions, cancellation, -rollback and a later writable transaction on a valid unit, with poisoned-unit -refusal controls. -Carrier updates: backend/database/security standards, request-pipeline/isolation -architecture, module specs and catalogue. - -#### OpenAPI, SDK and required-check plan - -Use `backend/openapi/v1.json` as the only committed v1 snapshot. Contract tests -compare it with the production composition root's served `/openapi/v1.json`, without -test probe controllers. Canonical comparison may ignore object-key order, not -arrays, schemas, paths or response content. Assert all eight operations as a -non-empty positive control, closed DTO reachability and complete Problem Details. - -Pin oasdiff **v1.33.0**, commit `322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf`, -Apache-2.0. Verify the fixed Linux AMD64 release archive before extraction/execution -against SHA-256 `43a4e328e2d13ba1552d760aa68d2485c75c5621f309f6ff64ae895188345247`, -then assert its version; no latest-tag or unpinned installer fallback. Sources: -[pinned licence](https://github.com/oasdiff/oasdiff/blob/322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf/LICENSE), -[archive/checksums](https://github.com/oasdiff/oasdiff/releases/download/v1.33.0/checksums.txt). -Use `breaking --fail-on WARN` with an explicit checked-in severity file -for ADR-0024; promote request-field removals, optional/required response-field -removals and response enum removals/additions as policy requires. Commit fixtures -for every representable ADR-0024 breaking row and nonbreaking controls; any tool -gap needs a deterministic companion check, not a silently excluded policy row. -Validator/status behavior absent from OpenAPI needs named runtime tests. Official -[severity configuration](https://github.com/oasdiff/oasdiff/blob/v1.33.0/docs/BREAKING-CHANGES.md#customizing-severity-levels) -and [release](https://github.com/oasdiff/oasdiff/releases/tag/v1.33.0) are supporting -sources, not claims that the repository has installed or run it. - -At minimum set these exact checks to `err`: `request-property-removed`, -`response-optional-property-removed`, `response-required-property-removed`, -`response-property-enum-value-added`, `response-property-enum-value-removed` and -`response-mediatype-enum-value-removed`. Pinned -[check registrations](https://github.com/oasdiff/oasdiff/blob/322d7ae815e5fb80f415bd4e8ef16d4b30cd8bdf/checker/rules.go) -make the optional field and enum-removal overrides necessary. Existing extensible -enum policy is not automatically supported by this generator/tool pair; when an -open response enum first ships, its consumer/compatibility companions must close -that gap. This packet's public response enums remain closed. - -Diff PR base SHA's snapshot against head. Push uses the push-before SHA; manual -runs use an explicit base ref. A first-baseline exception is permitted only when -the verified base has no v1 operations and no committed snapshot. Fetch/read errors, -missing snapshots after bootstrap or deleted head snapshots fail. Failure artifacts -include both specs, SHAs, tool/version/policy and readable/machine reports. - -Regenerate from that file through `LEARNSTACK_OPENAPI`; keep the lockfile's -openapi-typescript 7.13.0. The SDK root exports generated types only. Replace the -unused `/server` stub with a thin typed public GET transport accepting an injected -Fetch-compatible transport; operation/request/response types derive from generation. -The supplied transport resolves relative SDK URLs; there is no global-fetch default -or implied working server hop. Parse errors as unknown, validate Problem Details -and project them into the existing closed AppError union including its unknown -branch, ignoring unrecognized extension members rather than trusting an unchecked -cast. Fake-transport tests cover the four-route inventory, encoded parameters, -absence of authority headers, success/errors, unknown codes and malformed bodies. -Remove unused `/client` factory/export. Do not add a runtime client library, tenant -ID option, header authority, hop secret or frontend request-header lookup here. -G35 selects the trusted server adapter/options in P02d-5. - -Provide four logical GET wrappers and a typed success/Problem Details envelope; -malformed JSON, transport failures and caller cancellation stay distinct from a -valid API error. Tests cover exact URL/query construction and generated typing. -P4 proves SDK operation coverage and drift; P5 supplies the first server consumer; -P6 proves every logical GET has a public-page consumer. HEAD is the HTTP companion, -not an invented browser JSON consumer. The phase's consumer criterion follows -this split. - -Replace the deferred CI placeholder with always-running **`openapi diff`**, removing -ENABLE_OPENAPI_DIFF and its deferred suffix. Add snapshot-based SDK regeneration/ -scoped generated-file drift to the required frontend job. Keep Lighthouse under G44. -After a real job runs, add `openapi diff` with GitHub Actions attribution (15368) to -live `main` protection, preserving the five current checks, strict=true and all -other settings. The maintainer approved this exact external setting change on -2026-10-03; -verify it by API read-back and record the date/list, without claiming an edit here. - -#### Implementation steps and two-round review loop - -First commit the Accepted decision records and carrier updates. Then implement on -`development`, without another branch or worktree: - -1. **Authority and read-only foundation.** Factory host provenance, public admission, - explicit UoW mode/setup/nesting/reset, pipeline selection and non-vacuous - structural companions. Validate factory/matrix controls, existing writer/audit - behavior and app-role READ ONLY EF/SQL refusal with writable/mixed-mode controls, - mode active when Begin returns and setup failure/cancellation cleanup. -2. **Public site and HTTP boundary.** Tenancy configuration contract, live-scope and - locale/configuration decisions, typed theme/effective attribution, site endpoint, - explicit HEAD, no-store and shared Problem Details. Validate production middleware - plus real database, safe fallback and swapped-provider controls. -3. **Education reads and continuation.** Central eligibility, three queries, exact - translations, catalog/outline cursors, descriptor-ordered lesson projection and - alternates. Add internal requiredness to Customization presentation fields; - prove optional omission, required absence and non-object/non-string refusal - without a schema validator. Validate all leakage/masking/locale/pagination cases - with positive controls; inspect real app-role EXPLAIN plans for consumer query - shapes and record representative cold/warm measurements with their limits. -4. **Contract/SDK/CI and closeout.** Snapshot equality/allowlist, breaking-policy - mutation fixtures, generated types/typed transport/drift, CI activation and - approved protection update; final documentation and required PR evidence. - -For **each** step: implement and commit; first independent multi-dimensional agent -review; verify findings, fix and commit; second fresh review; verify/fix/commit. -No empty fix commits. Choose model/effort by risk: authority, UoW, isolation and -policy reviews use the strongest available deep reviewer; contract, tests and -corpus get an independent implementation/docs reviewer. Re-review material fixes. -Proceed automatically to the next step unless a new approval boundary blocks it. - -Required packet evidence includes Release build/format, unit/architecture/contract, -Docker-free and Docker integration with no empty selection/skips; frontend checks; -snapshot regeneration/SDK drift; policy companions; changed-document link/anchor -checks and diff hygiene. Record actual counts/results only after execution. - -The behavioral inventory includes lifecycle/no-locale/invalid-default outcomes; -locale casing, 35/36 bounds, whitespace/newlines, repeated/missing/disabled values -and header invariance; exact fallback locale; parent/child policy/publication/ -deletion and cross-host/org masking; zero protected reader invocations; full catalog -and outline walks/ties/deleted anchors/restart/scope mismatch; GET/HEAD/error/no-store -and If-None-Match; zero normal audit writes; warm-cache policy controls; served -snapshot extra/removed operations and recursive forbidden fields. Use distinct -allowlisted fixture values when public IDs are intentionally absent. - -#### Acceptance carrier actions and authorization - -Acceptance updates the following owners together, before code: - -- ADR-0052/index and approved dated ADR-0036/0040 amendments; this register/status, - packet-specific criteria and Registered catalogue obligations. Preserve frozen - P02d-1/2/3 decisions and delivery history. -- API, backend, database, security, frontend, localization, error, performance, - infrastructure and architecture-test standards/index; derive changed nontrivial - rules from the accepted ADRs. Distinguish Registered proofs from implemented ones. -- Frontend, request pipeline, tenant isolation, localization, gateway, feature flags, - hybrid licence and customization architecture; replace public edge-ID lookup, - clarify query locale, exact display applicability, attribution and no-store. -- Education/Tenancy/Customization spec, audit/permission matrices and glossary; - public descriptors are separate from internal read/seed DTOs. Fix stale - ADR-0048-only access language and premature public-ID/consumer criteria. -- CI/CONTRIBUTING/SDK detail: record approved activation and later execution; do not - label a proposed job, transport, endpoint or required setting delivered. - -Maintainer approval covers this package, ADR-0052, the two appended clarifications, -four-step implementation/review plan and the exact sixth-check protection addition. -The gates listed above are now Accepted; later packet parts retain their owners. No new -schema, infrastructure adapter, -marketplace direction, protected learner access or renderer decision is implied. - -**Acceptance validation — 2026-10-03.** Against `cdca081`, 39 changed/new Markdown -files pass 2576 local-link and 538 fragment checks. Frozen P02d-1/2/3 decisions and -delivery records are unchanged; the existing ADR-0036/0040 bodies are byte-identical -after removing the two appended clarifications. Five CorpusConsistencyTests pass -in Release with zero failures/skips; diff hygiene is clean. Independent security, -locale/branding and contract/corpus checks found no decision change needed; -verified wording/table findings were corrected. This is acceptance validation, -not implementation delivery or either review round of an implementation step. - -#### P02d-4 Step 1: authority and read-only foundation - -**Implementation — 2026-10-03.** Factory-only immutable HostScope retains the -host tenant/organization independently of claim-selected scope. Public admission -requires matching real provenance; existing unmarked origins and resolution -inputs retain their contract. An explicit transaction mode defaults existing -callers to ReadWrite. PublicSurface selects ReadOnly before dispatch; mode setup -completes before Begin returns. Same-mode joins preserve ownership; mixed-mode -attempts poison the outer unit before handler invocation. Partial setup failure -or cancellation cleans up immediately. Physical completion resets mode, while -rollback-only remains sticky and successful read-only completion permits reuse. - -The HostScope construction guard has mutable/public/second-site planted controls. -Real app-role PostgreSQL cases exercise EF/raw SQL refusal, identical writable -controls, same/mixed-mode nesting, setup faults/cancellation and successful/fresh -scope reuse. The existing HTTP isolation probe now proves the read-only barrier; -a separate writable frame retains WITH CHECK refusal and an own-tenant positive -control. No production endpoint, eligibility reader or public response is shipped -in this step; Steps 2–4 retain those obligations. - -**Pre-review verification.** Release build has zero warnings/errors. All 2672 -.NET tests pass with zero failures/skips: 1598 unit, 189 architecture, one contract, -171 Docker-free integration and 713 Docker integration. Format and changed-document -link/anchor checks pass. At this pre-review boundary both review rounds were -pending; completion is recorded below. - -**Review round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers -examined `f79e4a4..77b13f5`. Neither found a production defect or Blocker/Major. -Verified Minor findings: two editable current-state carriers still described -Step 1 as pending, and the driver-log fault injection ran before Npgsql sent BEGIN. -Carrier wording now separates delivered foundations from Steps 2–4. The original -pre-send cases remain, with corrected wording; two additional cases observe server -read-only mode and inject fault/cancellation from the driver's safe ReaderClosed -callback before Begin returns. They assert cleanup before DI-scope disposal and -sticky poisoned-unit refusal. The pinned-driver reflection seam exists only in -tests and fails loudly if its members change. No production test hook is added. - -**Round 1 fix verification.** All nine transaction-mode cases pass with zero -failures/skips, including both post-server setup failures. Five corpus consistency -cases pass. A clean CI=true rebuild (rather than an incremental cached build) -exposed CA1852 on the deliberately unsealed planted offender. Its narrow, explained -test-only suppression preserves that offender; the clean Release rebuild then -passes with zero warnings/errors. Production code is unchanged by these fixes. - -**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers -examined `f79e4a4..1020611`. No Blocker/Major was found. A double-marked request -could pass unresolved admission without HostScope; no production request uses -that combination. PublicSurface now refuses that combination under unresolved -context, with a planted unit control, preserving ordinary provisioning and the -existing tenant_mismatch refusal. The HTTP isolation class summary now separates -its read-only refusal from the writable WITH CHECK controls. All 21 focused -admission unit cases pass with zero failures/skips. The contracts reviewer also -independently ran a clean Release build (zero warnings/errors), 189 architecture, -63 focused units, nine mode cases and the changed HTTP control on `1020611`, all -passing with zero failures/skips. A fresh GPT-6-astra xhigh focused review of -`1020611..248b5e3` found -no remaining actionable issue. Step 1 and both review rounds are complete. - -#### P02d-4 Step 2: public site bootstrap - -**Implementation — 2026-10-03.** The internal typed Tenancy configuration port -checks live tenant/mapped-organization lifecycle on the announced/enlisted -read-only transaction. Valid locale emptiness stays distinct from invalid stored -configuration. Site GET/HEAD dispatch a marked Off query through ISender; they -project only the approved display name, sorted enabled locales, default locale, -whole validated theme or null and effective attribution. No caller scope selector, -new permission, generic settings route or palette is added. - -An early public-prefix response policy covers successes and all errors, including -routing, rate limiting and exception handling: no-store, no validators and no HEAD -body. Structural Off, independent action dispatch/method and transitive controller -persistence guards include offending and clean controls. A production-composition -HTTP fixture uses real writer seeds and the application database role; it observes -server read-only mode and non-bypass role before each configuration read. Cases -cover lifecycle withdrawal after warm host resolution, locale order/emptiness, -invalid configuration, uncached whole-theme/null, attribution provider outcomes, -query refusal before data, no normal audit rows, exact endpoint inventory and -GET/HEAD error/no-store behavior. Education and contract/SDK/CI remain Steps 3–4. - -**Pre-review verification.** A clean CI=true Release build with --no-incremental -passes with zero warnings/errors. All 2710 .NET cases pass with zero failures/skips: -1599 unit, 195 architecture, one contract, 171 Docker-free integration and 744 Docker -integration. TRX counters retain each suite separately and agree with the runner. -After strengthening token/case/action-suffix route discovery and its controls, the -clean build and all 195 architecture cases pass again; all 29 focused site HTTP -cases pass. Formatting, diff hygiene and 1540 local links/400 fragments across the -15 affected Markdown files pass. Existing ADR-0052 text and frozen P02d-1–3 records -remain intact. At this implementation boundary both review rounds were pending. - -**Review round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers -confirm the production site behavior and identify two structural guard gaps. -The dispatch check independently found a marked construction and a Send call; -it now verifies the actual directly constructed argument, permits exactly one -Send and refuses unverifiable origins. Discarded marked, mixed-send and variable -controls fail. The persistence walk now follows production implementations of -reachable interfaces and abstract helpers; planted independent-connection -helpers fail through both shapes. The testing standard's endpoint status is -aligned. The clean Release build has zero warnings/errors; all six focused -public guard cases pass. A fresh second round follows the correction commit. - -**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers find no -production site defect. Their probes expose generic helper references that -compare closed instances against open definition keys, and a clean direct Send -followed by an unmarked helper Send. The walk normalizes generic definitions and -refuses sender acquisition in reachable non-controller helpers. Safe-return -interface and abstract probes now isolate implementation traversal, including -closed generic and clean controls. The helper-Send regression fails before the -fix and passes afterward. Generated action state machines remain part of their -owner instead of separate sender-acquiring helpers; an initial full-suite run -caught that false positive and the subsequent correction restores the clean -production control. Lambda extra-Send controls also fail. Current theme and -performance carriers record Step 2 delivery. A fresh focused review checks these -final corrections. - -**Focused fix verification.** The fresh review identifies an additional private -controller method that sends after the clean marked action. A controller-wide -Send census now equals the approved HTTP action count, while each action still -proves its actual marked argument. A planted private helper fails the control. -The follow-up control also gives the private helper a GET attribute: private -methods are not MVC actions and cannot offset an extra Send. This regression -fails before the public-method filter and passes afterward. A fresh GPT-6.1-sol -xhigh reviewer approves `6b8e743`: clean production GET/HEAD pass, ordinary and -decorated private sends fail, and removing only IsPublic in a temporary assembly -restores the decorated bypass. No actionable correction remains. The final clean -Release build has zero warnings/errors and all 195 architecture cases pass with -zero failures/skips. Step 2 and both independent review rounds are complete; -Education implementation proceeds in Step 3. - -### P02d-4 Step 3: public Education reads - -**Implementation — 2026-10-04; both review rounds complete.** Education serves all three -GET/HEAD pairs through marked audit-Off queries and the read-only pipeline. The -source store intersects immutable host scope with normal EF filters and RLS. -Published/nondeleted exact-locale marketing is separate from public-parent -inventory/body eligibility; the body SELECT requires its eligible public parent -and exact URL relationship in the same SQL statement. Restricted courses retain -marketing with a null outline; hidden content has the same masked not_found. - -Purpose-built DTOs expose ordered string fields and authored label locales only. -Customization carries admitted `required` metadata through the internal display -contract; no read evaluates a JSON Schema. Optional missing fields are omitted, -unknown properties are omitted and malformed selected/required content yields a -whole unavailable state. Missing exact pins/bands remain bounded without rebinding. -Enabled content locales are exact, while display fallback remains Pattern B. - -The bounded v1 cursor codec checks canonical unpadded base64url, exact JSON members, -version, lower-case scope/UUIDs and UTC microsecond timestamps or nonnegative sort. -Scope binds normalized host digest, host tenant/organization, canonical locale and -endpoint/order; page size is excluded. Syntax/known-scope checks precede the data -transaction; an outline's parent is checked after eligible course lookup and before -inventory/definition loading. PostgreSQL tuple seeks preserve timestamp/sort ties. - -A new no-schema-evaluation architecture guard inspects all four public handlers -and follows production helpers/implementations, with direct, concrete and generic -interface offenders plus a clean control. Controller guards retain all previous -planted bypasses. The persistence walk distinguishes a value object's declared -identifier interface from acquisition of an injected identifier-interface service; -clean metadata, direct domain-ID and hidden service implementations are controls. -Approved read methods are explicitly enumerated in the aggregate-write census; -key-only writes remain visible. The route census covers all eight GET/HEAD actions. - -HTTP/database cases cover exact locale and alternate URL pairs, nullable values, -source lifecycle withdrawal after warmed definition reads, hidden draft/restricted/ -foreign/sibling/wrong-parent content, body/definition corruption, cursor boundaries, -claim/host narrowing, scope hatches, transaction admission and no normal audit rows. -Fixture mutations assert affected rows and announce their explicit write scope; -owner-only satellite corruption is setup, never the observed public connection. -Public execution is proved as non-superuser/non-BYPASSRLS learnstack_app, READ ONLY. - -**Local measurement.** The actual production SELECTs are captured and explained -with ANALYZE/BUFFERS as the application role, without forcing indexes. The tiny -seed uses the course live-key and translation indexes; both outline and body plans -also use `ix_lessons_tenant_id_course_id_sort_id`. The catalog ordered partial index -is available but not selected at this cardinality; no representative large-data or -production p95 claim is made. Captured catalog/marketing/outline queries fetch no -lesson body, and the body query includes access/publication/scope/locale predicates. - -A local Docker sample records a first HTTP request, one warmup and ten observations -per Education route and tenant. Catalog/course/lesson warm medians in one run are -4.16/6.57/6.17 ms for English and 7.65/7.70/7.18 ms for Yoga. Payloads are respectively -551/415/479 and 733/504/662 UTF-8 bytes. Full plans and timing ranges are test output; -these six local medians are neither a production p95 nor a rendering budget proof. -OpenAPI snapshot, SDK/drift and required-check activation remain Step 4. - -**Pre-review verification.** The final clean CI=true Release build has zero -warnings/errors. All 2831 .NET cases pass with zero failures/skips: 1643 unit, -198 architecture, one contract, 171 Docker-free integration and 818 Docker -integration. The final architecture run follows the production-census control; -TRX counters preserve all five suite results. Disabling only transitive helper -walking or implementation walking makes the new planted guard controls fail; -both deliberately broken variants are restored before the final clean run. -Formatting verifies zero changed files and diff hygiene passes. The link/anchor -sweep and unchanged P02d-1–3 delivery records/ADR-0052 prefix are verified. -Both independent review rounds follow this implementation commit. - -**Round 1.** Independent GPT-6-astra and GPT-6.1-sol xhigh reviewers inspect -`b1bff6f..b5c3be2`. The security pass finds no additional isolation, eligibility -or cache issue. The protocol pass finds a malformed-Unicode cursor exception: -JSON strings materialize lazily, outside the original parse exception boundary. -A compiled production probe independently reproduces the unexpected exception. -The fix strictly decodes UTF-8 and refuses escaped-surrogate materialization -failures in both codecs. Unit and real GET/HEAD cases prove bounded 400 before -data access, including property-name corruption and a valid escaped-string control. -The review's coverage limits are closed too: masked 404 fields are checked in -full, and real database cases prove deleted-anchor continuation and current-row -restart for both catalog and outline. The clean Release build and 33 protocol, -198 architecture and 81 Education database/HTTP cases pass with zero skips. -Formatting and diff hygiene pass; a fresh second review follows the fix commit. - -**Round 2 and step closeout.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers -independently approve `b1bff6f..6c09888`, including the Unicode refusal fix and -stronger HTTP/pagination proofs. Both run the 45 protocol/display unit cases; -the protocol reviewer also runs 13 public-surface/aggregate-write architecture -cases. All pass with zero failures/skips; neither reviewer mutates files. No -verified finding remains. Step 3 is complete after both review rounds; Step 4 -continues with the approved OpenAPI, SDK and CI contract. - -### P02d-4 Step 4: contract, SDK and CI - -**Complete — 2026-10-04; PR #25 awaits maintainer review and merge.** -The production -OpenAPI transformer documents manually parsed locale/cursor/page parameters, -shared Problem Details, closed enums and bodyless HEAD. The sole committed v1 -snapshot matches the actual production composition. Contract controls assert all -four paths/eight operations, exact status/query inventories, required public fields, -recursive schema/CLR leaves and complete error shape. Planted missing operations, -parameters/statuses, reordered arrays and nested private/raw fields fail. - -The SDK root exports generated types only; `/server` implements four generated -GET contracts through an injected transport. Encoded paths/queries, no authority -options, allowlisted success shapes and validated Problem Details have fake -transport controls. API errors project into Standards 09's closed AppError union; -unknown extensions are ignored. Malformed JSON, invalid response shape, transport -failure and caller cancellation remain separate. The unused client export is gone. -P02d-5 still owns the configured trusted server adapter and first consumer. - -The always-running `openapi diff` workflow installs checksum-verified oasdiff and -uses the explicit severity policy. Sixty mutation/control fixtures cover -representable ADR-0024 rows and verified placement/type-direction tool gaps. -A deterministic companion traverses reachable request/response schemas and local -object/schema references. It enforces type changes, closed enum additions and -open enum closure/removal, normalizing only matching open enum lists. A combined -open addition plus another breaking change still fails. Current public enums stay -closed; this does not claim an open-enum generator/consumer has shipped. - -PR base SHA, push-before SHA and explicit manual base ref select verified git -snapshots. Missing/deleted heads or failed ref/read/proof fail. Only an actual -operation-free base production composition with no snapshot permits bootstrap; -the verified phase-entry base was built and served with zero v1 operations. Eight -snapshot-admission controls accompany this proof. Artifacts retain original and -normalized specs, refs/hashes, pinned tool/policy and readable/machine reports. -Required frontend CI regenerates the committed SDK and refuses scoped drift. -The approved live sixth check is applied only after the real job runs; no settings -mutation is claimed by this implementation note. - -**Full-suite fixture correction.** The first complete Docker run exposes test -host lifetime leakage: disposed clients retain child hosts and their independent -Npgsql pools until collection teardown. PostgreSQL reports SQLSTATE 53300, and a -new three-client control observes connections rising from one to four. Client -ownership now disposes the private child host and pool too. This changes the test -harness, not the production read contract; targeted and complete regression -results are recorded after execution. - - -**Pre-review verification.** Clean CI=true Release build: zero warnings/errors. -All 2843 .NET cases pass with zero failures/skips: 1644 unit, 198 architecture, -four contract, 171 Docker-free integration and 826 Docker integration. The new -client-lifetime control fails against the original fixture (four connections -instead of one), and passes after host ownership; the combined 102 public HTTP -cases and full Docker run pass. Frontend typecheck/lint/build and all 66 Vitest -cases pass (53 SDK, 13 web). Twenty-three real pinned-tool policy controls and -eight snapshot-admission controls pass. The actual base Program bootstrap has -zero v1 operations. Formatting, actionlint, diff hygiene and changed-document -links/anchors pass. Served snapshot and generated SDK are refreshed from the -current production composition. Both independent review rounds follow this -implementation commit; live check registration follows the real CI job. - -**Round 1 and verified fixes.** Independent GPT-6-astra and GPT-6.1-sol xhigh -reviewers inspect `5d72c2f..5f49f62`. They reproduce three Major contract/policy -findings and two Minor SDK/documentation findings; no Blocker. Actual pinned CLI -probes show root closed-enum additions, referenced open-enum closure and numeric -type changes passing the original gate. The companion now enforces these ADR-0024 -rules in both request and response positions, including local object references; -nine added controls cover root, array, reference and request/type directions. -All 32 pinned-tool controls pass (22 breaking, ten nonbreaking), alongside eight -snapshot-admission controls. The original root-enum reproduction now fails the -policy even though the underlying tool still reports no break. - -Problem Details parameter values now match the existing string-valued -`LocalizedMessage` carrier in served OpenAPI, snapshot, generated types and SDK -parsing. Contract controls compare the nested schema with CLR and actual factory -serialization; empty/number/object schemas fail. SDK controls refuse numeric, -object and null parameters. Lazy URL construction keeps ill-formed surrogate -paths within an `invalid-request` result; already-aborted calls stay `cancelled` -without transport. The sibling frontend standard no longer treats G31 as open. - -The complete .NET suite is repeated: all 2843 cases pass with zero failures/skips -(1644 unit, 198 architecture, four contract, 997 integration, including 826 Docker -cases). SDK typecheck/lint and all 58 cases pass. These fixes change the -schema/SDK/policy, not database read behavior. -Fresh Round 2 review follows the fix commit. - -**Round 2 and verified fixes.** Fresh GPT-6-astra and GPT-6.1-sol xhigh reviewers -inspect `5d72c2f..db9bab6`, independently rerunning 32 policy controls, eight snapshot -controls, 58 SDK and four contract cases; the SDK reviewer also runs the client -disposal control. All pass, but review reproduces three additional policy defects -and two Minor SDK/test gaps. Per-occurrence local reference materialization and -immutable analysis now prevent an open enum normalization from erasing a closed -consumer; both object-key orders have controls. Effective operation parameters -honor inheritance/overrides and the CLI explicitly flattens parameters. Parameter -and header schema/content forms are mirrored into temporary policy-only bodies -with source-location metadata, so the pinned tool checks their fields/validators. -The runtime snapshot is unchanged by this comparison normalization. - -The shared-owner reproduction now refuses even where the raw tool already reports -the break. Inherited tightening/removal/requiredness and relocated type changes -refuse; equivalent relocation remains compatible. Content-form property removal -and request-validator tightening refuse. A response minimum-length increase is -kept as a compatible stronger output guarantee, rather than misclassified as an -input rejection. Fifty real CLI controls pass (36 breaking, fourteen nonbreaking) -with eight snapshot controls. The SDK refuses exact dot segments before dispatch; -all 60 SDK cases/typecheck/lint pass. Added method and path mutants fail the -eight-operation contract control; all four contract cases pass with zero skips. -A fresh focused review verifies these final policy/SDK corrections before closeout. - -**Focused verification and recursive fix.** A fresh GPT-6-astra xhigh reviewer -independently verifies all 50 controls, eight snapshot cases, 60 SDK cases and -four contract cases. It confirms the earlier bypasses are closed, then reproduces -a recursive open-enum addition wrongly refused at an untouched component cycle -edge. Recursive edges now point to private effective schema copies, identified by -stable declaration locations so documentation changes do not alter identity. -Analysis/normalization reach these cycle copies while preserving closed consumers. -Six added controls cover open addition, unchanged recursion, documentation edits -and mixed open/closed schemas in both orders. All 56 real CLI controls pass -(39 breaking, seventeen compatible), with all eight snapshot controls. - -**Final recursive verification fix.** A fresh GPT-6-astra xhigh reviewer verifies -all 56 controls and 27 additional probes, then reproduces an unchanged inline -recursive schema crashing the normalizer. The same occurs inside a Response -component. Stable declaration identity now applies to every local schema location, -rather than only Schema components; four added real CLI controls cover unchanged -and open-addition cases in both placements. Fresh independent verification at -`ef5c4d8` approves: all 60 real CLI controls pass (39 breaking, 21 compatible), all -eight snapshot cases and 27 additional probes pass, and all four original -reproductions return compatible. Both Step 4 review rounds and focused fix review -are complete. No verified finding remains. - -**Pre-PR closeout.** All four implementation steps and their two independent -review rounds are complete on development. Final frontend validation passes -typecheck, lint, build and all 73 cases (60 SDK, thirteen web). Complete .NET -regression remains 2843 passed, zero failed/skipped, as recorded above; the later -compatibility fixes change scripts/fixtures only, and the final operation mutants -pass all four contract cases. Formatting, actionlint, link/anchor and frozen-record -checks pass. Live CI and sixth required-check API read-back follow PR creation; -packet exit is not yet claimed. P02d-5 is next, with its decision pass not started. - -**Live CI and approved check rollout — 2026-10-04.** -[PR #25](https://github.com/HodeTech/LearnStack/pull/25) opens from development to -main. At head `0a14c7474f7cb383a789adf1966d28e67dbc3954`, all six jobs pass in -[the real PR run](https://github.com/HodeTech/LearnStack/actions/runs/37188555958): -backend, Docker integration, frontend, meta, secret scan and `openapi diff`. -Lighthouse is the sole deferred job, owned by P02d-6/G44. Backend TRX artifacts -confirm 2017 Docker-free cases and 826 Docker cases, with zero failures/skips. -The Linux OpenAPI artifact confirms pinned oasdiff 1.33.0, all 60 controls -(39 breaking, 21 compatible), verified base -`d1a47369d82f8b6d91cb325f56d4c42382ec77b6` and actual operation-free baseline -composition; the comparison passes. - -After that successful `openapi diff` job, the approved PATCH adds only its GitHub -Actions context (`app_id=15368`). Fresh full protection read-back proves the five -existing contexts remain, all six have Actions attribution, strict up-to-date -checking remains true, and every other protection field is identical. This includes -zero required approvals and admin enforcement off under the existing maintainer -deferral; no unrelated protection is changed. -[CONTRIBUTING](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) owns -the current list. All six live contexts match the successful PR check rollup. - -P02d-4 implementation and rollout are complete; maintainer review/merge remains. -The final documentation commit reruns the same six jobs before handoff. P02d-5 -owns the next decision pass, trusted server transport and first consumer. P02d-6 -owns pages/rendering; P02d-7 owns the two-host demonstration and full-stack exit. -No browser delivery, marketplace commerce or production p95 is claimed. - -**Final external documentation review.** All six required jobs also pass at -`ddc96a566cd5babf2af3779314471aac33642b95` in -[the final documentation run](https://github.com/HodeTech/LearnStack/actions/runs/37189085766). -CodeRabbit then reports three Minor documentation comments. Current code confirms -cursor/bootstrap delivery and implemented endpoint/write-refusal controls; the -standards now reflect them. ADR-0040 Amendment 9 adds dated frame-delivery evidence -without rewriting its acceptance-time status. The catalogue identifies the table -parser’s actual limit: row method cells remain manual, while the separate endpoint -census mechanically enforces exact GET/HEAD. No production code changes. - -**External review remediation — 2026-10-05.** Findings against `1d938388` are -verified against current code. ADR-0036 Amendment 9 and ADR-0050/0051 Amendment 3 -record delivered provenance, access enforcement and presentation. ADR-0052 -Amendment 12 adds current-delivery navigation. All acceptance statements and -earlier amendments remain unchanged; dated Status disclosures identify them as -history. Browser rendering and authenticated grants retain their named owners. - -Unavailable catalog levels now emit one count-only Warning per summary batch, -rather than one per row. A 100-row regression proves the bound and absence of -private diagnostic fields. The nullable-default refusal remains defensive: -a broken reader contract is refused, as a focused unit case demonstrates. -Cleanup proofs now inspect a fresh live writable transaction on the same -connection after both pre/post-activation setup faults, while the poisoned unit -still refuses another frame. Injected Npgsql logging uses the shared application -data-source guard; direct and transitive bypass-role cases exercise its logged -overload with restored-role positive control. - -The suggested common provenance refactor introduces no correctness fix and is -not bundled. The Education spec explicitly records the controller/helper guard's -scope and independent handler-connection residual risk already accepted by -ADR-0052; current handlers use their approved read ports. The pre-existing -membership-reader DI backstop is outside this PR, rather than a P02d-4 defect; -production still registers the deny-all reader. - -Local verification: clean Release build with zero warnings/errors, format and -link/anchor checks pass. Full .NET regression is **2847 passed, zero failed or -skipped**: 1646 unit, 198 architecture, four contract and 999 integration. The -four added cases are two display/configuration facts and two logged role-guard -theory cases. Contract tests again verify the production-served v1 document; -the committed OpenAPI/SDK contract is unchanged. Live main protection still -requires all six Actions contexts with strict checking; no settings are changed. - -**Remediation review closeout.** Two fresh independent rounds review -`1d938388..ef86f64`: Round 1 code and documentation reviewers both Approve; -Round 2 code and documentation reviewers both Approve. No actionable finding -remains. Both documentation reviewers independently verify preserved ADR history, -delivery claims, phase ownership and all 590 relative links/anchors in the six -changed Markdown files. The complete local regression above verifies the code -fix; this closeout adds delivery evidence only. - -### P02d-4 merge and closeout (2026-10-08) - -The maintainer merged [PR #25](https://github.com/HodeTech/LearnStack/pull/25) at -2026-10-08 15:25:18 UTC. GitHub records final PR head -`f8adb110ff7fca2a15bbd3f87c1546c62852dc4c` and merge commit -`b83175538cf6f9c5415294a8f77dadd9c82588dd`. The merge's second parent is that -head, and both commits have the identical tree. Development remains the working -branch; the fetched main ref verifies the merge without changing branches. - -- All six required checks pass on the - [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37794924088). - Downloaded TRX artifacts confirm **2847 passed, zero failed or skipped**: - 1646 unit, 198 architecture, four contract, 171 Docker-free integration and - 828 Docker integration. Frontend CI passes typecheck, lint, build, SDK drift - verification and **73 tests** (60 SDK, thirteen web). -- All six required checks also pass in the - [merge-commit run](https://github.com/HodeTech/LearnStack/actions/runs/37800631591). - Independently downloaded merge-run TRX confirms the same 2847 passing cases - and zero failures/skips. Its OpenAPI artifact matches the merge SHA and - snapshot hash. Read-only protection verification confirms all six Actions - contexts with `app_id=15368` and `strict: true`; no setting is changed. -- OpenAPI artifacts match the final head, verified base and committed snapshot - hash. All **60 policy controls** pass (39 breaking, 21 compatible). The final - workflow correction adds six actual-event selection controls to the eight - admission/bootstrap controls: **14 Python tests** pass locally and in CI. - Four local selector mutants fail. Zero-before pushes select the head's parent; - ordinary push, PR and manual refs retain their existing contracts. -- The final review corrections retain unchanged ADR decisions and align delivery - navigation. Two fresh focused reviewers approve each final follow-up - (`7e07613..7ad4b91` and `7ad4b91..f8adb11`). CodeRabbit succeeds at the final - head; all five inline threads are resolved. The four implementation steps' - two-round review records above remain unchanged. - -**P02d-4 is closed.** Host-scoped anonymous site/catalog/course/lesson GET/HEAD, -physical read-only frames, exact enabled-locale/access eligibility, bounded public -projections and cursors, the served OpenAPI baseline, typed SDK and compatibility -gate are delivered. No database migration is added by P02d-4. - -**Next: P02d-5 — Server-rendering path.** Its implementation and decision pass -have not started. The [packet gate table](#packets-and-decision-gates) owns its -complete prerequisites; the [decision register](#the-decision-register) still -leaves development transport/hosts, trusted-hop topology and rate limiting, -server SDK transport, middleware/locale entry, rendering/cache policy and the -frontend test/skip fence open. P02d-4 supplies the completed API prerequisite; -it does not accept those later decisions. - -P02d-6 owns the three public pages, text-card renderer, safe theme injection, -language attributes and accessibility. P02d-7 owns `make demo`, the two-host -full-stack evidence and phase exit. G44 retains the Lighthouse activation -decision. Phase 02d remains in progress; no browser delivery, authenticated -learner grants or Course Marketplace commerce is claimed by this closeout. - -**Documentation-only closeout validation.** Five local corpus-consistency tests -pass with zero failures/skips. The seven changed Markdown files pass the local -relative-link/fragment audit (825 link occurrences, 342 fragments), added-prose -width and diff checks. ADR-0052 changes are insertion-only; previous P02d-4 -delivery notes and the P02d-1 suffix remain byte-identical. No production code -changes or new decisions are introduced. - -### P02d-5 decision package (2026-10-08) - -**Accepted — 2026-10-08, verified against development `88f52c4`.** The maintainer -approved ADR-0053 and this package before implementation. P02d-4 is merged; -[ADR-0053](../decisions/0053-trusted-public-server-rendering.md) owns the bounded -replacement rules. Only the named P5 gate parts below close; delivery remains -separate from acceptance. - -#### Baseline and document review - -The preparation baseline is development `88f52c4`. Three independent read-only -reviews cover trust/topology/limiting, frontend/runtime semantics and governance. -Their conclusions are checked against source, not accepted as instructions. - -- P02d-4 supplies bootstrap, Education GET/HEAD, public DTOs, READ ONLY, no-store, - cursors, a served snapshot, typed injected SDK and required diff/drift checks. -- SDK Vitest tests and AppError parsing are already delivered. G38(a)'s older - missing-script premise and G35's implied missing parser are historical premises. -- Middleware still forwards client headers, writes host into `x-tenant-id`, invents - `en` and refuses production requests with `503`; no configured caller exists. -- Installed Next 15.5.18 preserves a supplied `x-forwarded-for` when adding socket - metadata. Middleware cannot turn it into reliable visitor identity. -- API limiting is 60 calls/minute per socket peer. Forwarded-header middleware is - unwired; reading the connection feature alone does not protect a mutated peer. -- API startup permits both hop lists empty in every mode, refuses partial lists, - invalid CIDRs and blank/secrets shorter than 32 characters. ADR-0053 explicitly - adopts that policy in place of ADR-0036's older non-Development/byte wording; - a dated ADR-0036 Amendment discloses it without rewriting the Accepted body. -- Standards 07's delivered injected SDK contradicts ADR-0036's older exact file - chosen to set hop headers. The new decision must disclose its replacement. -- Standards 07 and Architecture 14 still prescribe cached public rendering under - open G37; a changed ongoing rule requires an ADR, not a quiet code exemption. -- The route skill's obsolete P4 stub description is corrected during preparation. - Frozen P1–P4 delivery records and Accepted ADR bodies remain unchanged. - -The reviewed carrier families are CLAUDE/README, vision/MVP, roadmap timing and this -phase; ADR-0009/0035/0036/0040/0050/0051/0052 and the ADR index; architecture -09/12/14/30; standards 03/04/06/07/08/09/10/11/12/13/15/16/20/21; the route, -local-dev, seed and test workflows; current API/SDK/web/compose/CI source. Future -renderer decisions G39–43 are inputs, not accepted by this package. - -#### P02d-5 accepted answers - -| Gate part | Accepted answer and authority | -|---|---| -| G6(c) | Canonical enabled locale prefixes; `308` for enabled noncanonical spelling, `307` for default-locale entry, masked `404` for malformed/disabled/unknown prefixes. Exact matrix below | -| G20: exemptions | Demo identity literals only in `SeedData`, seed/development launch/configuration, operational docs and test-owned assertions/fixtures. No host/domain-specific branch in middleware, transport, renderer or modules; a generic host normalizer is not a demo exemption. P6 decides renderer subjects, P7 implements the complete Registered guard | -| G21: cookies | Public entry neither sets nor uses cookies; no Authorization/session forwarding. Preserve P2's no new remote subresource contract. Phase 02b owns session cookies; Secure-cookie TLS proof here is a test-owned transport control, not authentication implementation | -| G30: headers | Native ingress verifies captured host/peer provenance; middleware rebuilds private context; one configured server adapter emits the closed API-hop set in ADR-0053. Education locale is query-only; no tenant/organization assertions | -| G32 | [Accepted — 2026-10-08](#local-setup-and-ingress-details): local hosts and TLS | -| G33 | [Accepted — 2026-10-08](#local-setup-and-ingress-details): local topology, shared source and ingress | -| G34 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#api-hop-and-anonymous-budgets): authenticated visitor and peer budgets | -| G35 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#configured-caller-and-rendering): configured caller/deadlines; [Frontend Observability](../standards/10-observability.md#frontend-observability) owns Phase 11 logger/Sentry/web-vitals | -| G36 | [Accepted — 2026-10-08](#public-entry-matrix): membership-first entry and redirects | -| G37 | [Accepted — 2026-10-08](../decisions/0053-trusted-public-server-rendering.md#configured-caller-and-rendering): dynamic no-store renderer policy | -| G38(a) | Vitest covers normalization/stamps/header stripping, locale/entry matrix, configured origin/header construction, errors, deadlines/body/cancellation and tracing; production-build/socket fixtures cover runtime boundaries. SDK tests remain inherited | -| G38(d) | Extend existing non-skippability rule to tested frontend workspaces. Fail skipped/todo, empty/unreadable reports and discovered test packages without an execution script; planted actual runner cases prove failure | -| G44: whether | Activate full-stack Lighthouse in P02d-7, after P6 pages and G45's shared demo harness. P5 updates live deferred-job ownership carriers; it does not audit placeholders. P7 still selects tools, URLs, assertions/budgets and status promotions before harness code | - -This acceptance closes only the named P5 parts. G38(b,c), G39–43, G44's harness -details and G45 remain with P6/P7. No market, auth, CMS, media or grant decision moves. - -#### Local setup and ingress details - -Keep the two hosts already declared in `SeedData`; do not create a second hardcoded -host registry in production code. The explicit workstation step adds those names -to `127.0.0.1` in the hosts file and creates a leaf certificate with their exact SANs -and `localhost` for readiness. The documented tool is mkcert (BSD-3-Clause); its CA -trust/install step is performed explicitly by the developer. No script edits hosts, -installs system trust, ignores TLS errors or shares the CA private key. Leaf/key -paths live under gitignored `.data/`; examples contain paths, never key material. - -The ingress owns port 3000 on IPv4 loopback and delegates requests/upgrades to Next's -supported custom-server interface. It strips inbound forwarding/internal/framework -override headers before minting the single provenance envelope specified by -[ADR-0053](../decisions/0053-trusted-public-server-rendering.md#ingress-and-provenance). -Middleware verifies it before bootstrap, rebuilds downstream request headers from -the allowlist, and the server caller verifies it again before SDK use. Direct stock -`next dev/start` is unsupported and must fail closed if callers forge plain carriers; -a valid production-build control proves the supported launcher actually works. - -One ignored local source provides a freshly generated 32-byte random ASCII-encoded -hop secret to both processes. API networks and secret list arrive together through -launch configuration; do not commit a network-only Development default. The native -launcher/Next caller use the same private source for domain-separated ingress MACs. -`.env.example` owns the variable vocabulary; the web example documents its narrow -projection and matching/conflict checks. The loader must not shell-evaluate env -values or echo credentials. Empty/malformed renderer configuration refuses startup; -ordinary no-hop API startup and existing Development fixtures continue to work. - -P5 tests use isolated certificates and trusted test roots, never disabled certificate -verification. Browser TLS/Secure-cookie checks are evidence to obtain, not claims -already proved on this workstation. P7's CI harness uses isolated per-run roots, -host resolution and secrets; it never installs a permanent developer CA. - -#### Public entry matrix - -The fixed public section name is `courses`; section-name localization remains -Phase 06. After bootstrap, enabled-locale membership takes precedence over every -shorthand or scaffold name. No locale is rejected just because its grammar-valid -name is `courses`, `studio` or `portal`. -For a well-formed request, bootstrap runs before locale/redirect decisions. Unknown -or platform host, unavailable live scope and valid empty locale configuration return -masked `404`. Dependency/invalid stored configuration or transport failure returns -bounded `503`; API `429` remains `429` with validated Retry-After. No body embeds -provider errors, host IDs or internal headers. P6 owns localized page-state rendering. - -| Input on a bootstrapped live host | Answer | -|---|---| -| `/` | `307` to `/{defaultLocale}/courses` | -| `/courses`, `/courses/{slug}`, `/courses/{slug}/lessons/{lessonSlug}`, when `courses` is not an enabled locale | `307` to the same path with the configured default prefix | -| `/{enabledCanonicalLocale}` or its one trailing slash | `307` to `/{locale}/courses` | -| Enabled noncanonical locale prefix on a supported public path | `308` to its canonical prefix; only after enabled membership succeeds | -| Canonical enabled prefix on a supported public content path | Continue with verified host/peer and canonical route locale; P6 supplies pages | -| Exact current `/studio` or `/portal` scaffold root on a live host, when that name is not an enabled locale | Continue to the existing scaffold without a public locale or authentication claim; no prefix-wide exemption | -| Malformed, disabled, unknown or overlength locale prefix; unknown section/path | Masked `404`, no fallback and no content request | -| Malformed/missing Host, socket provenance or ingress signature | Refuse before bootstrap; never use a forwarded/default host | - -Locale parsing matches the shipped LocaleTag grammar, canonicalization and -35-character bound without trimming. First validate/canonicalize the first segment -and check enabled membership; only on a nonmember consider the exact scaffold -roots or the `courses` shorthand. Otherwise it is an unsupported/malformed prefix, -so `en_US` never becomes a default-locale resource path. Percent-encoded locale -prefixes are refused rather than decoded into another locale identity. No -`Accept-Language`, cookie or `?locale=` overrides the path. Explicit query locale on -Education calls always comes from that path. - -When `courses` is enabled, `/courses` is its locale root and `/courses/courses` its -catalog; `/courses/{slug}` shorthand is intentionally unavailable on that host. -Its full localized `/{locale}/courses/{slug}` path remains available. Default and -nondefault `courses`/`studio`/`portal` fixtures must prove terminal redirects and -normal localized admission. P6/Phase 02b's future static/auth routes must preserve -these public paths rather than shadow them; those packets own their distinct UI -namespaces. No known-locale registry or locale-writer restriction is introduced. - -Redirects use the successfully bootstrapped normalized visitor host with the -configured HTTPS scheme/ingress port and a local computed path. They never use -`request.url`'s possibly substituted origin, forwarding headers or a query redirect -target. Preserve query bytes as inert query data; bound/validate request targets, -reject authority/encoded separator or traversal ambiguities and test those cases. -Disable implicit pre-middleware slash/URL redirects where they bypass this policy. -Every tenant-bearing redirect/refusal is no-store; no cookies are emitted. - -The matcher excludes Next assets/HMR, exact `/api/healthz` and favicon. It does not -exclude `studio`/`portal` prefixes: enabled locale paths need normal admission. -Health remains live without a tenant bootstrap; native ingress sanitation still -applies. The exact scaffold-root continuation above requires successful live-host -bootstrap and grants no API or authentication authority. Platform/unknown hosts -still receive `404`. Future BFF/auth routes require their own Phase 02b contract; -P6/G40 decides the product behavior of the remaining scaffold screens. - -**P02d-6 entry extension — Accepted 2026-10-09.** In addition to the delivered -P5 matrix above, exact `/{enabledCanonicalLocale}/status/not-found` continues -through live admission with middleware HTTP `404`. Noncanonical enabled prefixes -canonicalize under the same rule; sibling/extra status segments remain masked -`404`. This status route carries no Education authorization. P6's decision package -owns the original content request's 307→404 navigation chain. Implementation is -not claimed by this acceptance note. - -#### P02d-5 implementation plan - -The first commit accepts this package and ADR-0053, records the bounded ADR-0036 -replacement/navigation and updates the ongoing carriers below. -Then every implementation step is committed, reviewed by fresh agents twice, and -each confirmed correction is validated/committed before the next step. - -1. **Native ingress and local topology.** Implement the mandatory launcher, private - configuration/stamp protocol, TLS path/readiness, fixed loopback bindings and - shared-source launch recipe. Update web scripts/config, environment examples, - README/local-dev/seed workflows. Prove missing/forged/bypassed ingress refusal, - valid production-build startup, no-env API startup, TLS and secret containment. -2. **API visitor admission and budgets.** Add strict trusted visitor metadata, - canonical IP partitioning, peer ceiling and pre-lookup refusal. Keep network - plus secret checks and forwarded-header ban. Add actual socket and HTTP/Postgres - positive/negative/flood controls as `learnstack_app`, preserving no-store/DTOs. -3. **Configured caller and public entry.** Implement the single server-only - transport, narrowly scoped fetch-lint exemption, Node middleware/bootstrap, - locale matrix, origin-safe redirects and dynamic/no-store policy. Prove slow - bodies, decoded-size bounds, cancellation, redirect secret containment, - trace-ID agreement and every - malformed/disabled/noncanonical entry case with a non-English default. -4. **Mechanical frontend fences and closeout.** Enforce server/cache/header - boundaries and frontend skip/todo refusal with clean/planted controls. Complete - production-build integration evidence, update all current carriers, run relevant - suites and both final reviews; open the P5 PR for maintainer review. - -P5 production-build fixtures use test-owned routes importing the real ingress, -middleware and caller against the real public API; no diagnostic route enters the -shipped app. Entry/bootstrap runtime evidence is distinct from P6's catalog/course/ -lesson UI and P7's two-host browser demo. Where a phase-level criterion requires -those pages, its evidence owner stays P6/P7; P5 cannot mark it complete with a fake -transport. API-only proofs remain named separately. - -#### Acceptance carriers and validation - -Acceptance updates ongoing rules; delivery updates each owner with its enforcing -implementation: - -- ADR index and current packet register/navigation; append-only ADR-0036 note for - the bounded limiter/setter replacements and mode-independent startup policy. - Name it a dated Amendment under ADR-0041/Standards 13, with source/history evidence - and carrier disclosure; the new ADR owns changed rules, not an in-place correction. -- Standards 04/11 rate limits; 07/15 dynamic rendering/caller; 08 path entry; 10 and - Phase 11 frontend observability ownership; Architecture 09/12/14/30 as applicable. -- Existing Standards 21 hop/peer/non-skippability entries, plus Registered proof - names only when selected; claims become Implemented with actual enforcing tests. -- Route/local-dev/seed/test skills; root/web environment examples; web scripts, - Next configuration, README Quickstart and Makefile launch help where introduced. -- Phase 02b G12/G14 re-verification handoff; Phase 06 redirect/cache inheritance; - CI/CONTRIBUTING/test-skill Lighthouse ownership explicitly P02d-7/G44. Historical - shipped records are not rewritten to disguise the transition. - -Validation includes Release/format, architecture/unit/contract and relevant Docker -integration suites; all frontend workspace typecheck/lint/build/tests and SDK drift; -real production-build/socket/TLS cases; actual skip/todo/import/cache mutants; changed -Markdown relative links/anchors, width/residual checks and ADR-history preservation. -No test count, browser observation or CI success is claimed until it is run. - -**Preparation verification — 2026-10-08.** Two fresh proposal-review rounds -checked security/runtime and corpus/decision completeness. The confirmed locale -name collision was corrected with membership-first entry; both second-round -reviewers approve the revised proposal. Two fresh focused reviewers also approve -the external-review corrections to secret cardinality, provenance carriers and -Amendment/standard ownership. The existing `CorpusConsistencyTests` pass 5/5, -with zero failures/skips. The six preparation files have 683 relative link -occurrences and 321 fragment targets, all resolving; added prose wrapping, -`git diff --check` and Accepted-ADR/historical-body preservation checks pass. -These are document-preparation results, not P5 implementation or browser evidence. - -#### Approval boundary - -The maintainer approved the exact ADR/package on 2026-10-08: the native custom -launcher, existing names with manual local TLS, dynamic public rendering and the -explicit 60/IP plus 600/peer API budgets. Automatic trust-store modification is not -authorized. Implementation now proceeds on development through the four steps and -two fresh review rounds per step; acceptance alone marks no delivery criterion done. - -### P02d-5 delivery record - -#### P02d-5 Step 1 — Native ingress and local topology - -**Implementation delivered — 2026-10-08; review rounds pending.** The mandatory -native Node launcher binds HTTPS to `127.0.0.1:3000`, validates the private source -and delegates requests/upgrades to Next 15.5.18. It captures the real socket peer, -canonicalizes IP identities, validates exactly one Host and bounded request target, -strips incoming private/forwarding/framework carriers, then mints the HMAC envelope. -Verification binds host, peer, method and raw target and refuses forged/repeated or -noncanonical envelopes. No ingress code resolves tenant/organization authority. - -`make public-env` generates an ignored 32-byte random ASCII-encoded secret without -hosts/trust changes. `make public-api` supplies only runtime database credentials, -fixed loopback network and matching secret; `make public-web` and `pnpm dev/start` -use the native launcher. Root/web environment examples and README/local-dev/seed -workflows describe explicit mkcert trust, leaf creation and manual hosts aliases. -The API's ordinary no-hop startup remains unchanged. - -The old middleware's tenant-header placeholder and invented `en` fallback are -removed. Its interim Node admission returns no-store `503` after valid provenance -and masked `404` otherwise. Health/assets are excluded from tenant entry, but all -requests pass native sanitation. Step 3 replaces the interim refusal with real -bootstrap and locale entry. Next implicit URL/slash redirects and Server Component -HMR caching are disabled. P6 pages and P7's demo remain separate delivery scopes. - -**Validation.** The frontend suites pass 128 cases (60 SDK, 68 web), including 55 -ingress/config/socket cases; workspace lint, typecheck and production build pass. -The production companion verifies test-root TLS readiness, private-header stripping, -no carrier/secret in responses or retained fixture diagnostics, and stock-Next -forged-carrier refusal. Existing API hop-configuration tests pass 5/5 with zero -failures/skips, preserving empty-hop mode-independent startup. TLS controls use -isolated trusted roots and a test-only Secure-cookie response header; no browser -cookie acceptance or local CA installation is claimed. - -**Step 1 round 1 — confirmed corrections (2026-10-08).** Independent security -and quality reviewers identify two boundary failures in the committed foundation. -The production companion reproduces a valid raw query returning `404` because Next -serializes its search parameters and removes `_rsc`; it also reproduces an interior -repeated slash causing a pre-middleware redirect. The fix preserves the signed raw -target, compares only its explicit pinned-Next projection at middleware admission, -and rejects repeated pathname slashes before delegation. Ten focused cases and -production controls cover query rewriting, terminal `?`, RSC query stripping, -method/path/query substitutions and no-store refusal without an implicit redirect. -OpenSSL prerequisites and the paired/API-only restart guidance are clarified. -The corrected frontend suite passes 138 cases with zero failures/skips; -production TLS/query/bypass controls, typecheck, build, native/config lint and -changed-link/history checks pass. Second-round review remains pending. - -**Step 1 round 2 — closeout (2026-10-08).** Fresh GPT-6-astra xhigh and -GPT-6.1-sol xhigh reviewers inspect the cumulative implementation. Confirmed -corrections remove all pinned-Next internal routing/resumption/revalidation -headers at native admission and prevent Next's automatic upgrade listener from -receiving rejected inputs. The supported `httpServer` option registers that -listener on a non-listening sink; native TLS admission alone delegates upgrades. -Real production controls reject duplicate Host before Next, admit one sanitized -upgrade, and fail when the sink option is removed. An isolated development fixture -receives `101` for admitted HMR and no delegation for its rejected control. - -The companion also recognizes children already terminated by signal, observes -exit before signaling and bounds forced cleanup. Real already-exited, running and -SIGTERM-resistant controls pass. The corrected 138 frontend cases, production -TLS/query/upgrade/bypass controls, production build, typecheck and lint pass with -zero failed/skipped cases. Both reviewers approve the corrected scope; Step 1 is -complete and Step 2 follows. No workstation-browser proof or P6 page is claimed. - -#### P02d-5 Step 2 — API visitor admission and budgets - -**Implemented — 2026-10-08; independent reviews pending.** The API captures one -request-local visitor identity through the existing network-and-secret hop -predicate. Its bounded IP parser rejects abbreviated/integer IPv4, ports, lists, -zones and whitespace; IPv4-mapped IPv6 shares the direct IPv4 namespace. Unknown -peers retain one fixed fallback partition. No header selects a tenant. - -Chained fixed-window limiters apply 600 calls/minute per physical peer first, -then 60 calls/minute per canonical visitor IP, without queues. This ordering -prevents exhausted peers from creating additional visitor partitions. Missing, -malformed and repeated trusted metadata consumes fallback quota, then receives -masked `404` before host classification; untrusted forwarding metadata is ignored. -Existing `429` Problem Details and `Retry-After` remain authoritative. - -**Validation.** The 28 new identity cases and 18 existing hop/configuration cases -pass. Fifteen new real-Kestrel/PostgreSQL cases and both existing anonymous HTTP -controls pass, with zero failures/skips. Positive public reads reach the production -reader as `learnstack_app`, with READ ONLY and no superuser/BYPASSRLS privileges. -Controls cover shared direct/hop quotas, independent visitors, canonical IPv6, -rotation, repeated raw headers, novel-host bounds and both budget ceilings. -Invalid metadata and over-budget requests do not call the host resolver. The -initial API Release build passes with zero warnings/errors. Steps 3–4 remain open. - -**Step 2 round 1 — confirmed corrections (2026-10-08).** Independent -GPT-6-astra xhigh and GPT-6.1-sol xhigh reviews identify premature physical-peer -exhaustion and a quota-test oracle gap. ASP.NET retries a refused synchronous -acquisition asynchronously; re-running the peer-first fixed-window chain charges -its earlier peer permit twice. A real-Kestrel regression fails on request 331 -after 60 accepted and 270 refused calls. A request-local no-queue wrapper preserves -the first refusal and its metadata without repeating the acquisition; each -framework attempt owns a separate lease. Peer-first ordering remains unchanged. - -The corrected mixed-traffic control admits the remaining allowance through actual -request 600 and refuses 601 before lookup. Independent assertions fix the accepted -60/IP, 600/peer and one-minute values. All 18 focused HTTP controls and 47 -identity/hop/configuration cases pass with zero failures/skips. The pre-correction -full regression passed 2,890 cases but did not cover this newly reproduced boundary; -it is not evidence for the corrected head. Second-round review follows. - -**Step 2 round 2 — lifecycle correction (2026-10-08).** Fresh GPT-6-astra -xhigh and GPT-6.1-sol xhigh reviewers confirm the corrected quota behavior and -identify incomplete limiter shutdown. The framework chain does not own its child -budgets; the wrapper's asynchronous path and the options registration also lacked -ownership. DI now owns the wrapper, which disposes both budgets exactly once on -synchronous and asynchronous shutdown. Four focused lifecycle cases pass. -Both reviewers independently verify the correction, including actual provider -shutdown, completed child timers and refusal after disposal, and approve. - -The independent security probes also confirm that rotating visitor metadata after -peer exhaustion creates no further visitor partitions, while an already-cancelled -acquisition creates none. These are test-owned probes, not production telemetry. -Both review rounds are complete. The final corrected Release build has zero -warnings/errors; **2,896 backend cases** pass: 1,679 unit, 198 architecture, -four contract and 1,015 integration, with zero failures/skips. The nonempty-run -check covers all four assemblies. The two changed Markdown files pass the local -link/fragment audit (552 links, 295 fragments), added-prose width and diff checks. -Frozen P1–P4 history and Accepted ADR bodies remain unchanged. Step 2 is complete; -Steps 3–4 follow automatically under the approved plan. - -#### P02d-5 Step 3 — Configured caller and public entry - -**Complete after both review rounds — 2026-10-08.** One server-only -adapter supplies the four injected SDK GETs with private origin and a closed -authenticated hop. It re-verifies the envelope and derives locale only from the -canonical signed route. Redirects are refused; caller cancellation is distinct -from the ten-second total header/body deadline. Decoded response bytes are counted -while consuming, up to 8 MiB; oversize is a transport failure without truncation. -Cleanup does not wait indefinitely for stream cancellation or late fetches. - -Node middleware verifies before request-local live bootstrap, then applies the -accepted membership-first entry matrix. Non-English default, disabled/malformed -prefixes and default/nondefault `courses`/`studio`/`portal` locale collisions are -covered. Redirect authority comes from the bootstrapped captured host and fixed -HTTPS port, preserving signed raw query bytes. Continuation rebuilds request -headers and emits no cookie or ordinary provenance response header. The public -layout is dynamic with zero revalidation and force-no-store fetches. - -**Validation.** All **280 frontend cases** pass: 220 web and 60 SDK, zero -failures/skips. The 39 adapter controls include real loopback HTTP gzip expansion, -exact decoded size, redirect credential containment, caller cancellation and a -ten-second deadline spanning delayed headers and body. Eighty-two entry and 21 -middleware cases cover admission, raw queries, error mapping and request isolation. -Workspace lint/typecheck and the production build pass. The production TLS -companion exercises the real middleware/caller against a test-owned bootstrap -server, proving live redirects, raw-query retention and stock-Next refusal before -bootstrap. It does not replace Step 4's real-API integration or P6 pages. -The real-Kestrel/PostgreSQL trace control also passes: the API's Problem Details -uses its own span with the adapter's propagated trace identifier. The HTTP test -disables the test HttpClient's ambient trace injection so it observes the intended -wire header; the production caller itself remains unchanged. - -**Step 3 round 1 — harness failure cleanup (2026-10-08).** Independent -GPT-6-astra xhigh approves the security/runtime boundary. GPT-6.1-sol xhigh -reproduces an asynchronous fixture-listener assertion bypassing the outer cleanup, -leaving a Next child and temporary tree alive. The listener now records refusal -without printing credential values; the awaited outer flow raises the failure -where cleanup owns all resources. A source-planted wrong-path control runs the -real production harness, exits red and verifies its child and tree are gone. -The unmodified production TLS companion also passes. No API/entry policy changes. - - -**Step 3 round 2 and closeout (2026-10-08).** Fresh GPT-6-astra xhigh -approves security and runtime behavior, including both production companions and -no-store scaffold continuation. Fresh GPT-6.1-sol xhigh reproduces a test-oracle -gap: a 36-letter locale already fails primary-subtag grammar, so removing only -the 35-character guard leaves the entry suite green. Grammar-valid 35/36-character -controls now isolate the bound; the reviewer verifies all 84 cases pass and the -removed-guard mutant fails exactly the 36-character case. Production policy is -unchanged. Both independent rounds and fix verification pass; Step 4 follows. - - -#### P02d-5 Step 4 — Frontend fences and production integration - -**Implemented — 2026-10-09; independent reviews pending.** Two reserved frontend -rules now name actual Vitest assertions with a nonempty production TypeScript -census. AST analysis follows runtime imports/reexports and constant dynamic imports, -with alias/computed fetch and header, server-only, raw-authority, layout-policy and -cache controls. Request-local React cache remains allowed. Arbitrary eval, runtime -reassignment and external implementation bodies are outside the structural claim; -actual production/socket proofs remain separate. - -The root frontend runner discovers test packages from the workspace declaration, -including ones pnpm would otherwise skip. It refuses missing scripts, missing or -invalid/empty reports, failures, skipped/todo cases and omitted discovered files. -Actual isolated Vitest clean/skip/todo/missing-script/report/omission controls prove -refusal. The existing frontend CI context uses this runner and executes the native -production TLS/failed-listener cleanup companions after build. - -`PublicServerRenderingTests` compiles a disposable app with test-owned routes that -import the real ingress/middleware/caller and SDK against real Kestrel/PostgreSQL. -Both seed hosts render the same locale/slug in cold/interleaved HTML and RSC without -cross-host values. The fixture proves exact lesson projection, non-English default -redirect, stock-Next forgery refusal before any API/database bootstrap, nonempty -client asset and native/API log containment, and next-request publication freshness -in the same native process. Its real API reads use `learnstack_app`, physical READ -ONLY frames and the existing isolation observer. Only test setup mutates owner rows, -with restoration in `finally`; it is not the role used to prove isolation. - -A real Client Component import of the configured caller fails with the server-only -diagnostic; deleting that test-owned route yields a clean production build. Private -runtime configuration is supplied only after compilation. Bootstrap/page reads -share one valid trace identifier for supplied, missing and malformed incoming -contexts; the middleware creates a request-local context before either caller. -No trace or private carrier is emitted to the browser. - -Pinned Next streams RSC not-found with HTTP 200 and its exact -`NEXT_HTTP_ERROR_FALLBACK;404` digest, while the document response is 404. The -fixture requires the real API's parsed 404, the digest and absence of previous -content; other API/transport failures fail the proof. It stays below the existing -60-call visitor budget and owns only isolated ports/certificates/build trees. -Backend integration CI receives Node/pnpm and frozen frontend dependencies; no -required check name or branch-protection setting changes. - -Test-owned routes are P5 transport/runtime evidence. Public catalog/course/lesson -product UI is P6; browser demo and Lighthouse remain P7/G44/G45. This step adds no -production diagnostic route, page UX, auth, CMS or database migration. - - -**Step 4 pre-review verification (2026-10-09).** Release build has zero -warnings/errors; format verification passes. All **2,898 backend cases** pass: -1,679 unit, 198 architecture, four contract and 1,017 integration, with zero -failures/skips. Every assembly passes the nonempty-run checker and direct TRX -counter comparison. The complete guarded frontend run passes **381 cases**: -321 web and 60 SDK, zero failures/skips/todos. Workspace lint/typecheck and the -production build pass. Focused production integration also passes independently; -normal native TLS and planted listener-cleanup controls pass. Both `pnpm test` -and `make test-frontend` route through the guarded runner. SDK snapshot drift and -the final per-step review evidence are recorded below when complete. - -**Step 4 round 1 — proof repairs (2026-10-09).** Independent GPT-6-astra -xhigh runtime/security review approves the production boundary. It reruns the real -API fixture and verifies that compiled shared-result and credential-log mutants -fail their intended isolation/containment assertions; owned listeners and build -trees are cleaned on failure. GPT-6.1-sol xhigh quality/standards review identifies -three proof gaps: the missing-report control fails before reaching report parsing, -namespace aliases can hide Next caching, and destructured headers can hide raw -authority reads. Each gap is independently reproduced before repair. - -The report control now runs a successful script without a report and requires -`ENOENT`; empty and unreadable reports have separate reason assertions. Source -analysis follows namespace variable/import/reexport aliases and object-binding -headers, including a transitive barrel control. All 77 source controls and 26 -runner controls pass, and the complete guarded frontend run passes **388 cases**: -328 web and 60 SDK, with zero failures/skips/todos. Web typecheck/lint pass. Three -workflow skills now describe Accepted G25/G36/G37/G44 instead of their prior open -questions; no accepted decision or production behavior changes in these repairs. -The quality reviewer independently confirms all three fixes and passes 127 focused -source/runner/middleware cases. Both first-round reviewers approve the corrected -tree; second-round review remains pending. - -**Step 4 round 2 — source and cleanup repairs (2026-10-09).** Fresh -GPT-6-astra xhigh security/runtime and GPT-6.1-sol xhigh quality/standards reviewers -verify the current implementation independently. The confirmed source gaps are -awaited header collections, named/default/star/namespace export aliases, private -environment bindings and exported global fetch. Reused constant expressions need -path-local cycle detection, and explicit runtime exports must shadow star exports. -All original counterexamples fail before their fixes; dirty and clean controls now -separate these cases without interpreting function bodies or runtime reassignment. - -The final source suite passes **104 cases**. The quality reviewer independently -executes 28 additional in-memory controls over the production census: all 20 dirty -cases are detected and all eight clean cases are accepted. The complete guarded -frontend run passes **420 cases**: 360 web and 60 SDK, with zero failures/skips/todos. -Workspace lint/typecheck pass. Focused-test instructions use the package command; -the guarded root runner deliberately accepts no filters. Stale App Shape, SSR risk -and text-card projection status clauses are synchronized without changing decisions. - -Owned test process groups can outlive their leader, so both native fixtures share -bounded group cleanup. Only an absent group closes the proof; transient Darwin -`EPERM` counts as present, and persistent refusal fails at the deadline. Five clean -and planted cleanup cases pass. The security reviewer independently passes four -consecutive native runs, the failed-listener companion and the real-API production -rendering fact in Release with `CI=true`, with zero failures/skips. The helper's ESM -declaration uses the existing shared typed ESLint parser. No production trust rule -changes in this round. Both second-round reviewers approve the corrected tree; -Step 4's two independent rounds and fix verification are complete. - -#### P02d-5 packet closeout (2026-10-09) - -**Implementation-complete, unmerged.** All four planned steps and two fresh -independent review rounds per step are complete. Confirmed findings are repaired -and committed; no verified P5 issue or maintainer decision remains open. The native -ingress, authenticated visitor budgets, configured server caller, live locale entry, -dynamic/no-store policy and their mechanical/runtime proof surfaces are delivered. - -Local verification: - -- Release build: zero warnings/errors; format verification passes. -- All **2,898 backend cases** pass: 1,679 unit, 198 architecture, four contract and - 1,017 integration, with zero failures/skips; direct TRX counters and the nonempty - assembly checks agree. After the final cleanup repair, the independent security - reviewer reruns the real-API production rendering fact successfully. The final - architecture rerun also passes 198/198. -- The final guarded frontend run passes **420 cases**: 360 web and 60 SDK across two - tested packages, with zero failures/skips/todos. Workspace typecheck/lint, - production build and regenerated SDK snapshot drift checks pass. -- Native socket/TLS, failed-listener cleanup, actual skipped/todo/missing-report - controls and production Client Component import refusal pass. HTML/RSC separation, - eligibility freshness, trace continuity and secret containment use the real API; - they are transport evidence, not a shipped product-page or browser-demo claim. -- Manual changed-document file/fragment validation, added-prose wrapping, - `git diff --check`, strict commit messages and Accepted-ADR/P02d-1–4 history - preservation pass. CI's existing link check covers files, not fragment targets. - -These local runs use Node 22.23.1 and .NET SDK 10.0.302; they do not claim the pinned -CI Node 20.11.0/.NET SDK 10.0.112 run. The P5 PR's actual checks establish that -separate evidence before maintainer handoff. No live protection setting or required -check name changes. This packet adds no database migration or public OpenAPI/SDK -contract change. - -**Next: P02d-6 — Public renderer.** Re-verify G5/G12/G16/G20/G38/G39–G43 against -the delivered transport, then accept its page/state, text-card, theme and -accessibility contracts before implementation. P6 consumes the configured SDK and -preserves uncached rendering and live eligibility. P7 still owns `make demo`, the -two-host browser harness, Lighthouse and phase exit. Phase 02d remains in progress; -P5 does not complete the full walking skeleton or deliver authentication, CMS, -enrollment grants, commerce or production ingress/distributed quotas. - -**CI lint preflight correction (2026-10-09).** The first P5 PR run exposes a -clean-checkout dependency: native launcher lint resolves generated -`.server/ingress.js` before the later build step emits it. Existing local output -hid this ordering gap. Removing that owned output reproduces the precise import -refusal; the web lint command now compiles ingress first, then retains all lint -rules. The staged-web hook follows the same preflight. Full workspace lint passes -from absent generated output; no runtime policy or test count changes. -Two fresh GPT-6.1-sol high reviewers independently approve this narrow correction; -shell syntax, failure propagation, ignored output and staged-file isolation pass. - -**PR handoff — 2026-10-09.** -[PR #26](https://github.com/HodeTech/LearnStack/pull/26) proposes development into -main for maintainer review. Main synchronization uses a normal merge on development -and preserves the validated tree; no branch switch or history rewrite occurs. -The PR's actual required-check rollup owns pinned CI evidence separately from the -local runs above. P02d-5 remains unmerged; P6/P7 delivery is not claimed. - -**Review evidence clarification — 2026-10-09.** The Step 4 and packet-closeout -counts above describe `e580444f0dbaf11151bf008a06a75688f2bd6e4a`: 104 source cases -and 420 frontend cases (360 web + 60 SDK), confirmed by -[CI run 37852875524](https://github.com/HodeTech/LearnStack/actions/runs/37852875524). -The subsequent `5db8daedfd93f816ef23e545b8741ee54395e2f8` remediation adds four -compiler-erasure controls: inline type-only imports/reexports retain runtime edges, -while declaration-level type-only forms are erased. Both inline controls fail -before the guard fix. Two fresh independent reviewers approve the correction. -That tree passes 108 source cases and **424 frontend cases** (364 web + 60 SDK), -with zero failures/skips/todos. All six required checks pass in -[CI run 37855253417](https://github.com/HodeTech/LearnStack/actions/runs/37855253417); -TRX counters confirm 2,898 backend passes, including 846 Docker cases and the -real-API production renderer. These named runs qualify the earlier dated evidence; -they do not rewrite it as a claim about every later commit. - -**Review sanitation correction — 2026-10-09.** Client-supplied `next-url` is -removed from both native header collections and the middleware's downstream -allowlist under ADR-0053's existing client-carrier sanitation boundary. The -middleware control first reproduces its prior forwarding; the real TLS control -checks parsed/raw header removal while retaining successful native admission. -Next uses this carrier for interception routes, which P5 does not implement; -normal RSC/navigation protocol headers remain available. - -The other suggestions do not identify current failures. Port 3000 is the Accepted -local topology; Phase 11 owns its replacement. ADR-0052 limits the API to GET/HEAD, -and the configured caller exposes only those reads; a blanket web-method rule -would also govern scaffold and future Phase 02b BFF/auth paths. The caller consumes -only API origin and secret, never its computed TLS paths; the native launcher alone -reads certificate/key files, resolved against the repository root. - -### P02d-5 external-review remediation (2026-10-09) - -**Current status — Complete and merged (2026-10-09).** The -maintainer approved ADR-0054 and all five correction steps on development. -Runtime, proof and corpus corrections complete both fresh independent review -rounds and verified fixes. Step 5 records full local validation. The -[merge closeout](#p02d-5-merge-and-closeout-2026-10-09) records PR #26's final -head, six required checks and merge verification. Original delivery, proposal and -review notes below remain historical; P6/P7 scope remains separate. - -Review reports are evidence to verify. The triage below compares their claims with -`07016405`, installed Next 15.5.18/.NET 10 behavior and owned isolated reproductions. - -#### Decision package - -[ADR-0054](../decisions/0054-bounded-public-renderer-admission.md) is Accepted — -2026-10-09. It replaces only these ADR-0053 contracts: - -1. Refuse an exhausted known visitor before peer debit; keep unknown visitor - creation peer-gated. Own the actual visitor limiters and coordinate acquisition, - idle retirement and request-result replay. Preserve 60/IP, 600/peer, fixed - windows, no queue, the direct/hop shared namespace and pre-lookup enforcement. - Retain a 600-per-window peer-debit/allocation cap, not a total refusal-traffic - cap. One process-local owner lock serializes acquisition and bounded cleanup - batches; Phase 11 owns contention measurement and upstream protection. -2. Admit GET/HEAD on the current native public/scaffold surface; give other methods - masked no-store `404` before Next. Close all production upgrades; development - retains only required validated HMR. Future BFF/auth routes require explicit - admission in Phase 02b. No public API method or authentication rule changes. - The native rule covers every HTTP path, including middleware-exempt health and - assets; future Phase 06 Server Actions/write routes need their own admission. -3. Preserve inert query values, duplicates and ordering in redirects, allowing the - supported serializer's equivalent percent encoding. Stop promising identical - raw query bytes. Keep raw signed route identity and pinned framework projection. - -The current peer-first order is explicit in ADR-0053 Amendment 3, so this is a -bounded supersession, not a false-when-written correction. Dated navigation is -appended to ADR-0053/0036; this record explicitly replaces G34's accounting order -and G36's query-byte promise only. Their original accepted answers remain -historical; membership-first precedence and P6/P7 open parts remain unchanged. No -new global quota, distributed limiter, database migration, transport-suffix route -alias or schema/API contract is introduced. - -Keep existing valid traceparent continuation. Sampling participation, IPv6-prefix -aggregation and production tracing policy remain Phase 11; they are not tenant -authority. Keep the existing local HMAC key distribution/wire format. Fix diagnostic -containment now; freshness/nonces or a process-specific key require separate -production trust/distribution evidence, owned by Phase 11. - -#### Verified current findings and actions - -| Finding group | Verified result | Action in this PR | -|---|---|---| -| Shared peer budget, B1 | One visitor's 600 requests admit 60 and refuse 540 while exhausting the peer; a fresh visitor is then refused. Bare reversal allocates unknown visitors after peer exhaustion | Implement Accepted ADR-0054; prove refusal fairness, bounded work per refusal and peer-gated allocation independently. Retain the admitted-call/allocation cap; total refusal traffic is outside it | -| Framework endpoint retry | Current global-only wiring charges once. Adding an endpoint policy reproduces a second global debit after success | Save successful and refused request outcomes in the new owner; test actual endpoint-policy retry now | -| Next URL projection, M1 | Valid query values ending `.rsc` are changed by the adapter's full-URL normalization and rejected by the current verifier | Mirror pinned adapter processing, while retaining the signed raw target for route/locale identity. Test query cases and unrelated routes; add no suffix aliases | -| Proxy header sanitation, M2 | Native parsed/raw headers retain `x-real-ip`, bare `x-forwarded` and vendor authority spellings. Current downstream/API allowlists prevent authority escalation | Strip the explicit forwarding/authority carrier set from both collections; prove mixed-case controls and unchanged signed socket identity | -| Framework debug output | Installed Next logs full request headers under `DEBUG=next:*`, including the signed envelope | Refuse/suppress unsafe framework diagnostic configuration before request handling; prove containment with an enabled-debug canary | -| Methods/upgrades | TRACE/TRACK can fail before user middleware. Unmatched production upgrades can remain open because Next expects another WS consumer | Apply the Accepted native GET/HEAD and production upgrade rule; retain proven development HMR, no-store and bodyless HEAD | -| Redirect bytes | Literal apostrophe query values become `%27`; meaning is retained | Apply the Accepted equivalent-encoding contract; test actual runtime Location, not only the helper | -| Authority/source guard, M4 | `new Headers(request.headers)` and `Object.fromEntries(request.headers)` reads escape tracking, including spread of the converted object | Add bounded constructor/conversion tracking, named planted/clean controls and a census of supported tsconfig aliases; fail unsupported local mappings | -| Compiler evidence, M7 | Existing tests measure tsc verbatim emission. Installed Next SWC erases inline type-only imports/reexports | Keep the conservative graph policy; label the tsc proof accurately and add pinned SWC evidence with value/mixed-edge positive controls | -| Ingress fixture lifecycle, M6 | Setup occurs before try/finally; interruption leaves detached children/temp material | Put setup under one idempotent resource owner; cover setup failure, SIGINT/SIGTERM and parent/control-pipe closure | -| Fixture readiness | Ingress readiness can accept a stale 3011 listener; the real-API fixture already preflights its ports | Preflight both owned fixed ports, require owned-child bind/readiness and child liveness. Fail clearly on collision; do not attach to or kill an existing server | -| Fixture TLS/log proof | Ingress inherits TLS/debug overrides and can forget a leak after 64 KiB of later output | Allowlist child environment, explicitly verify TLS, and scan before truncation with chunk overlap and sticky verdicts | -| Renderer cleanup | Broken stdout can raise unhandled EPIPE before finally; ordinary stdin/signal cancellation is already handled | Route output-pipe errors through idempotent cleanup; prove an owned broken-pipe case | -| Upgrade/build containment evidence | Client-side timeout can masquerade as server closure; IPC is not synchronized. Secretless build only proves its declared secretless path | Make timeout fail, await owned IPC observations, add actual closure controls and a nonempty configured-build canary for private asset/diagnostic exclusion | -| Fixed-window tests | Exact accounting over 600 sequential HTTP requests assumes no minute rollover | Add deterministic owner/factory/sweep seams and barrier controls, plus retained real-framework/HTTP proof. Keep production window/limits unchanged | -| Hook/CI/DX | Hook omits `.mts/.cts`; SDK lint claim exceeds invocation; root config/generated-file selection differs; `.server` is formatted | Align explicit lint subjects/parser handling, cover SDK lint, exclude generated output, and add representative failure controls | -| Runtime support | Node 20 is EOL; CI still pins 20.11.0, while local P5 evidence uses 22.23.1 | Pin supported Node 22.23.1 across current tool/configuration carriers, then rerun actual CI. Historical Node 20 evidence stays historical | -| Narrow evidence/consistency | HttpClient merges repeated secrets; `v1.` substring is overly broad; favicon matcher has an unescaped dot; some guard assertions are only nonempty | Add raw-wire repeated-secret and mapped-peer controls, structural token matching, exact favicon matching and named guard assertions | -| Corpus and workflows, M3 | Current owner/status prose and route/seed launch guidance lag delivered G31–38/G44 | Align current documents and skills with accepted ownership; preserve P6/P7 open parts and immutable records | -| ADR disclosure guard | First nonempty Status line is a blockquote in ADR-0052, so CI's current awk misses its Accepted lifecycle | Parse the lifecycle line within Status, ignoring banners; plant Accepted-with-banner controls. Preserve original status/history | - -The Node support finding is verified against the -[official release schedule](https://github.com/nodejs/Release#release-schedule): -20.x reached EOL on 2026-04-30; 22.x remains Maintenance LTS through 2027-04-30. -The [22.23.1 archive](https://nodejs.org/en/download/archive/v22.23.1) identifies -the selected local-tested patch. No particular HTTP-parser CVE/exploit is claimed. - -Ongoing corpus fixes in this preparation cover Architecture 04/05/14/25, -Standards 03/06/07/11/12/15/index, glossary placement and frontend entry READMEs. -G32–37 answer links now point to their actual detail owners. Security Standards -carry the accepted private carrier, five API-hop headers, 10-second/8-MiB bounds, -secret/client/log exclusions and the narrow local Node configuration exception. -Remaining route-skill/seed/hook/CI edits ship with their corresponding code/tests. - -#### Rejected, qualified and later-owned claims - -| Claim | Disposition and reason | -|---|---| -| IPv4-mapped peers fail `IPNetwork.Contains` | Refuted on current .NET 10; the loopback IPv4 network contains mapped loopback. Add a pinning test, no parser workaround | -| Invalid visitor metadata violates an “only 600” rule | Refuted: existing policy specifies two budgets and peer-IP fallback. Clarify both debits; the proposal changes only exhausted-visitor accounting | -| Direct `.rsc`/segment paths must become public aliases | Not established for the supported non-minimal Node mode; segment cache is not enabled. Fix the valid query bug without broadening route identity | -| Plain `{...request.headers}.host` is a Next authority escape | Refuted for WHATWG Headers; it does not create a string host property. Converted plain-object spread remains a real guard gap | -| TRACE's ordinary framework 500 lacks no-store | Refuted by installed Next error rendering. Native refusal still avoids unsupported-method framework dispatch | -| Fixed 3000 is an accidental product port | Refuted: Accepted local topology. Test collision must fail rather than reuse a foreign listener. Phase 11 owns production topology | -| `make demo` is falsely claimed shipped | Refuted: README assigns it to P7. Do not add P7's target as a P5 repair | -| OpenSSL is undocumented; every PEM needs a global ignore | Refuted/scoped: prerequisites name OpenSSL and `.data/` protects accepted private certificate paths. Broad PEM ignores could hide public fixtures | -| All parent-death cleanup/TLS/log scanning is absent | Overstated: the real-API harness already watches stdin/signals, allowlists environment and scans before truncation. Fix its verified EPIPE path and the separate ingress deficiencies | -| Slowloris waits forever | Not reproduced; default Node timeout closes the reported case. Keep production timeout/topology tuning in Phase 11; enforce bounded fixture waits now | -| PID reuse warrants skipping every exited group leader | Rejected fix: surviving descendants require group cleanup. Reduce stale handles after confirmed group absence and retain the surviving-descendant control; no unrelated-group kill was reproduced | -| Envelope has no replay expiry | True protocol fact, not a supported-listener replay bypass. Submitted envelopes are replaced; Step 2 addresses the verified debug leakage. Phase 11 owns production replay/key lifecycle | -| Restart every visitor trace, change sampling, aggregate IPv6 prefixes | New observability/rate policies, not demonstrated P5 defects. Preserve accepted continuation; Phase 11 owns these choices | -| New static/auth/robots/sitemap paths must already bypass admission | P6/G40 and Phase 02b own their explicit namespaces. Existing exact exclusions remain; correct only the favicon regex defect now | -| Bootstrap reuse / Link prefetch already required in P5 | No current product pages exist. P6 owns request-local consumption/prefetch choices before page code, including call-count evidence; no caching or shared bootstrap is authorized | -| SDK response-parser/body/Retry-After notes | SDK is inherited from P4 and outside this PR's changed transport. P5's configured caller already bounds decoded bytes/deadline; re-verify SDK contracts with P6 consumers rather than change them speculatively | -| PlatformAdmin is required by `make public-api` | Refuted: optional credential is copied only when present; composition registers its lazy guarded source and boots without it. Public reads use the app role. Prove launch without it; do not grant public paths bypass access | -| Merge versus squash blocks remediation | Neither changes the code contract. Maintainer chooses merge mode; dated source/CI references remain scoped evidence, not a demand for a merge strategy | -| CLAUDE status length / model diversity proves a runtime bug | No. Keep task-specific current state honest and evidence scoped; broad guidance restructuring and unsupported transcript claims are not corrective production changes | - -Historical ADR-0053 delivery amendments remain intact. Acceptance appends the -bounded supersession note and clarifies ADR-0036's existing navigation wording -through dated navigation, preserving old text. CI currently checks relative -file targets, not anchors; keep manual anchor evidence labeled honestly. No new -required check or protection weakening is proposed. - -#### Implementation and review sequence - -Maintainer approval on 2026-10-09 authorizes these five correction steps on -development. The current status above and per-step records below own progress. -For each: -implement and validate, commit, run two fresh independent review rounds, validate -and commit confirmed fixes, then proceed automatically. Preserve main and unrelated -local work; do not rewrite the branch or merge PR #26. - -1. **Coordinated anonymous admission.** Implement the owned visitor limiter and - cleanup/retry semantics; deterministic accounting, parallel last-permit/creation, - safe retirement, endpoint-retry, selected Retry-After, cancellation/disposal and - real HTTP controls. Replace the named peer-refusal accounting test identified in - ADR-0054, retain admitted-traffic controls, and prove bounded per-refusal work, - non-overlapping/eventually complete sweeps and shutdown/acquisition safety. -2. **Native ingress and URL boundary.** Fix pinned projection, header sanitation, - debug containment, method/upgrade admission, query wording/Location proof, - powered-by and exact matcher. Retain real HTML/RSC, valid TLS and development HMR - controls; verify protocol headers through the actual middleware path. -3. **Fixture reliability and containment.** Resource-own setup/termination/EPIPE, - synchronize owned readiness/upgrades, enforce TLS/env allowlists and sticky - scanning, add configured-build canary and structural-token controls. Mutants for - omitted cleanup, early leaks, disabled TLS checks, stale listeners and unclosed - upgrades must fail with an independent clean control. -4. **Source/runner/tooling proof.** Close constructor/conversion and alias gaps, - make compiler claims exact, align lint/hook/formatter subjects and Node pins, - fix lifecycle parsing and strengthen narrow evidence controls. Keep every guard - falsifiable; an empty production client-component census is not bundle evidence. -5. **Corpus and PR closeout.** Update current skills/seed/setup/standards/catalogue - and ADR navigation with actual enforcement. Run applicable full Release suites, - lint/typecheck/build, production socket/TLS/rendering fixtures, SDK drift, - Markdown links/anchors/width, immutable-history and strict commit checks. Push - development, verify all six required checks on the exact new head and update - PR #26's description/evidence for maintainer review. - -No remediation acceptance or passing-test count is inferred from the earlier -`07016405` CI run. Preparation checks and independent document reviews are recorded -after they actually run; implementation evidence belongs to the five steps above. - -#### Remediation Step 1 — Coordinated anonymous admission - -**Complete — 2026-10-09; both independent review rounds passed.** The API owns actual -visitor fixed-window limiters, serialized acquisition and bounded periodic -retirement. Exhausted known visitors return their unchanged refusal metadata -before peer debit; peer refusal prevents unknown visitor allocation. Successful -and refused HTTP outcomes are copied into independent request-local leases, -including ASP.NET's retry after an endpoint policy refuses. Teardown closes -admission, joins active sweeping and disposes children outside the owner lock. - -Focused controls cover both final-permit races, single creation, both-budget -Retry-After selection, cancellation, replay/lease independence, more than two -sweep batches, non-overlap, full-quota idle retirement, actual .NET automatic -replenishment and concurrent teardown. Real HTTP accounting freezes only test -budget replenishment, retaining actual fixed-window implementations, so minute -rollover cannot invalidate exact accounting. The application-role/read-only -controls retain their original runtime path. No incoming-traffic or production -throughput bound is claimed. - -**Validation — 2026-10-09.** Strict Release solution build passes with zero -warnings/errors. All 2,922 .NET tests pass without failures/skips: 1,702 unit, -198 architecture, four contract, 172 Docker-free integration and 846 Docker -integration. The focused accounting/lifecycle set passes 27 cases; the real -endpoint-retry proof and 17 trusted-visitor HTTP cases pass. TRX execution/zero-skip -checks and changed-source format verification pass; the format workspace loader -reports a warning without a formatting violation. Corpus consistency is rechecked -at 5/5 after the status edits. - -**Review round 1.** Fresh GPT-6-astra xhigh runtime/security review approves the -implementation; fresh GPT-6.1-sol high proof/corpus review identifies one confirmed -test gap: eventual traversal did not constrain lock-batch size. The strengthened -300-entry control blocks the first outside-lock disposal, observes exactly 128 -idle inspections, admits another request before release and verifies complete -exact-once traversal. An actual `int.MaxValue` batch mutation fails the intended -128-versus-300 assertion; restored-source focused tests pass 27/27 with zero -skips. The production limiter is unchanged. The correction is committed as -`a107df5`, following implementation commit `208d64f`. - -**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high -proof/corpus reviewers approve the corrected tree. Their independent runs pass -56 focused unit cases and one endpoint-retry integration case, and 27 focused -accounting/lifecycle cases plus the endpoint retry respectively, with zero skips. -The remaining current-sequence status sentence is aligned in this closeout; -no additional production change is needed. Step 1 is complete; Step 2 starts next. - -#### Remediation Step 2 — Native ingress and URL boundary - -**Complete — 2026-10-09; both independent review rounds passed.** Native HTTP admission -accepts GET/HEAD before Next on every callback path; other callback methods receive -masked no-store 404. Node retains parser-level refusals, including TRACK, and no -CONNECT tunnel is admitted. Production closes every upgrade. Development permits -only exact validated GET HMR, bounds its initial 101 handshake and closes missing, -failed or ignored delegation while retaining established HMR connections. - -The launcher disables framework DEBUG before importing Next, including later -framework dotenv loading. Forwarding/authority carriers are removed from both -parsed and raw headers. `poweredByHeader` is disabled; the favicon matcher uses a -literal dot. URL verification applies pinned Next's full-URL `.rsc` normalization -before parsing and `_rsc` removal, then returns the signed raw context. Route and -locale admission still refuse suffix aliases. Redirect proofs compare actual -Location authority, path and ordered decoded query pairs, including apostrophes. - -Flight protocol preservation is tested through the real adapter and middleware; -the direct middleware mock no longer claims to exercise adapter-hidden headers. -The disposable route emits only named booleans, and its five GET probes plus HEAD -must produce exactly six live API bootstrap calls. No product route is introduced. - -**Validation — 2026-10-09.** All 469 frontend cases pass through the workspace -outcome guard (409 web, 60 SDK), with zero skips/todos. Lint and typecheck pass; -production build passes. The real API/PostgreSQL production-rendering case passes -1/1, including the six protocol/bootstrap calls and existing tenant isolation, -trace, freshness and containment. The actual native TLS fixture passes all-path -method/HEAD, matcher, query, production closure, DEBUG and retained development -HMR controls; its original planted cleanup control also passes. Corpus consistency -passes 5/5 and diff checks are clean. - -The DEBUG canary caught a pinned-library detail during implementation: an empty -DEBUG is deleted by debug initialization. The final nonempty `-*` exclusion is set -before importing Next, survives initialization/dotenv and is exercised with enabled -process and dotenv canaries. Next development route discovery also requires a -fixture-owned source copy, whereas production uses its existing compiled output. -These are verified fixture/runtime corrections, not new product contracts. - -**Review round 1.** Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol high -proof/corpus reviewers approve implementation commit `458a1dd` without verified -findings. Independent focused runs pass 257 and 218 frontend cases respectively; -the runtime reviewer also compares ten targets with the installed Next adapter. - -**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high -proof/corpus reviewers approve the same tree without verified findings. Focused -runs pass 125 and 218 frontend cases; the latter also passes all five corpus -consistency cases. These reviewers inspect the committed fixed-port fixture -proofs without rerunning them. Step 2 is complete; no corrective runtime commit -is required. Fixture ownership/containment and source/tooling remediation remain -Steps 3–4. - -#### Remediation Step 3 — Fixture reliability and containment - -**Implemented — 2026-10-09; independent reviews pending.** Test fixtures share -resource ownership, positive environment construction and bounded sticky output -scanning. Setup occurs inside cleanup ownership; signals, explicit parent control -closure and broken output pipes join the same cleanup before exit. Children stop -before private trees are removed. Process handles coalesce repeated cleanup and -retire permanently after confirmed absence; exited leaders still require cleanup -of surviving descendants. This narrows stale-handle exposure without claiming an -atomic POSIX process-identity signalling API. - -Both fixed ports are preflighted. Readiness requires evidence from the actual -owned child before accepting a healthy response; a foreign listener is neither -reused nor stopped. HTTPS, raw TLS and WebSocket clients explicitly verify trust. -Wrong-CA and wrong-name controls fail before bootstrap. Private-output verdicts -remain sticky after truncation and across chunk boundaries; structural envelope -checks distinguish ordinary API/version text from private wire values. - -The real renderer builds with nonempty private configuration and an actual -public-only Client Component. A successfully compiled secret-leaking component -fails emitted-asset scanning; the restored component builds cleanly with nonempty -client output. The API observes no request during compilation. Existing SDK, -host/trace isolation, six Flight/bootstrap calls, same-process freshness and stock -launcher refusal remain covered. Actual stdin closure and EPIPE controls require -exit 1 and removal of the owned temporary build tree. - -**Validation — 2026-10-09.** The guarded frontend runner passes 491 cases -(431 web, 60 SDK), with zero skips/todos; workspace lint and typecheck pass. -`PublicServerRenderingTests` passes 15/15: the real production path, twelve -structured-log controls and two actual parent-pipe cleanup cases. The strengthened -pipe controls also pass a focused rerun. Release integration build reports zero -warnings/errors; changed-source format verification passes with a workspace-load -warning. The shared scanner/environment/owner and process-handle controls pass -27/27. Corpus consistency passes 5/5 with zero failures/skips, and ADR-0054's -change is insertion-only. - -The real ingress source-mutant matrix passes 18/18: early OpenSSL failure, -asynchronous bootstrap refusal, setup/omitted cleanup, both signals, explicit IPC -closure, EPIPE, secure environment/TLS and disabled-TLS rejection, benign large -output and early split leaks, stale/bind failures, and upgrade closure/refusal. -Each intended failure is checked by its own oracle; cleanup rescue runs only -after the absence verdict and never re-signals a saved PID after confirmed absence. -Independent normal native/TLS/HMR verification remains the clean control. - -**Review round 1.** Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol high -proof/corpus reviewers inspect `e2f92b7`. Three verified findings are corrected: -failed child cleanup now retains the private tree, final child output drains -before shutdown containment, and token boundaries at chunk ends wait for a real -delimiter or EOF. A shutdown-only source mutant and split malformed-MAC controls -prove the fixes; the early-output control now includes an actual delimiter. -Focused helpers pass 31/31, the real ingress matrix passes 19/19 and the guarded -frontend runner passes 495 cases (435 web, 60 SDK), with zero skips/todos. -Changed-source lint passes. The original implementation counts above remain -historical. The real API/PostgreSQL renderer rerun also passes 15/15. - -**Review round 2.** Fresh GPT-6-sol xhigh runtime/security and GPT-6.1-sol high -proof/corpus reviewers approve `131a933` without actionable findings. The runtime -reviewer independently passes 31 helper/process-group cases, the normal real -native ingress and all 19 source-mutant controls. The proof reviewer independently -passes 31 helpers and five Release corpus cases. Step 3 is complete after both -rounds and verified fixes. Source/tooling and final closeout remain Steps 4–5. - -#### Remediation Step 4 — Source, runner and tooling proof - -**Complete — 2026-10-09; both independent review rounds passed.** Bounded AST tracking -covers global Headers constructors, converted records, constant aliases, -destructuring and converted-record spread, with named clean/dirty controls and -real public-entry mutations. Plain WHATWG Headers spread stays inert. Effective -inherited tsconfig paths and workspace exports are checked against the resolver; -unsupported production module extensions fail explicitly. Real pinned Next SWC -and TypeScript verbatim emission are separate proofs; the conservative graph -keeps inline type-only edges even where SWC erases them. No production Client -Component is invented to make the census appear nonempty. - -Web CI and staged lint share one source/script/root-config census, with generated -output/declarations excluded explicitly. Native `.mts`/`.cts` parsing is explicit; -the hook also invokes SDK/UI lint. Root Tailwind configuration now participates -in typecheck; its shared preset declares the existing Tailwind peer dependency. -The lock changes only that importer, without changing a resolved package version. -CI, `.nvmrc`, engine minimum and current setup guidance use Node 22.23.1. Generated -`.server` output is excluded from Prettier. Test discovery refuses symlinked -workspace packages or sources rather than silently skipping them. - -The ADR disclosure job reads the lifecycle declaration inside Status, ignoring -banners and consuming the complete input. A real workflow-block control rejects -an undisclosed Accepted-with-banner edit and accepts its dated disclosure. The -original Accepted ADR status/body/history remains unchanged. - -Raw HTTP proves two actual secret fields reach Kestrel, spend the exhausted -socket-IP fallback and bypass no lookup; one valid field then admits a fresh -visitor. Mapped-peer and noncanonical dotted-tail controls pin .NET behavior. -The actual public-local API launcher starts with only the application credential, -an empty owned user-secret root and no local env fallback, then serves both seeded -hosts through the trusted hop without PlatformAdmin. It uses a dynamic API port; -the accepted fixed renderer topology is unchanged. - -**Validation — 2026-10-09.** The guarded frontend run passes 557 cases (497 web, -60 SDK), with zero skips/todos. Focused source-boundary cases pass 157/157; -lint-tooling/runner controls pass 39/39. Workspace typecheck/lint and frozen offline -installation pass. Seven Python lifecycle/workflow controls pass. The focused -backend units pass 45/45; trusted visitor and real local-launch integration pass -18/18, with zero skips. Release solution build reports zero warnings/errors; -owned backend formatting and diff checks pass. Both fresh review rounds remain -pending; final full regression, real CI and PR closeout belong to Step 5. - -**Review round 1.** Fresh GPT-6-astra xhigh source/security review identifies two -confirmed static-alias gaps: destructured global constructors and separately -bound header iterators escaped the authority guard. Fresh GPT-6.1-sol high -tooling/backend review approves its scope after seven lifecycle controls, -39 tooling/runner cases, 45 unit cases, two real integration cases and web lint. -The correction follows verified global destructuring and gives header iterators -a distinct origin, consumed only by conversion/clone operations. Four planted -violations fail before the fix; named shadowed/inert/iterator controls and both -real render-helper mutations pass afterward. All 171 focused boundary cases and -571 guarded frontend cases (511 web, 60 SDK) pass with zero skips/todos; -workspace typecheck/lint pass. No production consumer exploits either gap. -**Review round 2.** Fresh GPT-6-sol xhigh source/security review confirms the -first-round fixes, then identifies the same static-constructor gap in the -separate API-hop-header setter fence. The correction reuses the verified global -constructor predicate; qualified/aliased/bound setters and a real helper mutation -are refused, while inert/shadowed constructors and the adapter exemption stay -clean. The before-fix run exposes all three setter escapes, the helper escape and -the old shadowed-constructor false positive. All 178 focused boundary cases and -578 guarded frontend cases (518 web, 60 SDK) pass afterward with zero skips/todos; -workspace typecheck/lint pass. Fresh GPT-6.1-sol high tooling/backend review -approves after seven lifecycle, 39 tooling/runner, 45 unit and 18 real integration -cases, web lint and diff checks. The source reviewer independently verifies -`ced7911`: all three setter escapes change from missed to flagged, shadowed/inert -controls stay clean and all 178 boundary cases pass. Step 4 is complete after both -rounds and verified fixes; Step 5 owns final corpus/CI/PR closeout. - -#### Remediation Step 5 — Corpus and PR closeout - -**Local closeout complete — 2026-10-09; both independent review rounds passed.** -Current architecture/security prose and Phase 02b G14 now reflect delivered -ADR-0054 behavior. CLAUDE, README and the ADR/roadmap indexes link this current -record instead of maintaining separate remediation-step status lists. Original -Accepted ADR bodies and dated delivery evidence remain unchanged; ADR-0054's -new delivery navigation points here. - -Route guidance identifies the API as tenant/organization authority and marks the -Keycloak/session example as Phase 02b work requiring explicit ingress admission. -Seed output points to manual hosts/CA/leaf preparation and the paired public -launchers, without claiming P6 pages or P7's demo. Setup/test guidance distinguishes -random Testcontainers PostgreSQL ports from fixed renderer ports, and current -deployment-mode defaults from the Phase 02c Hub adapter. The seed-role diagnostic -correctly distinguishes FORCE RLS ownership from a privileged bypass credential. - -**Final local validation — 2026-10-09.** Strict Release solution build reports -zero warnings/errors. All 2,940 .NET cases pass: 1,705 unit, 198 architecture, -four contract, 172 Docker-free integration and 861 Docker integration, with zero -failures/skips. Actual TRX counters and the nonempty/no-skip runner are checked. -All 578 guarded frontend cases pass (518 web, 60 SDK), with zero skips/todos. -Workspace typecheck/lint/build and regenerated SDK drift checks pass. Native -HTTPS/Next verification and all 19 independent failure controls pass; the full -Docker suite includes real production HTML/RSC, configured-build containment, -parent-pipe cleanup and the actual app-only API launcher. - -Seven ADR lifecycle/workflow and 14 OpenAPI CI controls pass. Both compose -projections validate with and without the gated profile using the public example -configuration. Full backend format verification passes with a workspace-loader -warning and no formatting violation. Post-acceptance ADR changes are insertion-only. -The strict commit hook, changed-document relative links/fragments, added-prose -wrapping, corpus consistency and diff checks pass after the closeout edits. -Fragment verification is a manual local audit; CI's link job checks file existence. -All six live required checks and strict protection remain configured. [PR #26](https://github.com/HodeTech/LearnStack/pull/26) -records their execution on the final published head and the final PR description; -these local checks do not imply a successful remote run. - -Remaining scope is unchanged: P6 owns product pages, request-local bootstrap reuse, -prefetch decisions and accessibility; P7 owns the browser/demo/Lighthouse harness. -Phase 11 owns distributed/edge limits, contention/load evidence, production -topology, replay/key lifecycle and tracing participation. These corrections add no -API schema, database migration, tenant resolver, authentication flow or Hub crossing. - -**Review round 1.** Fresh GPT-6-astra xhigh corpus/governance and GPT-6.1-sol high -DX/evidence reviewers verify `2b5b6ac` against current source and actual reports. -One confirmed Minor finding is fixed: a second mutable step-status sentence still -said Step 4 reviews/Step 5 were pending. It now points to the section's current -status and per-step records. Whole-PR added-prose verification also wraps two -long standard/catalogue lines. Both reviewers approve after the verified -correction; no production change is needed. Round 2 and exact-head CI remain pending. - -**Review round 2.** Fresh GPT-6-sol high corpus/governance and GPT-6.1-sol high -DX/evidence reviewers approve `869145e` without actionable findings. They -independently confirm the real TRX/frontend/native-control results, append-only -ADR history, current API authority, local TLS/port behavior and P6/P7/Phase 11 -ownership. Link/fragment, prose, strict commit and diff checks pass; the five -Release corpus cases pass with zero skips. The later 578-case workspace report -is the frontend evidence; the earlier 557-case run remains historical. -Both rounds and verified corrections are complete. Development is the only -working branch; PR #26's final head/checks and description own remote closeout. - -**Preparation verification — 2026-10-09.** Independent GPT-6-astra xhigh security -and GPT-6.1-sol xhigh corpus reviews find no remaining major issue in the proposal. -Confirmed wording/header/ownership corrections are applied. Release -`CorpusConsistencyTests` pass 5/5, with zero failures/skips. Manual inspection of -all 18 changed/new Markdown files resolves 1,226 relative links and 441 fragment -targets; added prose wrapping and `git diff --check` pass. Existing Accepted ADR -files are unchanged. These are proposal/document checks, not runtime remediation -or new CI evidence. - -**Second independent proposal review — 2026-10-09.** Fresh GPT-6-sol xhigh design -and GPT-6.1-sol high corpus reviewers approve `d8d540a` for maintainer decision -approval with no remaining actionable findings. The design review independently -checks zero-permit framework behavior and actual redirect value/order preservation. -This closes the two proposal-review rounds; ADR-0054 remains Proposed and dependent -implementation still requires the maintainer's explicit approval. - -**External ADR review clarification — 2026-10-09.** All six findings are verified -against the current limiter, HTTP tests, native launcher and app route census. -ADR-0054 now distinguishes the admitted-call/allocation budget from total refusal -traffic, names the test whose peer-debit expectation must change, and specifies -the process-wide lock, refusal metadata precedence and lifecycle proof obligations. -It records native admission across middleware exemptions, separate identification -control and the missing carrier/reference links. The app currently has GET health -and no POST handler or Server Action; real launcher controls remain implementation -obligations. Prior reviews/counts remain historical. ADR-0054 stays Proposed; -these documentation clarifications accept no decision and deliver no runtime fix. -Release `CorpusConsistencyTests` pass 5/5, with zero failures/skips. The two changed -Markdown files resolve 456 relative links and 283 fragment targets in a manual -audit; added prose wrapping and `git diff --check` pass. All phase text outside -this remediation section and every Accepted ADR file remain unchanged. - -**Clarification review closeout — 2026-10-09.** Two fresh independent rounds review -`1a7c6fd`: GPT-6-astra xhigh / GPT-6.1-sol high first, then GPT-6-sol xhigh / -GPT-6.1-sol high. Both rounds report no actionable design or corpus findings after -checking the changed contract against source, existing tests and pinned framework -behavior. This approves the revised proposal for maintainer decision review; -it does not accept ADR-0054 or establish runtime remediation/CI evidence. - -### P02d-5 merge and closeout (2026-10-09) - -The maintainer merged [PR #26](https://github.com/HodeTech/LearnStack/pull/26) at -2026-10-09 15:45:36 UTC. GitHub records final PR head -`f09a4edf3e00e7043f6775642e10e40024ab9393` and merge commit -`863f5c1b0051c318a0326357c2fb65dded75afca`. The merge's second parent is that -head, and both commits have the identical tree. Development is fast-forwarded to -the verified merge without changing branches or rewriting history. - -- All six required checks pass on the - [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/37943884658). - Downloaded TRX confirms **2,940 passed, zero failed or skipped**: 1,705 unit, - 198 architecture, four contract, 172 Docker-free integration and 861 Docker - integration. Frontend CI confirms **578 passed** (518 web, 60 SDK), zero - skips/todos, and successful typecheck, lint, production build and SDK drift. -- Native HTTPS/Next verification and all **19 failure controls** pass in CI. - Real API/PostgreSQL HTML/RSC, build containment and parent-pipe cleanup proofs - remain part of the Docker suite. These are transport/runtime proofs, not P6 - product-page or P7 browser/Lighthouse delivery. -- The final review correction isolates fixture Git/hook environments from inherited - `GIT_*` variables and reconciles README/catalogue status. Eleven tooling and - seven ADR workflow cases pass locally under both invalid inherited Git settings - and the normal environment, with typecheck, lint, format and link checks clean. - The original four steps and five remediation steps retain their recorded - independent review rounds and verified fixes. -- Read-only branch-protection verification confirms the same six required Actions - contexts and `strict: true`; no protection setting changes. - -All six required checks also pass in the -[merge-commit run](https://github.com/HodeTech/LearnStack/actions/runs/37954123158). -Independently downloaded merge-run TRX confirms the same 2,940 passing .NET cases -with zero failures/skips. Frontend logs confirm the same 578 guarded cases and -19 ingress controls. Both runs use the delivered Node 22.23.1 pin; the deferred -Lighthouse job remains owned by P02d-7. - -**P02d-5 is closed.** The trusted native ingress, fair known-visitor accounting, -bounded configured caller, live-host/locale entry, uncached rendering policy and -source/runtime controls are delivered under ADR-0053/0054. No database migration, -public API schema change or authentication/Hub flow is added by this packet. - -**Next: P02d-6 — Public renderer.** Its decision pass has not started. Re-verify -G5's unavailable-band behavior, G12's page states, G16's rendering part, G20's -subjects, G38(b,c) and G39–G43 against the delivered API and transport before -implementation. The packet owns catalog, course-detail/outline and lesson pages, -UI messages, ordered text-card rendering, safe theme injection, language/SEO -metadata, page/error/empty/locked states and accessibility checks. Request-local -bootstrap reuse and prefetch policy must also be settled before page consumers. - -P02d-7 owns `make demo`/stop behavior, the two-host browser/full-stack harness, -Lighthouse activation and phase exit. Phase 11 owns production/distributed limits, -load evidence, ingress topology, replay/key lifecycle and tracing participation. -Phase 02d remains in progress; neither remaining packet nor Course Marketplace -commerce is delivered by this closeout. Earlier dated records remain unchanged. - -**Documentation-only closeout validation.** Five local Release corpus cases and -seven ADR lifecycle/workflow controls pass, with zero failures/skips. The eight -changed Markdown files resolve 901 relative links and 393 fragments in the local -audit; prose wrapping and diff checks pass. ADR-0053/0054 changes are insertion-only; -earlier dated delivery records and P02d-1's decision/scope suffix are byte-preserved. -This closeout changes no production code or accepted decision. - -### P02d-6 decision package (2026-10-09) - -**Accepted — 2026-10-09, re-verified against `2d821c4`.** P02d-1–5 are complete -and merged. The maintainer explicitly approved revised -[ADR-0027](../decisions/0027-frontend-i18n.md), all gate answers and the status/URL -tradeoff below. The decision commit precedes implementation and claims no product -page or dependency delivery. Earlier preparation/review records remain historical. - -#### Reviewed inputs and verified premises - -The documentation pass covers the platform vision and MVP boundary; Principles; -the glossary and decisions index; ADR-0008/0009/0018/0035/0036/0040/0042/0043/ -0050/0051/0052/0053/0054; Localization, Frontend Architecture and Tenant -Customization Model; Standards 03/06/07/08/09/11/13/15/16/21; Phase 02d and its -Phase 04/05/06/07 consumers. The `implement-task`, `add-frontend-route`, -`add-i18n-key`, `write-adr` and commit workflows are included. - -Code verification covers the public SDK DTOs/results, native ingress and verified -entry, configured caller, middleware, root/public layouts, CSS tokens, renderer -registry, frontend source fences, guarded runner and real API/Next fixture. -In particular: - -- Four public GET operations and their eligible alternates already exist. Pages - need no new endpoint, write method, entity, migration, tenant id or Hub call. -- The only implemented lesson presentation is ADR-0051's ordered plain-string - `default-card`. The larger registry does not implement additional renderers. -- Public theme DTO validation currently checks string shape, not color grammar. - Safe HTML injection must validate the complete four-token value again. -- Middleware consumes and discards live site bootstrap. `React.cache` can share - RSC work within a render, not between middleware and RSC execution. -- The production fixture currently injects a disposable transport-probe page. - It proves P5 transport, not the actual P6 product pages. -- Root HTML still has fixed English/platform metadata. No UI catalogue/runtime - is installed. Existing seed inventory does not fill a normal 20-item page. - -The pass corrects current mutable carriers that prematurely claim product pages, -leave the delivered G12 interface open, or require an outbound URL sink in this -plain-text packet. Accepted ADR bodies and shipped delivery records are unchanged. - -#### P02d-6 accepted answers - -| Gate / part | Accepted answer | -|---|---| -| G5, G12 page states | Preserve public DTO eligibility and exact pins. Omit a null level; localize an unavailable level. Unavailable content has a bounded placeholder, never raw JSON or another revision. Distinguish empty catalog, empty public outline, restricted outline, empty ready content and unavailable content. | -| G16(g) | Render the complete safe tenant palette independently of plan. The effective `showPlatformAttribution` value alone controls platform attribution; no plan inference in the renderer. | -| G20 subjects | Census production frontend TS/JS and JSON, including renderer/message values, against the exact decoded seed identity literals from G20(a). Preserve the accepted platform-built-in and development/test exemptions, without a blanket catalogue exemption. P7 implements the existing registered rule across backend and frontend. | -| G38(b,c) | Vitest covers synchronous views and pure mappings; real production HTML/RSC tests cover async pages. Extend the existing required Docker integration fixture to unchanged product pages while preserving the isolated P5 transport probe. P7 still owns shared demo/browser/Lighthouse activation. | -| G39 | ADR-0027 is Accepted at first use: exact next-intl 4.14.9, server-first configuration using shared verified request admission, app-local `src/i18n/messages/{en,tr}/public.json`, dotted feature UI keys and one checked ICU catalogue contract. Backend `lockey_*` remains a separate wire namespace; the web app owns closed page-outcome mapping, not the SDK. No i18n routing middleware or preference cookie. | -| G40 | Three fixed content routes, minimal tenant chrome, both opaque pagination surfaces, exact-locale metadata and explicit page states. The maintainer explicitly approved the status/navigation choice below. | -| G41 | Render only the API's ordered plain-string fields through app-local synchronous components in `apps/web/src/components/public/`. Unsupported renderer or unresolved presentation renders the bounded fallback. No HTML, Markdown, linkification, authored URL sink or new primitive. | -| G42 | Emit a server-generated style element containing only four fixed `--ls-*` color properties after atomic `#rrggbb` validation. Null or malformed theme retains the entire existing CSS default palette. No per-token merge, style attribute, URL, font or organization override. | -| G43 | Enforce applicable jsx-a11y rules at error severity with actual-config planted controls; assert visible semantics/languages/titles. Catalog → course → lesson is a critical flow requiring keyboard, focus, reflow, contrast and a real screen-reader smoke record. Status promotion occurs with enforcement, not acceptance. | - -UI catalogue fallback is not content fallback. An enabled language without an -authored UI catalogue remains admissible; UI groups and API-resolved labels carry -their actual language. Document language/direction follow the admitted route as -specified by ADR-0027. A test-owned enabled RTL locale and eligible content prove -document direction and English UI fallback language independently, without -rewriting the historical seed or promising an Arabic UI catalogue. No tenant -identity selects markup, translations or fields. - -#### G40 status and navigation decision - -Pinned Next **15.5.18** was exercised in an owned disposable production fixture, -without modifying this repository. These are planning experiments, not passing -product tests: - -| Strategy | Observed initial document | -|---|---| -| `notFound()` below a loading boundary | Streamed HTTP 200 with not-found digest | -| Await resource outside child loading, then `notFound()` | HTTP 404, but generic error HTML without visible localized fallback or root `lang`/`dir`; fallback text exists only in Flight | -| Remove loading entirely | The same generic HTTP 404 error document | -| Local Suspense / access-fallback boundary | Visible fallback with HTTP 200, not a hard 404 | -| Await lookup, redirect to an explicitly admitted fixed error page; middleware supplies its 404 status | Local HTTP 307 followed by visible localized HTML 404 with root language/direction and no-store; HEAD is bodyless | - -The maintainer accepted the last strategy, **including its URL/status tradeoff**. -Root/route admission awaits the request-cached resource -before emitting a document shell. A missing/hidden resource redirects to the -same host's fixed `/{locale}/status/not-found` page, which middleware admits only -after live host/locale validation and marks HTTP 404. That page is ordinary -server rendering, not a thrown `notFound()`. It echoes no original slug, query, -cursor or failure detail. Its title/robots are localized and noindex; it has a -catalog recovery link and the same safe theme/chrome. It never queries Education. - -The original request is **307, followed by 404**, and the browser URL changes. -This is not a claim that the original document returns a direct 404. The -acceptance commit updates G40's completion criterion to name that exact chain and -adds this error namespace to the entry matrix and route skill. Middleware's -existing masked -unknown-host/provenance refusals remain direct, neutral responses. No new signed -data carrier, shared bootstrap cache or outbound header is introduced. - -Returning a localized HTTP 200 error as though it were a 404 is rejected. A -middleware content preflight followed by another content read is also rejected: -it costs a fourth call on every success and still races the later read. A new -authenticated DTO-transfer protocol is not justified for this packet. Preserving -the original URL with a branded direct 404 would require a separately designed -response-ownership change; it is not silently promised by this decision. - -Metadata, layout and page use the same request-local resource loader. Layouts do -not serialize child execution, so each page honors the loader result itself. -Required `loading.tsx`/`error.tsx` files remain, but no loading boundary may flush -the document before redirect admission. Loading UI is not promised during that -initial pre-admission wait. Unexpected framework errors retain the framework's -pre-stream 500 / post-stream 200 behavior; `error.tsx` cannot set arbitrary status. - -Known content-call failures use controlled, translated, noindex page states: -invalid cursor → explanation and a relative reset link; 429 → retry-later state; -transport/invalid response/unavailable API → unavailable state. These are ordinary -HTTP 200 representations, not claimed HTTP 400/429/503 responses. Bootstrap -refusals retain middleware's real 404/429/503 and bounded Retry-After. A fresh -bootstrap failure on the error-route request remains that neutral refusal rather -than inventing a tenant theme or configuration. A closed mapping selects owned UI -keys for supported outcomes; unknown codes/failures use the unavailable state. -No Problem Details message key, title, field error or parameter becomes a lookup -identifier or visible copy. - -#### Routes, pagination, metadata and chrome - -- Keep `/{locale}/courses`, `/{locale}/courses/{slug}` and - `/{locale}/courses/{slug}/lessons/{lessonSlug}`. Fixed section names remain until - Phase 06; the platform placeholder leaves the public product path. Existing - exact `/studio` and `/portal` scaffolds remain without invented authentication. -- Use ordinary same-host relative anchors for product navigation, including - pagination: no automatic prefetch and no reliance on retained client Router - Cache. A new document request re-reads current API state. -- Parse only owned pagination parameters from the verified raw signed target; - observed Next `searchParams` is not their authority. Refuse duplicate, empty, - malformed or oversized owned values. Cursors stay opaque and are never decoded - by the renderer. Catalog uses `cursor`/`limit`; outline uses - `lessonCursor`/`lessonLimit`, with the API's bounds and a default page size 20. -- Show restart/next links as applicable; do not fabricate a previous cursor. - A test-owned inventory above the page bound proves both pagination surfaces; - do not reduce the product page size or rewrite the historical seed inventory. -- A restricted course shows marketing metadata and a translated access notice, - with no lesson count, lesson link, purchase/login/enrollment control or body. - An empty public outline is distinct. Missing optional text is omitted. -- Minimal chrome contains tenant display name, catalog navigation, skip link and - conditional platform attribution. Full menus, logo/media, authored errors, - preview, organization theme overrides and Studio editing remain Phase 06. -- Canonical and Open Graph URLs use only the verified live host, existing HTTPS - listener convention and validated local segments. Course/lesson hreflang uses - the API's actual eligible alternate slugs, never the current slug substituted - into another locale. Catalog uses enabled locales. Paginated views are noindex - with the cursor-free first-page canonical; error states are noindex with no - misleading resource alternates. Metadata shares the same data read as the page. - -#### Rendering, theme and accessibility detail - -Course lists use semantic lists; ordered outlines use ordered lists; field cards -use definition lists with authored order and language-bearing labels. Each page -state has one main, one descriptive h1, sequential headings, a skip target and -visible keyboard focus. Long unbroken strings wrap and logical CSS supports RTL. - -Strings resembling scripts, HTML, `javascript:`, `data:` or HTTP URLs remain -escaped, inert text. Absent optional fields render nothing. Unknown composites -and unavailable content emit only bounded placeholders and at most one diagnostic -per request containing a count/state, not field values, keys or private context. -The original G41 candidate's integer/boolean/enum/taxonomy expansion is not -authorized by ADR-0051; those richer primitives remain Phase 04/05 and Phase 06. - -The theme emitter admits the complete four-color grammar before producing fixed -CSS. Foreground/muted text retains its 4.5:1 background requirement. Primary has -only a 3:1 background guarantee, so normal text links use foreground plus an -underline; do not assume white text on primary is accessible. Primary may supply -non-text focus/border accents where its contrast is sufficient. CSP delivery -remains Phase 11; output must be safe without it. - -Manual evidence names commit, environment, both hosts/locales, keyboard path, -focus, 320 CSS px reflow/zoom, long strings, contrast and the screen reader used. -DOM assertions do not replace that assistive-technology smoke. If it cannot be -performed, the record stays pending and packet completion is not claimed. -Full Playwright/axe remains Phase 06; Lighthouse activation remains P02d-7. - -#### Request accounting and validation - -Normal content document: middleware bootstrap + request-local RSC bootstrap + -one shared content operation = **three API calls**. A missing document followed -to the accepted error page adds two bootstrap calls = **five total**. Repeated -metadata/layout/page consumers must not add calls; the next incoming document -must re-read. No retry or shared validated-DTO cache is added. - -The existing 60-call visitor and 600-call peer windows therefore give theoretical -ceilings of 20/200 successful three-call documents before other calls, not page -throughput promises. No limiter number, deadline, byte cap or partition changes. -Phase 11 owns production/distributed capacity and measured optimization triggers. - -The actual-page fixture must retain learnstack_app, RLS/read-only transactions, -native HTTPS ingress, closed hop headers and existing containment/failure controls. -Keep the synthetic P5 probe in a separate mode so its catch-all cannot shadow -product routes. Assert visible HTML/DOM separately from Flight strings: status, -language/direction, headings, theme, attribution, both hosts/locales, cross-tenant -absence, overlapping concurrent requests across both hosts/locales, freshness in -one process, controlled failures, pagination, exact schema swaps and inert values. -Verify the 307→404 chain and no direct internal bypass. -These HTTP/RSC proofs are not a browser end-to-end claim. - -#### Accepted implementation steps - -0. **Decision commit.** Accept approved ADR/gate parts; reconcile every normative - carrier and the changed G40 status criterion before writing implementation. -1. **Localization and document foundation.** Install/pin i18n, author complete - catalogues and ICU controls; verified request-local loaders, language/direction, - safe theme/chrome and controlled state components. Establish status-route - admission with production regression, preserving all P5 controls. -2. **Catalog and course.** Implement actual list/detail/outline pages, both - pagination surfaces, restricted/empty states and metadata from shared loaders. -3. **Lesson presentation.** Implement ordered default-card fields, unavailable - fallbacks, language attribution, schema-swap and inert-value proofs; complete - semantic/focus/lint controls across all page states. -4. **Product proof and closeout.** Complete the real product fixture, no-leak and - request-count/freshness controls, manual accessibility evidence and all carrier - updates. Validate, then open the implementation PR for maintainer review. - -Every numbered implementation step is committed, then reviewed by fresh agents -in two independent rounds. Verify each finding against current code, commit -confirmed fixes, rerun affected checks and only then advance. Reviewer model and -effort follow criticality; security/runtime and proof integrity have separate -review lines. No branch/worktree change; all commits remain on `development`. - -Validation comprises the guarded frontend suite, typecheck, lint, production -build/native verification, relevant Release backend architecture/contract/unit and -real Docker integration suites, formatting, diff checks and relative-link/anchor -audits. Record actual passing counts only after execution. Browser/assistive -technology observations are reported separately from automated test evidence. - -#### Approval boundary and acceptance carriers - -The maintainer approved these together on 2026-10-09: - -1. ADR-0027's library, pin, catalogue home and UI/content-locale separation. -2. G40's explicit local 307→404 error-route behavior and URL change, three-call - normal path/five-call missing path, plain-anchor navigation and controlled - HTTP 200 noindex API-failure states. The original direct-404 wording is not - claimed as implemented by this plan. -3. The remaining gate answers, four implementation steps and mandatory manual - accessibility proof above. - -The acceptance commit updates the decisions index; Standards 03/06/07/08/09/16/21 -and index; -Localization/Frontend/Customization architecture; Phase 04/05/06/07 inheritance; -glossary terms where introduced; the frontend route/i18n/block and test skills; -and this register, -renderer scope/completion criteria and decision record. Only implemented tests -may be labelled Implemented. Accepted ADR-0053/0054 remain unchanged: this selects -their delegated page composition, without another authority carrier or budget. -If review finds an Accepted decision must change, draft its replacement and seek -approval before dependent code. P02d-7 and Phase 11 ownership remains unchanged. - -#### Acceptance validation (2026-10-10) - -The acceptance-only reconciliation passes five Release corpus-consistency cases -and seven ADR-status workflow cases, with zero failures/skips, plus added-prose -wrapping, relative-link/fragment and diff checks. A fresh independent acceptance -review confirms Registered proof statuses, unchanged previously Accepted ADR bodies -and the pending implementation boundary. Its confirmed stale block-skill carrier -is reconciled before the decision commit. No dependency or runtime is delivered. - -#### Preparation review and validation - -Two independent draft-review rounds complete: GPT-6-astra high and -GPT-6.1-sol high review runtime/corpus first; fresh GPT-6-sol high and -GPT-6.1-sol high review the corrected package second. The separate i18n review -also checks the pinned package evidence. Confirmed fixes add a complete message -key example, ICU formatting in the selected UI language, callsite-to-catalogue -coverage with planted controls, and overlapping host/locale request proofs. -Both final round-two reviews report no actionable issue; maintainer acceptance -is still required. - -Documentation-only validation: five Release corpus cases and seven ADR -lifecycle/workflow cases pass, zero failures/skips. Local relative-file/fragment -audits, added-prose wrapping and `git diff --check` pass across the ten changed -Markdown files. ADR-0027 parses as Proposed. No Accepted ADR file or production -code is changed; no frontend/product, browser or accessibility test is claimed -passing by this preparation record. - -#### External i18n draft review reconciliation (2026-10-09) - -The review of `64eefe8` is checked against the SDK, current entry/caller and -mutable documentation. Its six finding groups are addressed: general UI keys -use dotted feature names in the proposal; backend `lockey_*` resources remain -intact; the false SDK translation-map claim is removed. Standards 09, the glossary -and the key skill now distinguish wire-message data from consumer-owned copy. -Acceptance explicitly reconciles Standards 03/07/08/09 and the catalogue sketches. - -ADR-0027 now names the shared verified admission source for request configuration, -whole-catalogue fallback versus missing-key build failure, the future Standards 21 -section, actual repository dependency pins and test-owned RTL inventory. The -review's prefix claim is qualified: `lockey_` is a backend invariant, not a blanket -ban on frontend error resources. No Accepted backend localization contract is -removed. No gate is accepted and no implementation or dependency is added. - -Fresh first-round runtime/corpus reviews use GPT-6-astra high and GPT-6.1-sol -high; an independent second round uses GPT-6-sol high. All report no actionable -finding in the corrected proposal. Maintainer acceptance remains required. - -Five Release corpus cases and seven ADR workflow cases pass with zero failures or -skips. Relative-file/fragment, added-prose wrapping and diff checks pass. These are -documentation checks; no product-runtime or accessibility proof is claimed. - -### P02d-6 Step 1: Localization and document foundation - -**Foundation implemented — 2026-10-10; both independent review rounds complete.** -Work stays on `development`. This record covers the foundation only; -actual catalog/course pages remain Step 2 and lesson presentation remains Step 3. -It does not close P02d-6 or any product/manual accessibility criterion. - -#### Delivered foundation - -- Exact `next-intl` 4.14.9 dependency/lockfile, App Router plugin and server-only - request configuration, with complete app-local English/Turkish `public` - catalogues. ICU/key/argument and production-callsite census controls include - planted missing-key, absent-from-all, misspelled-callsite, malformed-ICU and - argument-mismatch failures. Formatter failures select bounded translated copy. -- Shared server-only request-local admission and content loaders re-verify ingress, - read live site configuration and take content locale/route/pagination identity - from the signed target. The request loader imports neither next-intl nor - messages. UI fallback and runtime direction selection preserve content identity. - A private weak identity memo keyed only by Next's exact request-store headers - object retains same-request admission/content work across error rendering; no - header value, host or envelope keys a representation cache. `getPublicUi` uses - React cache only to reuse selected messages/translators inside an RSC render; - it does not own admission or content-read deduplication. -- Root document language/direction, atomic validation of all four color slots - before fixed style-element emission, and tenant chrome with one main/skip - target, catalog anchor and effective conditional platform attribution. Null or - malformed themes retain the entire existing CSS default palette. -- Closed translated state views, loading and unexpected-error boundaries. The - interactive retry boundary receives bounded labels only. The admitted fixed - status page supplies localized title/noindex metadata and a catalog recovery - link, echoes no original target and performs no Education read. Shared resource - admission selects the approved local 307→404 path for missing content. - -The production fixture adds a separate foundation-consumer mode while retaining -P5's isolated transport probe. The temporary consumer exercises foundation code; -it does not deliver or prove unchanged catalog/course/lesson product pages. -The real production fixture verifies three API calls for a normal document, -three again on its next request and five across the missing-resource redirect -chain. Parallel status requests, bodyless HEAD, renewed host/locale refusals and -canonical redirects pass. Enabled `ar`, `tr` and `tr-TR` coverage checks visible -localized status HTML/metadata, content direction and labelled English fallback -without an Education read. The historical seed remains unchanged. - -#### Verification and review boundary - -The guarded frontend run passes **817 tests: 757 web and 60 SDK**, with zero -skips/todos. All **198 Release architecture cases** pass. The production build -passes with the dynamic status route and root language/theme injection; the real -fixture checks that building performs no API prerender calls. Workspace lint and -typecheck pass. The focused real-API production integration run passes **16 cases, -zero failures/skips**, retaining the separate P5 transport and cleanup controls. -Native ingress regression verification passes TLS, method/upgrade admission, -query redirects, production containment and development HMR. Missing static assets -are refused before tenant bootstrap even when Next invokes the root fallback. -No unchanged content-page, -browser E2E, Lighthouse or manual accessibility pass is claimed here. - -All five P02d-6 architecture-test rules remain **Registered** until their complete -named proof obligations are verified; a foundation test alone does not promote the -broader page-state or accessibility rule. Accessibility remains **Adopted**. - -#### Step 1 review round 1 (2026-10-10) - -Fresh GPT-6-astra xhigh and GPT-6.1-sol xhigh sessions review `c14ecf2..568ecc2` -independently. Runtime/security has no confirmed finding; the proof/corpus review -finds one stale live packet-table cell. It is verified against the delivered code -and corrected to link this foundation record and distinguish the remaining steps. -No production change is required by this round. - -Independent verification includes 216 focused runtime cases and 360 focused proof -cases; the proof reviewer also reruns all 817 guarded frontend cases with zero -skips/todos. Both reviewers approve the Step 1 scope. They inspect the production -fixture but do not rerun its native/Docker execution; the root's validation above -owns that evidence. Product/manual accessibility work remains Steps 2–4. - -#### Step 1 review round 2 (2026-10-10) - -Fresh GPT-6-astra xhigh and GPT-6.1-sol xhigh sessions independently review -`c14ecf2..73b9d53`. Runtime/security has no confirmed finding. Proof/corpus review -confirms two Minor workflow-document issues: stale installation status in the -i18n/route skills, and a route example whose narrowed translator namespace does -not match the implemented callsite census. Both are corrected against the shipped -foundation; the reviewer verifies the resulting skill diff. No production code -change is needed. - -The runtime reviewer passes 374 focused cases across ten files and verifies the -pinned Next/React CSS ordering with a no-port render. The proof reviewer passes -269 focused cases, five Release corpus cases and seven ADR workflow cases. -Both report zero failures/skips; -neither reruns native/Docker fixtures or claims browser/manual accessibility. -The root checks all 30 relative links/fragments in the two changed skills and -`git diff --check`. Both independent rounds are complete; Step 2 follows. - -### P02d-6 Step 2: Catalog and course pages - -**Implementation — 2026-10-10.** The actual catalog and course routes consume the -shared verified resource loader independently in page and metadata. The obsolete -platform placeholder is removed; live middleware retains default-locale entry. -Synchronous server views expose semantic course/outline lists, distinct empty and -restricted states, actual label language and independent opaque next/restart links. -Restricted marketing never emits lesson counts, links or access-purchase controls. - -Canonical/Open Graph URLs use the verified live host, fixed HTTPS listener and -validated local segments. Course alternates use actual eligible translated slugs; -catalog alternates use enabled locales. Cursor pages are noindex with first-page -canonicals; controlled failures are localized noindex states without resource -alternates. No metadata/page consumer adds another content read or client cache. - -The foundation fixture now copies actual catalog/course routes unchanged and -keeps the isolated P5 transport probe. A separate pagination mode uses test-owned -inventory above 20 items and a fresh unchanged visitor budget; historical seed -declarations stay unchanged. Lesson presentation remains Step 3; full product and -manual accessibility closeout remains Step 4. - -**Validation — 2026-10-10.** The root passes 981 guarded frontend cases (921 web, -60 SDK), zero failures/skips/todos, workspace typecheck/lint and production build. -Both product routes are dynamic; the build reports about 103 kB First Load JS, -which is a local build observation, not a Lighthouse or production performance -claim. All 198 Release architecture cases and seven ADR workflow controls pass, -with zero failures/skips. The solution Release build has zero warnings/errors. -Native ingress verification passes TLS, method/HEAD admission, redirects, -production closure, DEBUG containment and development HMR. - -All 17 focused Release `PublicServerRenderingTests` cases pass, zero failures/skips. -The actual foundation mode observes exactly 52 API calls; the independent default- -pagination mode observes 18. Both stay within a fresh unchanged 60-call visitor -budget. Positive host-scope assertions derive from the seed declaration: Yoga's -mapped host includes tenant-wide and its own organization's published marketing, -while excluding the other organization. These are HTTP/RSC proofs, not browser -or manual accessibility evidence. Formatting, local links/fragments, added prose -and diff checks pass. Review closeout precedes Step 3. - -**Step 2 review round 1 — 2026-10-10.** Fresh GPT-6-astra xhigh runtime/security -and GPT-6.1-sol xhigh proof/corpus agents independently reviewed -`785c8c5..917f9f8`. Both approve with no actionable findings. The runtime reviewer -ran 283 focused frontend cases; the proof reviewer ran the 166 new view/metadata/ -path cases, fixture syntax and diff checks. Both traced adjacent admission and -resource loaders, approved metadata/pagination boundaries and real fixture -accounting. Neither started a build, server or Docker fixture; their pure checks -supplement the implementation validation above. Round 2 remains pending. - -**Step 2 review round 2 — 2026-10-10.** Fresh GPT-6-astra xhigh runtime/security -and GPT-6-sol xhigh proof/corpus agents reviewed `785c8c5..86f8ea1`. Both -independently confirmed a missing course hreflang self-reference: the real API -excludes the current locale from its alternate list, unlike the unit fixture. -The fix explicitly uses the current validated canonical, preserves other eligible -API slugs and refuses a supplied self alias. The corrected DTO fixture and actual -production HTML assert self/translated/reciprocal URLs. Protected-content absence -canaries now derive from seed lesson titles, slugs and values, with a nonempty -control and full HTML/Flight checks. Two current architecture-tree comments now -acknowledge delivered catalog/course views. - -Both reviewers inspected and approve the focused fixes, with no remaining -concrete finding. The root passes 284 focused frontend cases, workspace typecheck, -targeted lint, fixture syntax, scoped formatting and diff checks. All 17 focused -Release production-rendering cases pass again, zero failures/skips, with the -unchanged 52/18 call accounting and new real metadata/containment assertions. -Local links/fragments and added prose checks pass. Step 2 is complete after both -independent review rounds; Step 3 follows. - -### P02d-6 Step 3: Ordered lesson presentation - -**Implementation — 2026-10-10; both independent review rounds complete.** The actual -lesson route consumes the shared verified resource loader in page and metadata, -without a separate content read. Its synchronous view renders the API's ordered -plain-string fields as definition pairs, preserves present empty strings, and -attributes each resolved label's language/direction independently of the content -and UI locales. The course backlink uses the admitted request locale. No field -name, raw body/schema, active URL, HTML or richer primitive becomes visible. - -Empty ready content differs from unavailable/unknown presentation. Unsupported -renderers short-circuit before reading their descriptors and emit at most one -request-local bounded count/state warning; API-reported unavailable definitions -retain their own existing diagnostic. Lesson canonical/Open Graph and eligible -hreflang URLs use validated current and actual translated course/lesson slugs. -Unavailable/unknown presentation is noindex with its eligible canonical preserved. - -All 31 active recommended jsx-a11y rules are blocking through the actual app -configuration. A literal census and per-rule dirty/clean controls detect missing -rules, downgraded severity and vacuous subjects. Synchronous view and page-dispatch -units supplement the production fixture; they do not claim async Server Component -DOM support. Full product/manual accessibility closeout remains Step 4, and the -Accessibility standard stays Adopted. - -**Validation — 2026-10-10.** The guarded frontend suite passes 1,059 tests -(999 web and 60 SDK), zero failures/skips/todos. Workspace typecheck and full web -lint pass. All 18 Release production-rendering cases pass, zero failures/skips. -The new presentation mode observes exactly 46 API calls; foundation and pagination -retain 52 and 18 respectively, each in a fresh unchanged visitor budget. - -Actual English and Yoga lesson HTML/RSC proves ordered text, resolved label -languages, eligible translated metadata and tenant absence. A test-owned successor -revision first leaves the deprecated exact pin unchanged, then changes descriptors -only after switching the lesson pin. Inert script/markup/URL strings, absent -optional fields, empty ready and unavailable content are exercised in one running -process. Setup restores the original body, pin, lifecycle and generation. Both -cross-host and protected lesson requests follow the localized 307→404 chain: -original path segments may occur in Next's redirect routing tree, while private -content stays absent and the final status document omits even the original slug. -Native ports, fixture directories and containers are clean after completion. - -Workspace production build passes with all three content routes dynamic; its -about 103 kB First Load JS is a local observation, not a Lighthouse result. -All 198 Release architecture cases and seven ADR workflow cases pass, zero -failures/skips. Local relative links/fragments, added-prose and formatting checks -pass. Native verification passes TLS, method/HEAD admission, redirects, production -closure, DEBUG containment and development HMR. The solution Release build passes -with zero warnings/errors. No browser or manual -accessibility pass is claimed; full product/manual proof remains Step 4. - -#### Step 3 review round 1 (2026-10-10) - -Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus agents -review `c250677..0be38e8` independently. No Blocker/Major is found. The runtime -review confirms a misleading recovery destination: the translated catalog anchor -reloads the failed lesson. The lesson route and the adjacent course route now -send unavailable/rate-limited recovery to the admitted locale's catalog; invalid -cursor reset retains its original route. Dispatch controls render the synchronous -state and assert translated label and destination together. - -The proof reviewer independently confirms a stale narrow ADR-0051 catalogue row. -It now names the delivered component and actual presentation fixture as -Implemented, with its published counts reconciled. The five broader P6 rules stay -Registered -and Accessibility stays Adopted pending Step 4. Each reviewer passes 164 focused -frontend cases, zero failures/skips; neither runs native/Docker or manual checks. -The root passes 167 focused frontend cases, five Release corpus cases, workspace -typecheck and diff checks after the fixes. A fresh second round follows before -Step 4. - -#### Step 3 review round 2 (2026-10-10) - -Fresh GPT-6-astra xhigh runtime/security and GPT-6-sol xhigh proof/corpus agents -review `c250677..3ac4ee1` independently. Runtime approves with no actionable issue -and passes 173 focused frontend cases. Proof/corpus confirms one defensive recovery -edge: a lesson API validation failure selects cursor reset although lessons have -no cursor. The closed mapping now reserves cursor failure for HTTP 400 catalog/ -course reads; lesson and other-status validation failures select unavailable. -The result matrix tests both boundaries without displaying backend diagnostics. -This is a defensive case, not a reproduced admitted normal-path API failure. - -Both reviewers approve the focused mapping fix with no new concrete finding. The -root passes 176 focused frontend cases, zero failures/skips/todos. Final typecheck -requires the negative test DTO's mandatory empty `fieldErrors`; it is corrected, -and all 53 resource cases and workspace typecheck pass. Diff checks pass. Both -independent rounds are complete; Step 4 follows. -Actual product RTL/fault/concurrency and manual accessibility obligations remain -explicit. - -### P02d-6 Step 4: Product proof and accessibility closeout - -**Complete — 2026-10-10.** The unchanged product routes now -have dedicated `product-isolation` and `product-freshness` modes in -`PublicServerRenderingTests` / `verify-public-rendering.mjs`. P5's synthetic -transport mode and the foundation, pagination and presentation modes remain -separate and mandatory. This step adds proof inventory; it changes no production -route, API, rate budget or historical seed declaration. - -Test-owned Arabic translations use the same ASCII course/lesson slugs on both -hosts, with each course's original organization scope. A four-target content -barrier admits both hosts × English/Arabic before continuing the real API pipeline; -HTML and Flight checks reject opposite-tenant and protected authored markers. -Actual document direction, authored content and independently labelled fallback -UI are observed. Both seeded four-color palettes and effective attribution are -checked independently; one malformed theme must fall back atomically to the -whole local default palette, then recover after restoration. - -Freshness runs in one native server process. Publishing state changes remove the -course from the catalog and send course/lesson detail through the approved local -307→fixed localized 404 chain; restoring publication restores eligible content -without changing the other host. A naturally invalid cursor reaches the real -API. Strict one-shot exact host/locale/path content-boundary faults exercise -429 and 503 page states while bootstrap still uses the real application role and -read-only pipeline. These two faulted Education requests intentionally stop at -the test-owned API boundary; they do not claim production handler execution. - -Known content failures expose bounded translated HTTP 200/noindex views and -accurate cursor-reset/catalog recovery. Next may retain the request's own cursor -in its private Flight routing tree; the visible state/title and recovery link do -not echo it. Problem details and private provider copy stay absent from the -complete response. Fixture mutations restore locales, translations, theme and -publication in `finally`; every mode uses a fresh unchanged visitor budget. - -**Validation and reviews.** The guarded frontend run passes 1,065 cases -(1,005 web, 60 SDK), zero failures/skips/todos. All 20 focused Release -production-rendering cases pass, zero failures/skips. -The new isolation/freshness modes observe exactly 43/52 API calls; the earlier -foundation/pagination/presentation modes retain 52/18/46. Full backend regression -passes as recorded below; both review rounds are complete after their fixes. -Automated checks do not establish manual accessibility. The dated walkthrough -below records keyboard, focus, 320 CSS px reflow and contrast observations; -the maintainer's subsequent VoiceOver confirmation closes the remaining -screen-reader check in the packet closeout below. - -#### Step 4 review round 1 (2026-10-10) - -Fresh GPT-6-astra xhigh runtime/security and GPT-6.1-sol xhigh proof/corpus agents -review `e2b8de4..e073075` independently. Neither finds a Blocker/Major. Both -independently reproduce a narrow containment-test false negative: the injected -Problem Details type URI uses a different marker from the other private fields. -The URI now includes the common private sentinel; both reviewers confirm that a -type-only leak is rejected and a clean response remains accepted. No production -leak is demonstrated. The proof reviewer also confirms stale scaffold-only -wording in README; it now distinguishes implemented public pages from the -Studio/portal scaffolds. Related mutable roadmap, frontend setup and contributor -carriers are aligned without claiming completion or browser evidence. - -The root passes the full Release Docker integration suite: 866 passed, zero -failures/skips. After rebuilding the one-line fixture fix, both product modes -pass again (2/2); exact 43/52 request counts remain unchanged. Earlier current -Release results are 1,705 unit, 198 architecture, four contract and 172 Docker-free -integration cases, all passing with zero skips. TRX counters for the newly run -suites are inspected directly. Reviewers run read-only helper probes, syntax and -link checks; neither claims independent full-suite or manual execution. Both -fresh second-round reviews follow the fix commit. Manual accessibility remains -an explicit packet-completion requirement. - -#### Step 4 review round 2 and automated verification (2026-10-10) - -Fresh GPT-6-astra xhigh runtime/security and GPT-6-sol xhigh proof/corpus agents -review `e2b8de4..b86e20d` independently. No production defect is demonstrated. The -proof review identifies two assertion gaps: the malformed-theme check only sees -primary-token style elements, and fixed-status containment only checks `p6-` -requested slugs. The first now rejects any of the four color-token declarations -in style elements or style attributes. The second rejects every requested course -and lesson slug on the final fixed 404, including historical seed slugs. Own -requested route segments remain permitted in Next's 307 Flight tree, as already -recorded in Step 3; private content remains forbidden on both responses. - -Both reviewers independently verify the fixes with extracted real helpers and -clean/planted controls. The root's ten planted violations are all rejected; -both real product modes then pass again, zero failures/skips, preserving exact -43/52 API call counts. Current-state documents distinguish implemented automated -product proof from pending manual observation. ADR-0027 Amendment 2 is insertion -only and changes no accepted decision. The optional suggestion to revisit the -original faulted resource after catalog recovery is not required: the accepted -G40 catalog-navigation contract is directly exercised and passes. No automatic -retry or broader recovery guarantee is introduced. - -Full Release backend verification totals 2,945 distinct passing cases: 1,705 unit, -198 architecture, four contract, 172 Docker-free integration and 866 Docker -integration. There are zero failures/skips; recorded TRX counters are inspected. -The architecture suite is rerun after the current-status documentation changes. -Guarded frontend verification passes 1,065 cases (1,005 web, 60 SDK), zero -failures/skips/todos. Workspace lint/typecheck, JavaScript syntax, Prettier and -the seven ADR workflow tests pass. Production build evidence remains the earlier -Step 3 build; the review fixes change proof assertions and documentation only. -A local audit checks 2,194 relative links and 666 fragments across 33 changed -Markdown files against `origin/main`, excluding one explicit catalogue-link -template placeholder. No target is missing. This manual script audit does not -claim that CI's file-only link job enforces fragments. Added prose respects the -88-column rule and `git diff --check` passes. - -#### Manual accessibility handoff (2026-10-10) - -A temporary production fixture is prepared from `b86e20d`, with the real API, -`learnstack_app`, read-only frames, actual public routes and test-owned Arabic -long-string content. A separate Brave window opens both institution hosts. The -browser refuses the temporary test certificate before any product page loads; -the computer-use policy requires the user to pass that security interstitial. -The requested handoff is pending. No keyboard, focus, 320 CSS px reflow, contrast -or screen-reader pass is claimed. The temporary server and its owned children -are stopped cleanly before the automated rerun; ports 3000/3011 are free and no -test container remains. Existing developer services are untouched. - -Resume the actual manual walkthrough after the browser handoff, record its -commit/environment/hosts/locales/assistive technology and fix any observed issue -before closing P6 or promoting Accessibility and the five registered P6 rules. -The packet remains in progress; P02d-7 and its Lighthouse job have not started. - -#### Manual browser observations and remaining AT check (2026-10-10) - -The fixture is restarted and both product pages load after the user handles the -temporary certificate interstitial. The tested production routes are unchanged -at `180dde0`; the disposable fixture adds Arabic translations and a 240-character -unbroken `W` value. Observation uses Brave 154.1.96.61 on macOS 27.0.1, with the -real API/application role and native HTTPS ingress. The manual fixture uses the -default entitlement provider; the distinct attribution branches are proved by -the automated product-isolation mode, not by this walkthrough. -The tested hosts are `english.localhost:3000` (`en`, `ar`) and -`yoga.localhost:3000` (`tr-TR`, `ar`). - -- Keyboard-only English catalog → English foundations → Present simple and - Turkish Yoga catalog → Stüdyo temelleri → Ağaç duruşu navigation succeeds. - The skip link becomes visible on first Tab, Enter moves to main content and - subsequent links follow content order. Blue/green focus outlines are visible. -- DevTools explicitly reports a 320 CSS px viewport. English and Turkish - catalogs, the Turkish course and lesson, and both hosts' Arabic lessons reflow - without observed horizontal clipping or overlapping text. The long unbroken - value wraps; scrolling reaches the subsequent labelled fields. Arabic authored - content remains right-to-left while fallback UI/definition labels remain - left-to-right. This is a desktop responsive-viewport observation, not a mobile - device or zoom-conformance claim. -- At 320 CSS px, the English invalid-cursor view has readable status text and a - visible focused reset link; Enter opens the query-free catalog. A missing Yoga - lesson arrives at `/tr-TR/status/not-found`; the Turkish branded status and - focused catalog recovery link fit, and Enter returns to the catalog. HTTP - status/noindex assertions remain automated evidence. - -Contrast is calculated from the exact four-color palettes separately from the -visual observations, using WCAG relative luminance. Ratios against each theme's -background are: - -| Palette | Foreground | Muted text | Primary focus outline | -|---|---|---|---| -| English | 17.740:1 | 7.557:1 | 6.702:1 | -| Yoga | 14.628:1 | 7.357:1 | 6.876:1 | -| Local defaults | 17.853:1 | 4.759:1 | 4.634:1 | - -These exceed 4.5:1 for the text pairs and 3:1 for the focus pair. They do not -constitute a full WCAG audit. Normal viewport/zoom are restored after observation. - -**Real screen-reader evidence is still pending.** VoiceOver is initially off; -its caption-panel preference is already on. Enabling VoiceOver through System -Settings changes the switch to on, but the native app inventory still reports -VoiceOver as not running; no speech or caption output is observed. Direct -VoiceOver app access times out; VO navigation produces no observed output. -The switch is restored to off without changing the caption preference. -Accessibility-tree inspection is not substituted for an -actual screen-reader pass. The maintainer is asked to perform the remaining -English/Turkish catalog → course → lesson screen-reader smoke. P6 and standards -promotion remain pending that evidence; no production defect is demonstrated. - -The maintainer explicitly leaves the real screen-reader check pending on -2026-10-10; this does not waive the accepted completion requirement. The -temporary fixture stops cleanly with child exit 0, ports 3000/3011 are free and -its disposable test container is gone. Existing developer services remain -untouched. Resume this final check in a fresh manual fixture before packet -closeout, standards promotion or the completed-implementation PR handoff. - -#### P02d-6 packet closeout (2026-10-10) - -The preceding pending notes record earlier attempts. The manual fixture is -restarted from unchanged production routes at `180dde0`, using the same -Brave/macOS environment recorded above, real API/application role, read-only -transactions and native HTTPS. The maintainer performs the actual VoiceOver -smoke and explicitly confirms both checks: - -- English (`english.localhost:3000/en`): catalog → English foundations → - Present simple passes without an observed issue. -- Yoga (`yoga.localhost:3000/tr-TR`): catalog → Stüdyo temelleri → Ağaç duruşu - passes without an observed issue. -- On both flows, headings, links, skip navigation and lesson field label → value - order are understandable. The maintainer also confirms reading the missing-page - and invalid-link messages and following their catalog recovery links. - -This is maintainer-reported real VoiceOver evidence, separate from the agent's -earlier keyboard, focus, 320 CSS px desktop reflow and calculated contrast checks. -It does not claim a full WCAG audit, mobile-device test, zoom-conformance result -or Arabic screen-reader pass. The owned fixture stops cleanly with child exit 0; -ports 3000/3011 are free, its disposable container is removed and existing -developer services remain untouched. - -All four implementation steps and both fresh review rounds per step are complete. -The automated totals and scope remain those recorded above: 2,945 passing backend -cases and 1,065 passing guarded frontend cases, zero failures/skips/todos. -The manual closeout permits Accessibility Standards to become Active and the -five P6 catalogue entries to become Implemented; the automated checks named by -those entries are already present. The closure change updates documentation only. -Final corpus/link validation and two fresh documentation review rounds complete -before the implementation PR is handed to the maintainer, as recorded below. - -Closeout validation passes all 198 Release architecture cases, including the -corpus guards, with zero failures/skips, and all seven ADR-workflow tests. A local -inline-link audit, excluding fenced and inline code, checks 2,217 relative links -and 678 fragments in 34 Markdown files changed against `origin/main`; no file or -fragment is missing. This remains a manual audit, not a new CI anchor check. -Added prose and diff checks pass. No production code or test changes accompany -this closeout. - -Fresh GPT-6.1-sol high corpus and GPT-6-astra high evidence/governance reviewers -independently review `27a02ba..7d98228`. Both approve with one verified Minor: -the catalogue's current status-consistency assertion quotes the former -nineteen/three split. It now references the index-owned counts instead. Both -reviewers verify the five promoted entries against existing tests, 165 catalogue -rules (107 architecture, 58 outside), twenty Active/two Adopted standards, -maintainer-attributed VoiceOver scope and insertion-only ADR history. Neither -claims new broad runtime execution. - -Fresh GPT-6-sol high consistency and GPT-6.1-sol high history/evidence reviewers -independently review `27a02ba..2b6dbb4` after the fix. Both approve without findings. -They verify current status, catalogue and standards counts, bounded manual -evidence, preserved historical records and insertion-only ADR changes. The -history reviewer independently checks 1,832 relative links and 565 fragments in -the 23 closeout Markdown files; none is missing. Neither reruns a broad runtime -suite. Both closeout review rounds are complete. - -P02d-6 implementation is complete; PR review and merge remain separate. P02d-7 -owns `make demo`, the browser/full-stack CI harness, Lighthouse activation and the -Phase 02d exit checks. Its decision pass must close G20/G33/G38/G44/G45's remaining -parts before implementation. Full Playwright/axe and the expanded renderer/Studio -remain Phase 06; no later packet is delivered by this closeout. - -#### P02d-6 external-review remediation (2026-10-10) - -The external review of PR #27 at `47f9c12` approves without Blocker/Major -findings. Its three Minors and three documentation comments are rechecked against -the current tree; all remain valid and receive bounded fixes: - -- The cross-tenant course probe derives a foreign-only published slug and locale - from `SeedData`, not a second JavaScript literal. The other host's asserted - catalog keeps a visible control for that course. C# independently checks the - refused API path, locale and 404; the shared slug cannot serve this purpose - because it exists in both tenants. Normal/missing course and hidden lesson - checkpoints also assert API status. Next's 307/Location/no-store/404 chain - remains owned by the Node artifact; the API observer does not observe Next - response headers. The broad 1–59 check remains the visitor-budget ceiling; - existing exact per-mode counts and checkpoints remain unchanged. -- The malformed-theme proof removes its redundant root-style-attribute check. - Its existing scan still rejects four-color token declarations in any style - element or inline style, and checks the complete compiled default palette. These HTML - proofs inspect emitted CSS; they do not measure a browser's computed cascade. - The earlier contrast numbers remain calculated palette ratios. -- Missing content without an admitted locale fails through `notFound()` rather - than constructing `/null/status/not-found`; a defensive unit control covers - the otherwise unreachable inconsistent request. -- Error Handling records the delivered mapping and links Steps 1–3. README - inventory distinguishes the public pages from Studio/portal scaffolds. All - five P6 rule headings use H3 under H2; the corpus reader admits H3/H4 with - mixed-level planted controls so no rule falls out of the catalogue census. -- Failure containment uses each scenario's actual private code, retaining the - common private-value/message-key canaries. The ICU parser suggestion does not - require a dependency change: the lockfile uses 3.5.18 for both the direct - structural parser and `use-intl`'s runtime `intl-messageformat` dependency. - Build-time `icu-minify` uses 3.5.21 separately; existing actual formatting and - production-build controls remain mandatory. No general parser-parity claim is - introduced. - -Validation passes 1,066 guarded frontend cases (1,006 web, 60 SDK), lint and -typecheck; 198 Release architecture cases; and all 20 real renderer/cleanup -integration cases, including all six production modes. All report zero failures -and skips/todos where applicable. The H4-only parser mutation fails the mixed -heading control; the restored parser passes the full architecture suite. Format -verification and diff checks pass. A local audit of the four changed Markdown -files checks 1,017 relative links and 353 fragments without a missing target. -No broad backend-suite rerun is claimed by these focused local checks. - -Two fresh read-only remediation reviews approve `47f9c12..e871e88` on 2026-10-10: -GPT-6.1-sol at high effort, then GPT-6-astra at high effort. Both report no verified -actionable findings after standards, isolation, correctness, test-proof and -documentation checks. Neither reviewer claims a runtime-suite rerun. The -[PR #27 description](https://github.com/HodeTech/LearnStack/pull/27) owns the -exact-head CI evidence. - -#### P02d-6 systematic-review decision package (2026-10-10) - -**Maintainer response recorded — 2026-10-10.** The two external reports at -`ed6f81e` are review data, not new authority. Rechecks confirm guidance/status -drift, ordinary static source-fence gaps, missing dirty/clean response controls -and a second-bootstrap failure-classification gap. The exact-response-owner -design remains Proposed; the Open Graph and security maintenance parts below -are separately approved. - -The existing G40 content-error HTTP 200/noindex and cursor-free canonical/noindex -policies are accepted choices, not implementation drift. Google's -[pagination guidance](https://developers.google.com/search/docs/specialty/ecommerce/pagination-and-incremental-page-loading) -recommends individual canonicals; its -[status guidance](https://developers.google.com/crawling/docs/troubleshooting/http-status-codes) -explains temporary-error and soft-404 tradeoffs. These recommendations justify -recording the tradeoff, not silently reopening the approved policies. - -G10 explicitly defines editable base64url JSON seek cursors without confidentiality -or authentication. G40's opacity means the renderer does not interpret the token; -it does not hide anchor UUIDs from visitors. Scope/eligibility remains independently -enforced. Encryption, MAC rotation or server-side cursor state would need a new -decision and is not a correction to this PR. - -##### Maintainer decisions (2026-10-10) - -1. **Second bootstrap — design requested; not accepted.** The maintainer did not - approve the neutral 500 proposal and requested a fuller response-owner design - preserving exact 429/503. Revised proposed - [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md) selects one - live middleware-owned read and an immutable native request-local snapshot for - RSC. This removes the second-read failure and explicitly proposes two normal - document calls / three followed-missing calls in place of three/five. It also - proposes a closed Retry-After bound. These ownership, DTO handoff and accounting - changes await approval; no dependent code or current-contract change is made. - Independent design review rejected response-write interception as fragile; - the revised concrete ALS singleton design has no remaining architecture - finding, subject to actual Next 15.5.27 feasibility and isolation proofs. -2. **Open Graph locale — approved.** Emit `language_TERRITORY` only when the - admitted tag has an explicit two-letter territory and no script/variant - information would be silently discarded. Omit unrepresentable locale/alternate - properties rather than inventing a territory. `tr-TR` becomes `tr_TR`; - `en`, `tr`, `zh-Hant` and numeric-region tags are omitted. Document language, - route and hreflang keep - their exact BCP-47 tags. The [protocol](https://ogp.me/) makes these properties - optional; omission can leave consumers applying their own default. This adds - the bounded G40 projection and qualifies Standards 08's blanket rule. -3. **Security maintenance — approved.** Pin Next and eslint-config-next to - 15.5.27, disable the unused image optimizer, inspect/patch affected transitive - versions within compatible bounds, and re-prove native ingress and actual - production HTML/RSC. - The fresh audit reports 46 findings (2 critical, 28 high, 15 moderate, 1 low), - not 46 reachable public flaws. The AVIF - [advisory](https://github.com/advisories/GHSA-2xp9-vwfh-vxw4) affects the current - dependency version; attacker-controlled image input is not demonstrated. - The [15.5.27 metadata](https://registry.npmjs.org/next/15.5.27) supplies a - compatible 15.x backport. A Next bump alone does not clear transitive findings; - record each remaining advisory's actual input path and maintenance disposition. - -The approved ADR-0054 maintenance note is appended only after passing replacement -proofs. Its exact text is: - -> **Amendment 7 — Next security maintenance (2026-10-10).** The current verified -> runtime pin is Next 15.5.27 with matching eslint-config-next. The signed raw -> target, full-URL RSC projection and equivalent redirect-query contract are -> unchanged. The unused image optimizer is disabled. P02d-6's remediation record -> owns the replacement native/production proofs and dependency triage; historical -> 15.5.18 observations remain unchanged. - -No speculative native-addon/install-script policy is introduced. Existing exact -pins, frozen lockfile and real builds remain mandatory. Dependency patching does -not establish air-gapped packaging support. - -##### Remediation plan and review boundaries - -1. Correct current guidance/status carriers and skill examples. Strengthen the - existing response assertions, source-retention/prefetch fences, production - formatter-path tests and applicable accessibility controls. Align decimal - limit parsing and closed cursor-error classification with existing contracts. - These corrections need no new behavior decision. -2. Implement the approved G40 Open Graph projection. Separately prepare the fuller - exact-bootstrap response-owner design; its implementation waits for approval. - The eventual approved design must prove second-bootstrap faults through the - actual production fixture without weakening provenance, read-only/RLS or the - admitted content-error policy. -3. Apply the approved compatible security patches and close unused image - optimization; re-run affected full/native/real-API suites, audit, formatting - and local link/fragment checks. Record fresh exact-head PR CI. Append the - approved maintenance note only after its replacement proofs pass. - -Each group is committed and receives two fresh independent review rounds, with -verified findings corrected before the next group. All work stays on development. -The maintainer's earlier browser/VoiceOver report remains attributed to its tested -commit; later defensive/proof changes do not imply a new manual pass. P02d-7 and -Phase 06/11 retain their explicitly named browser, full accessibility and hardening -work. This package makes no new passing runtime or merge-readiness claim. - -##### Remediation group 1 — existing-contract corrections - -**Implemented; both review rounds and focused fix verification complete — -2026-10-10.** No approval-gated decision above is implemented by this group. -ADR-0055 remains Proposed. - -The Step 1 status and current i18n/theme carriers now match delivery. Skills use -locale-bearing public folders, the shared resource loader, supported Next page -exports and explicit catalogue wiring. Future block/entitlement sketches are -labelled as targets. Phase 06 explicitly owns localized section names and full -Playwright/axe completion; Phase 11 explicitly owns frontend telemetry. - -The production response predicates are shared with dirty/clean companions: -inline Flight escaping, entity-encoded attributes, opposite/protected values, -whole/partial palette emission, attribution and localized status metadata. -Emitted viewport checks reject zoom restrictions; they are not browser zoom proof. -The two unused ICU sentinels detect unchanged complete catalogues, not arbitrary -partial copy leakage. Static import fences supply the separate client boundary. -The bounded source analyzer now covers retained local factories/collections, -module mutable bindings, static/global writes and Next Link/router imports. -Admitted Studio/portal scaffolds are render roots and explicitly noindex. - -Direct tests exercise the actual request configuration and public UI wrapper; -callsite census follows ordinary aliases/Promise tuples and requires a nonempty -production subject. Actual lint controls cover image, object, area and image-input -alt text. A prefixed style-breakout value tests the theme regex's start anchor. -Loading uses a status live region. Counts explicitly describe the current page. -Positive decimal limits saturate at the API bound without rejecting long valid -values; only exclusive owned-cursor errors with a supplied cursor select reset UI. - -The following review claims do not justify changing accepted behavior: - -- Cursor confidentiality, self-canonical pagination and content-error HTTP status - are already decided; their tradeoffs and pending approval boundaries are above. -- Studio/portal bootstrap is the admitted scaffold contract, not an implemented - authentication surface. Their full UI remains Phase 04/06/07. -- Missing error-label context is outside the current provider-wrapped public - tree. No whole catalogue or hardcoded fallback is added to its Client Component. - The assertion that `reset` can never recover is not reproduced; the supported - framework reset and catalog recovery link remain. -- Security headers remain Phase 11's explicit scope. Arbitrary reflective/eval - source analysis, a complete WCAG audit and browser-computed theme/zoom proof are - not newly claimed by the strengthened bounded controls. -- ADR-0027's Decision explicitly authorizes the contract below it; the Context - placement does not make that contract nonbinding. Accepted history is preserved. -- Packet 10's 19/3 standards count is historical; its timestamp is now explicit. - Phase 06's P6 review/merge-pending statement is still true for this open PR. -- The review skill's conditional manual-evidence completion gate remains valid - for future work. Branding has no authored-language field; inventing a language - for the institution name would not establish correct pronunciation. - -Validation at `cc626e8`: the guarded frontend runner passes 1,197 cases (1,137 web, -60 SDK), with zero skips/todos; workspace lint/typecheck pass. Five Release corpus tests -and seven ADR-workflow cases pass. The final focused Release integration run passes -20 cases: six real production Next/native HTTPS/API/PostgreSQL modes and fourteen -cleanup/log-control companions, with zero skips. No backend full-suite rerun or new -manual accessibility pass is inferred from these focused checks. - -**Round 1 — fresh independent reviews of `ed6f81e..cc626e8`.** GPT-6-astra -(high) reviewed runtime/source-boundary behavior; GPT-6.1-sol (high) reviewed -proofs, guidance and documentation. Three findings were verified: shorthand -factory returns and destructured shared-storage aliases escaped the bounded -retention fence, and the attribution dirty control failed on its palette before -reaching attribution. Four new dirty cases fail before the retention fix; they -and two request-local clean cases pass afterward. The attribution control keeps -a valid palette and checks the specific failure in both entitlement directions. -Focused validation passes all 263 boundary cases and 36 response-helper cases; -web typecheck passes. Neither review claims a Docker/full-suite/manual rerun. - -**Round 2 — fresh independent reviews of `ed6f81e..69b382a`.** GPT-6.1-sol -(high) reviewed runtime/source boundaries; GPT-6-astra (high) reviewed proofs and -documentation. The proof/documentation review approved. Two further bounded -retention gaps were verified: resolved local object member factories and -destructured closure captures. Seven additional dirty controls fail before the -fix, while seven request-local or pure-value controls remain clean. The fix follows -literal members and selected named/indexed binding values, without treating an -unrelated sibling collection as a captured value. All 277 boundary cases and web -typecheck pass. Fresh independent verification of `69b382a..bdb88bb` approved -without actionable findings and independently passed all 277 boundary cases. -The verifier confirmed the seven dirty cases escape the prior analyzer and the -selected-binding clean controls remain clean. This closes group 1. - -##### Remediation group 2 — approved Open Graph locale projection - -**Implemented; both independent reviews complete — 2026-10-10.** The approved -G40 addendum above -separates Open Graph's optional locale format from BCP-47 identity. Only canonical -language plus an explicit two-letter territory is projected; script, variant, -extension, bare-language and numeric-region tags are omitted. Eligible and enabled -alternates keep their exact URLs and hreflang while unrepresentable Open Graph -alternates are omitted. No additional API reads or territory inference is added. -Unit projections and actual production-document checks cover both conversion and -omission. All 61 metadata cases and web typecheck pass. On the concurrently -patched Next 15.5.27 runtime, the guarded frontend suite passes 1,229 cases -(1,169 web / 60 SDK), zero skips/todos. The actual API/PostgreSQL production-render -suite passes all 20 cases, zero skips; its first run exposed an overly narrow -fixture-alternate expectation, corrected before this passing run. The production -build passes. Two independent review rounds follow the implementation commit. -ADR-0055 remains Proposed and has no dependent code in this group. - - -**Round 1 — independent review of `ca03942..75c3e61`.** GPT-6.1-sol (high) -independently passed 61 metadata cases and web typecheck. It found no production -projection error, but verified that the runtime alternate loop accepted missing -and ineligible serialized alternates. The corrected shared predicate compares -complete current/alternate arrays against the representable eligible hreflang -set. Six committed dirty/clean controls cover missing, ineligible, duplicate, -malformed and invented territory output. All 103 metadata/response-helper cases -pass. - -**Round 2 — fresh independent review of `ca03942..f16d937`.** GPT-6-astra -(high) approved without verified findings and independently passed the same -103 cases. The actual API/PostgreSQL fixture then passed all 20 cases, zero skips, -with the complete serialized-array predicate active. This closes group 2. - -##### Remediation group 3 — approved security maintenance - -**Implemented; replacement proofs and both independent review rounds pass — -2026-10-10.** The approved -paired Next/eslint-config-next 15.5.27 update disables unused image optimization. -Compatible lockfile patches cover PostCSS 8.5.23, sharp 0.35.5, js-yaml 4.3.2, -brace-expansion's existing major lines, nanoid 3.3.18, source-map-js 1.2.2, -browserslist 4.28.7, baseline-browser-mapping 2.11.0 and selector-parser 6.1.3. -Next pins an older PostCSS exactly, so only its dependency edge has a permanent -8.5.23 override. Redocly core 1.34.20 remains within the SDK's existing range and -updates its exact js-yaml dependency. Normal and frozen installation pass. - -Comparable fresh audits distinguish deployment from development tooling: - -| Scope | Before maintenance | After compatible patches | -|---|---|---| -| Production | 46 findings: 2 critical / 28 high / 15 moderate / 1 low | 2 findings: 1 high / 1 moderate | -| Full workspace | 59 findings: 5 critical / 32 high / 21 moderate / 1 low | 11 package/advisory records: 3 critical / 2 high / 6 moderate; 10 distinct GHSAs | - -The original 46-finding report was production scope. The full baseline uses the -pre-maintenance committed manifests/lockfile in a disposable directory. Neither -comparison claims every advisory is a reachable public flaw or a clean audit. -Current residual input paths and dispositions are: - -| Advisory | Current input and disposition | -|---|---| -| [GHSA-vfj7-8cjw-p6xm](https://github.com/micromatch/braces/issues/70) | Braces processes checked-in build/lint/watch globs through Tailwind/Next ESLint. No fixed release exists; retain visibility and reassess upstream or any request-supplied glob use. | -| [GHSA-rj75-hqrm-r3gf](https://github.com/postcss/postcss-selector-parser/security/advisories/GHSA-rj75-hqrm-r3gf) | Selector-parser 6.x processes checked-in CSS through Tailwind/PostCSS Nested. Fix 7.1.6 exceeds their declared range; no request-time selector input is identified. Track an upstream backport or separate compatible parent migration. | -| [GHSA-67mh-4wv8-2f99](https://github.com/evanw/esbuild/security/advisories/GHSA-67mh-4wv8-2f99) | Esbuild's serving feature through Vite/Vitest is not used by repository scripts. Proposed test-toolchain migration below removes the affected branch. | -| [GHSA-4w7w-66w2-5vf9](https://github.com/vitejs/vite/security/advisories/GHSA-4w7w-66w2-5vf9), [GHSA-v6wh-96g9-6wx3](https://github.com/vitejs/vite/security/advisories/GHSA-v6wh-96g9-6wx3), [GHSA-fx2h-pf6j-xcff](https://github.com/vitejs/vite/security/advisories/GHSA-fx2h-pf6j-xcff) | Vite development HTTP/editor/file-serving paths; repository scripts expose no Vite dev-server workflow. Windows-specific prerequisites are not a blanket exemption. Migration below replaces Vite 5. | -| [GHSA-5xrq-8626-4rwp](https://github.com/vitest-dev/vitest/security/advisories/GHSA-5xrq-8626-4rwp), [GHSA-82fw-gwwq-j7x9](https://github.com/vitest-dev/vitest/security/advisories/GHSA-82fw-gwwq-j7x9) | Vitest UI/API/mocker paths; scripts use run mode without UI/API/browser configuration or public mocker exports. These remain reported findings; migration below replaces both Vitest/mocker branches. | -| [GHSA-5gmw-xhrv-c9v3](https://github.com/tinylibs/tinypool/security/advisories/GHSA-5gmw-xhrv-c9v3), [GHSA-85c8-ppgw-ccpr](https://github.com/tinylibs/tinypool/security/advisories/GHSA-85c8-ppgw-ccpr) | Test-worker construction/options need prior prototype pollution and applicable attacker-controlled loading input; none is identified. Migration below removes tinypool rather than forcing an incompatible major into Vitest 2. | - -The P02d-6 remediation owns this triage and the approval request below. The -maintainer owns any remaining backport/parent-migration decision; applicable -Security Standards patch deadlines remain unchanged. No test-toolchain major is -silently included in the already approved compatible-patch package. - - -Replacement validation passes on Next 15.5.27: frozen install; production build; -workspace lint/typecheck; guarded frontend **1,235 cases** (1,175 web / 60 SDK), -zero skips/todos; and all **20** actual API/PostgreSQL production-render cases, -zero skips. All nine pinned SWC emission cases run against the installed patch. -Native ingress passes TLS, GET/HEAD, query projection/redirects, DEBUG containment, -production upgrade closure and retained HMR. The image proof decodes a valid raw -PNG, sees disabled GET/HEAD 404, enables only a disposable copied configuration, -then decodes optimized 200 and proves the same disabled predicate rejects it. -All **19** native lifecycle/negative controls pass. No shared build is mutated. -The approved ADR-0054 maintenance note is appended after these replacement proofs; -historical 15.5.18 observations remain unchanged. Two independent review rounds -follow the implementation commit. No new manual browser/VoiceOver pass is claimed. - -**Round 1 — fresh independent reviews of `f16d937..3f6f37f`.** GPT-6-astra -(high) reviewed dependency ranges, resolved versions, audit triage and ADR history; -GPT-6.1-sol (high) reviewed runtime proof controls, copied-build ownership and -cleanup. Both approved without verified actionable findings. These were read-only -reviews; syntax and diff checks pass, but neither claims a new runtime-suite run. -The full Release architecture suite also passes all 198 cases, zero skips; all -seven ADR-workflow cases pass. The second independent review round follows. - -**Round 2 — fresh independent reviews of `f16d937..05a4313`.** GPT-6.1-sol -(high) independently checked dependency ranges, lockfile deltas and saved audit -totals; GPT-6-astra (high) checked native proof falsifiability, runtime config -loading, cleanup and preserved gates. Both approved without verified actionable -findings. They passed syntax/diff checks and inspected installed packages/source; -neither performed another build or runtime-suite run. A local audit of the 22 -changed Markdown files checks 1,703 relative file targets and 567 fragments, with -inline/fenced examples excluded and no missing targets. Added prose respects -88 columns; CI's existing link gate still checks file existence only. This closes -the approved compatible-security group. ADR-0055 and the separate test-toolchain -migration remain pending approval and have no implementation in these commits. -Fresh exact-head PR CI remains the final validation step. - -###### Test-toolchain migration — approved (2026-10-10) - -The separately reviewable candidate pins Vitest **4.1.11** and Vite **6.4.3** in -both web and SDK, resolving esbuild **0.25.12** within Vite's range. Vitest 4 removes -tinypool; no tinypool major override is proposed. React plugin 4.7.0, jsdom 26.1.0, -Node 22.23.1, TypeScript 5.6.3 and React 19 remain. Narrow compatible resolution -pins may keep Vitest on Vite 6 and Vite on the selected esbuild patch; Vite 8 must -not appear as an accidental second tree. - -The [official migration](https://v4.vitest.dev/guide/migration) changes pool and -mock-constructor behavior. The existing arrow `Intl.Locale` constructor mock -must become a constructible function/class and still prove its intended error. -Inspect mock cleanup; retain explicit Testing Library cleanup and `globals:false`. -The JSON reporter keeps the counters/status/file fields consumed by the guarded -runner; all its skip/todo/missing/omitted-file negative controls must still fail. - -Before completion: frozen install, resolved graph/advisory audit, guarded full -frontend suite, lint, typecheck and production build; two independent review -rounds and verified fixes. Preserve package/control deadlines and all existing -proof gates. The maintainer separately approved this major test-toolchain upgrade -on 2026-10-10; implementation and fresh two-round review follow that approval. -It accepts no new architecture/ADR contract. The earlier compatible-security -group's pending-approval statement records its own commit-time boundary. - -###### ADR-0055 draft review reconciliation (2026-10-10) - -The maintainer's review is a request for draft corrections, not ADR acceptance. -The revised Proposed record names ADR-0054's unchanged Retry-After instruction and -limits the proposed qualification to renderer forwarding; API refusal selection -and metadata stay unchanged. It also names ADR-0054's deferred request-local reuse -and ADR-0027's admission loader, aligns the title with the existing filename, and -requires canonical Registered catalogue rules before dependent production code. - -Next 15.5.27 native-to-middleware-to-RSC context propagation must be demonstrated -before acceptance. An isolated feasibility experiment is research, not permission -to ship the proposed runtime. Maintainer approval is still required after review. - -The draft first appeared in mixed fix commit `cc626e8`, was revised in `bdb88bb`, -and received its decision-scoped commit in `ca03942`. That draft packaging is -recorded rather than rewritten. No Accepted ADR-0055 decision or dependent runtime -exists; acceptance-before-production implementation has not been bypassed. - -ADR-0054's original Next 15.5.18 pin and retired test name were accurate at -acceptance. Preserve that history: its existing Amendment 7 identifies the -current 15.5.27 maintenance baseline. No accepted-body erratum is appropriate. - -Two fresh independent reviews of `46bc8a4..2bf9d57` approve these draft corrections -without verified findings: GPT-6.1-sol (high), then GPT-6-astra (high). Both checked -the accepted sources, actual duplicate reads, historical pin/test and five changed -relative links/fragments. Neither claims a runtime feasibility proof. Seven -ADR-workflow tests pass. A local three-document audit resolves 442 relative -targets and their fragments; added prose and diff checks pass. - -##### Remediation group 4 — approved test-toolchain migration - -**Implementation recorded before independent review — 2026-10-10.** Both web -and SDK pin Vitest 4.1.11 and Vite 6.4.3. Narrow overrides keep Vitest on Vite 6 -and Vite on compatible esbuild 0.25.12; the existing Next/PostCSS override remains. -The resolved graph removes Vitest 2, Vite 5, tinypool and vite-node, without -introducing Vite 7/8. Runtime dependencies and application behavior are unchanged. - -The `Intl.Locale` mock uses a constructible function and proves that the intended -RangeError was thrown by identity, preventing an accidental constructor TypeError -from satisfying the fallback case. Configurations, explicit cleanup, globals, -runner/report validation, package/control deadlines and CI gates stay unchanged. - -Frozen installation and 46 focused locale/runner cases pass. The guarded frontend -suite passes all 1,235 cases (1,175 web / 60 SDK), zero skips/todos; workspace lint, -typecheck and production build pass. The Release architecture suite passes 198 -cases, zero skips. The full audit falls from 11 records / 10 distinct advisories -to two records / two advisories: zero critical, one high and one moderate. The -production audit retains the same two residuals already triaged in group 3; -neither audit is described as clean. Independent review rounds follow this commit. - -**Round 1 — independent review of `2bf9d57..0761d84`.** GPT-6.1-sol (high) -reviews dependency compatibility and approves without verified findings. A fresh -resolved graph matches the saved graph and installed lock; surviving package -records and runtime dependency declarations are unchanged. GPT-6-astra (high) -reviews runtime/test proofs and also approves without findings. It independently -passes 110 focused locale, runner, caller, HMR and cleanup cases, verifies the -26-web/one-SDK file census, and checks the installed JSON reporter semantics. -Neither reviewer claims another full frontend/build/architecture execution. - -**Round 2 — fresh independent review of `2bf9d57..a97f6ee`.** GPT-6-astra -(high) approves the dependency/documentation lens without verified findings, -independently matching the installed lock and fresh graph to the committed tree. -GPT-6.1-sol (high) approves runtime/proof integrity without findings. It passes -178 focused cases, including 68 shuffled DOM/request/mock cases, and validates -both reports with the actual repository validator. Its direct installed-spy -control distinguishes the intended RangeError from the old arrow's TypeError -and proves restoration of native locale behavior. No full-suite, build, install -or audit rerun is attributed to these reviewers. This closes group 4; fresh -exact-head CI follows. ADR-0055 remains Proposed and unimplemented. - -##### ADR-0055 isolated feasibility observation (2026-10-10) - -The root independently replays a disposable native HTTPS / production Next -15.5.27 fixture on Node 22.23.1. All 37 requests pass the propagation matrix: -eight simultaneous identical HTML, eight Flight, eight prefetch, eight host/locale -HTML/Flight combinations, HEAD and HTML/Flight missing/error cases. Native, -middleware and RSC compare actual holder/store references; request IDs are -observations, not context lookup keys. Unbound and duplicate-ALS controls each -refuse with 503, without snapshot publication or RSC consumers. Prefetch runs -middleware without dynamic RSC consumers in this synthetic fixture. - -Valid HEAD exposes a lifecycle caveat: Next can resume an already-started -not-found component after response finish. The store is correctly disposed, its -snapshot cleared, and late access refused; Next logs the bounded fixture error. -ADR-0055 now explicitly requires disposal checks after awaits and neutral -production diagnostics. Response finish does not imply synchronous reclamation -of already captured local references or completion of all React work. - -The experiment uses synthetic site publication. It proves neither real API/ -provenance/RLS nor the proposed two/three-call accounting, cancellation, active -shutdown, keep-alive, HMR or browser navigation. Certificates, children and owned -build output are cleaned; a local reproducible source/results bundle is retained -for maintainer inspection. No experiment source enters the production tree. -This supports feasibility of the proposed same-process design only. ADR-0055 -remains Proposed; dependent production implementation still requires approval -and all named production proofs. - -**Independent feasibility review — two rounds.** GPT-6-astra (xhigh) checks -the fixture/driver, retained diagnostics and root replay. It verifies one wording -gap: the RSC context-error paragraph also covered expected post-finish HEAD work. -Commit `5b5f5a9` limits that paragraph to active requests; the reviewer rechecks -and approves the narrow feasibility claim without remaining findings. It does -not characterize observation-only summary fields as comprehensive mutation tests. -GPT-6.1-sol (high) then independently reviews `22a9775..5b5f5a9`, confirms the -matrix and active/late distinction, and approves without findings. Both reviews -inspect evidence rather than run another build. The root's separate replay passes -the same matrix and both negative controls. No review constitutes ADR acceptance. - -##### ADR-0055 acceptance and implementation plan (2026-10-10) - -**Accepted — 2026-10-10; implementation not yet delivered.** After the isolated -Next 15.5.27 feasibility experiment and two independent feasibility reviews, the -maintainer explicitly approves revised -[ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md) and dependent -implementation. The earlier draft/review/feasibility notes record their own -pending-approval boundaries; this dated acceptance supersedes those current-status -readings without rewriting them. The decision-only acceptance commit precedes -production changes. All work stays on development. - -**Bounded G40 supersession.** The original G40 acceptance and its three/five-call -delivery remain historical. ADR-0055 replaces only duplicate bootstrap ownership, -request-local snapshot handoff and call accounting: middleware owns one live site -read and exact neutral 404/429/503; RSC re-verifies provenance and consumes the -immutable snapshot bound to that native request. A completed product document -costs two API calls, a fixed status/scaffold document one, and a followed missing -detail three. Actual HEAD/RSC/prefetch and Flight fallback counts require separate -production proof. Changes after bootstrap appear in the next request's site value; -content eligibility still runs live at the API. - -Renderer Retry-After forwarding accepts only eligible parsed integer zero-to-sixty -delta-seconds on supported 429/503 cases. Ineligible values are omitted without -clamping or invention. API refusal selection/metadata, numeric quotas, content -HTTP 200/noindex, cursor SEO and the local missing-detail 307-to-404 chain remain -unchanged. ADR-0053/0027/0054 carry dated bounded supersession navigation. - -Five canonical rules are Registered before code in the -[catalogue](../standards/21-architecture-tests-catalogue.md#p02d-6-request-local-bootstrap-admission-controls): -active native context, exact bootstrap HTTP responses, one immutable per-request -snapshot, native lifecycle completion and preserved production ingress boundaries. -Registered status is a commitment, not an executable or passing-test claim. - -###### Implementation and review sequence - -1. **Native context, facade and lifecycle units.** Add the sole versioned native - ALS holder and server-only facade, binding verified host/peer/method/target to a - fresh pending/ready/closed request store. Publish a bounded deeply immutable - snapshot only once; cancel/clear exactly once on finish/close/shutdown. Unit - controls cover missing/duplicate/mismatched context, abort, late publication, - deep immutability and overlapping identical requests. Extend source fences only - for this explicit owner/facade boundary. Commit, run fresh independent review - round 1, verify/fix/commit findings, then use new reviewers for round 2 and - verify/fix/commit its findings. -2. **Middleware publication and RSC consumption.** Middleware owns one bootstrap, - bounded Retry-After and refusal/redirect terminal states; RSC/resource/i18n - consumers use only the verified ready snapshot and native cancellation signal. - Remove the second site read without changing locale authority or content-state - policy. Add mapping and fault controls, update affected unit expectations, and - commit. Complete the same two fresh independent review/fix rounds before Step 3. -3. **Actual production proof and closeout.** Exercise the shipped native launcher, - pinned Next and real API/PostgreSQL as `learnstack_app`: first-wire refusals, - zero Education/theme after failure, exact counts, identical/differing concurrent - host/locale requests, HTML/RSC/prefetch/status/scaffolds, next-request freshness, - keep-alive, abort/shutdown/HMR and valid HEAD late work with neutral diagnostics. - Retain stock-launch, method/upgrade, exempt asset/health, no build bootstrap and - private-value containment controls. Plant failures beside clean controls. Run - affected full suites/build/lint/typecheck, catalogue and local link/fragment - checks; commit and complete both fresh independent review/fix rounds. Only then - mark proven rules Implemented, update delivery navigation and the existing PR, - and verify fresh exact-head CI. Merge remains a maintainer action. - -No step or review round is complete at acceptance. Missing propagation or lifecycle -proof cannot be replaced by another bootstrap, DTO headers, shared data or an -unapproved response owner; a required architectural change returns for a new -decision. P02d-7 and Phase 06/11 retain their named browser/accessibility/hardening -work. No new manual browser/VoiceOver result is implied by this approval. - -###### ADR-0055 Step 1 — Native request context and lifecycle - -**Implemented — 2026-10-10; both independent review rounds complete.** The native -launcher installs the sole versioned ALS holder before Next preparation and wraps -each admitted HTTP delegation in a fresh verified binding. Server-only consumers -retrieve the existing holder lazily; no bundled runtime constructs a replacement. -The holder copies only the closed public Site fields, bounds the copied snapshot -to the existing decoded-response ceiling and freezes its nested values. Refusal, -finish, close, abort and shutdown prevent later publication/use and release the -holder's snapshot reference and owned listeners. Request-input `close` and handler -promise resolution do not terminate the response lifetime. - -Forty-eight focused unit cases cover state/binding conflicts, source mutation, -the inclusive UTF-8 byte ceiling, eight overlapping identical requests, escaped -handles, singleton descriptor checks and completed HEAD/late work. Source fences -refuse runtime imports of the native owner, facade fallback construction and -Client Component access, with dirty/clean controls. The shared transport limits -retain the existing ten-second and 8 MiB values. - -The guarded frontend run passes **1,284** cases: **1,224 web and 60 SDK**, with zero -skips/todos. Typecheck, lint, production build and all **198 architecture cases** -pass. Native ingress verification and all **19 setup/cleanup controls** pass, -including production upgrades, development HMR, signal/IPC/EPIPE and owned -fixture cleanup. These unit/native-foundation results do not claim the complete actual -middleware-to-RSC handoff: Step 2 still owns publication/consumption and removal -of the second bootstrap; Step 3 owns actual product integration and lifecycle -proofs. The five new catalogue rules remain Registered until that proof closes. - -**Review round 1 — `166ffb3`.** Fresh security/lifecycle and proof/structure -reviewers independently run all 326 focused cases. They verify two gaps: completed -handles retain native request/response objects through the disposal closure and -the default abort exception's lazy stack; ordinary `call`/`apply`/`bind` wrappers -also evade the new facade installer fence. The fixes clear the retained closure, -use a fixed primitive cancellation reason on both terminal paths and recognize -the three installer wrappers. Dirty/clean controls cover every wrapper; the -original proof reviewer verifies its finding is closed. An isolated GC regression -retains completed handles while checking that both native objects are released, -with live-object positive controls. Both original and closure-only mutants fail -at the collection assertion for ready/refused paths; the repaired 327-case -focused run, typecheck and lint pass. Actual middleware/RSC integration remains -pending in the next steps. - -**Review round 2 — `af34e29`.** Fresh runtime and proof reviewers independently -run 367 and 446 focused cases. They verify that ordinary literal object/array -aliases evade the facade installer check and that the new signal handler leaves -a real development HMR connection/process alive. The source check now resolves -those static aliases, with dirty and clean controls. The launcher owns upgraded -sockets, cancels admission, awaits native/Next cleanup and bounds termination. -The native proof keeps HMR open through SIGTERM and SIGINT and requires exit code -zero and socket closure without fixture escalation. The original runtime reviewer -independently repeats both signals on real Next 15.5.27: both close and exit in -7 ms without SIGKILL, and closes the finding. The proof reviewer verifies its -minimal alias fix and all 278 boundary cases. Root revalidation passes 327 focused -cases, typecheck, lint, native ingress and all 19 setup/cleanup controls. Step 1 -is complete; no second-bootstrap removal or full product proof is claimed here. - - -###### ADR-0055 Step 2 — Single bootstrap publication and checked consumers - -**Implemented — 2026-10-10; both independent review rounds complete.** Middleware -requires the matching active native context before transport, performs the sole -site call and publishes only after successful route admission and response -construction. Redirects and refusals terminalize without a snapshot. Controlled -404/429/503 responses are bodyless for HEAD; the renderer forwards only eligible -integer Retry-After values from zero through sixty, without clamping. - -The RSC loader independently verifies provenance, consumes that native snapshot -and constructs its content caller with native cancellation. It never calls -`getSite()`. Invalid provenance and exempt transport fallbacks retain their prior -neutral behavior; active context/configuration defects fail with fixed internal -diagnostics. Identity checks distinguish simultaneous identical bindings. Private -memoized loaders have checked outer wrappers, and resource/UI/i18n/document -consumers recheck after their awaits; completed cache hits and retained translators -cannot revive an ended native request. - -The guarded frontend run passes **1,342** cases: **1,282 web and 60 SDK**, zero -skips/todos. Typecheck, lint, production build and all **198 architecture cases** -pass. The native ingress proof passes with one site call for status/scaffold -requests, real middleware/RSC consumption and retained TLS, method, optimizer, -DEBUG, HMR and signal controls. Focused tests include 88 middleware/admission and -18 actual-memo resource lifecycle cases. These are Step 2 results; Step 3 still -owns real-API/PostgreSQL product accounting, exact wire failures, broader lifecycle -and navigation proofs. The five catalogue rules remain Registered. - -**Review round 1 — `578dcd8`.** Fresh runtime/security and proof/structure -reviewers approve without actionable findings. Independent focused replays pass -122 and 400 cases. They verify single bootstrap ownership, exact middleware -refusals, bodyless HEAD, eligible Retry-After bounds, immutable snapshot identity, -post-await and memo-hit lifetime checks, cancellation and retained source fences. -Neither review claims Step 3's actual API/PostgreSQL or navigation obligations. - -**Review round 2 — `578dcd8`.** New runtime/security and proof/structure reviewers -approve without actionable findings. Independent focused replays pass 122 and -439 cases. They confirm real memo/runtime controls reject completed and -cross-store values before Education or result inspection, while preserving -request cancellation and the server-only boundary. Step 2 is complete; the -remaining production proof obligations stay with Step 3. - -###### ADR-0055 Step 3 — Production admission proof and closeout - -**Implemented — 2026-10-10; both independent review rounds complete.** The six -existing production modes consume the shipped native admission snapshot. -Release execution through real API/PostgreSQL passes all six cases, with zero -skips: transport **39**, foundation **33**, pagination **12**, presentation **30**, -product isolation **28** and product freshness **34** API calls. Exact checkpoint -assertions preserve the approved two/one/three-call contract, prior content-state -behavior and existing isolation, containment, build and stock-launch controls. - -`PublicAdmissionRenderingTests` and `verify-public-admission.mjs` add one actual -production case with three separately budgeted phases: wire **32**, lifetime -**48** and browser/HMR **10** API calls. Healthy calls use the real API and -PostgreSQL as `learnstack_app`, with positive READ ONLY and non-bypass observations. -Test-owned boundary faults exercise first-wire GET/HEAD 404/429/503, bounded -Retry-After, malformed/oversized responses, transport failures, deadlines and -invalid site admission. Refusals load no Education or tenant theme. A wrong-status -mutant fails the wire oracle, followed by a passing clean control. - -The lifetime phase forces overlapping identical HTML/RSC/prefetch requests and -mixed host/locale requests, proves distinct deeply frozen snapshots, and checks -zero retained contexts/snapshots after completion. Four concurrent prefetch lanes -make exactly eight API calls. Physical keep-alive reuse starts fresh admission; -client aborts cancel held bootstrap/content calls. A valid HEAD response finishes -before test-owned deferred work resumes; that work is refused before Education. -Shutdown cancels two held content requests, clears both snapshots and exits -without fixture escalation. Missing, duplicated and mismatched native contexts -fail closed without an API call. - -Stock Brave 154.1.96.61 proves actual refused Flight navigation at 429 and 503 -falls back to a new document request. The browser uses a disposable profile and -fixture certificate trust, without changing workstation trust. Development HMR -changes both source and live API data in the same process and proves fresh -admission with two site calls and no Education call. A bounded TLS WebSocket -watcher waits for the pinned Next compiler's `serverComponentChanges` message; -sync/client-only frames cannot release the source-change barrier. These are -narrow navigation/lifecycle proofs, not P02d-7's browser demo, Lighthouse or a new -manual accessibility audit. - -Two observed gaps were corrected before this commit. A successful JSON-shaped -response with the wrong media type was accepted by the configured caller; it now -requires the existing success/Problem Details media types before SDK parsing, -with cancellation, reader-release and positive controls. The initial full Docker -run exposed an HMR source-watcher race despite a passing focused run. The compiler -completion barrier replaces the racing source-write/request sequence; the focused -production case and subsequent full Docker run pass without retry or sleeps. - -Final local validation passes **2,946 backend cases**: **1,705 unit**, **198 -architecture**, **4 contract**, **172 Docker-free integration** and **867 Docker -integration**, zero skips. The guarded frontend run passes **1,402 cases**: -**1,342 web and 60 SDK**, zero skips/todos. Release build has zero warnings/errors; -format, workspace lint/typecheck, production build, native ingress and all -**19** ingress cleanup controls pass. The five admission catalogue rules are -Implemented with executable owners and planted controls. Accepted ADRs retain -their original bodies and receive dated delivery navigation. The reviews and -subsequent CI investigation are recorded below. - -**CI investigation and native completion proof.** The first Linux run on -`37ec51e` passes 866 Docker cases but fails the new production Fact during its -healthy wire control, after both real API calls return 200. An independent initial -console-only local attempt also fails without a retained substage; its captured -unchanged replay and five root replays pass. A diagnostic commit splits the closed -wire-control stages without printing provider or response data. - -The proof had inferred native completion from client response EOF. Node's socket -write callback emits server `finish`; client EOF and a later IPC message do not -establish that event has run. A test-only independent finish/close observer now -registers after production disposal listeners and waits for actual native terminal -events before asserting zero counts. Held-active observations stay immediate. -Six dirty/clean cases prove client/delegation completion cannot release the barrier -and missing runtime cleanup still fails after the barrier resolves. No sleep, -count-poll, production lifetime change or API retry is added. The actual production -Fact and guarded 1,402-case frontend run pass locally with this proof correction. -The diagnostic-only `9f785fc` then passes all six required jobs, including all -867 Docker cases and the new production Fact in -[run 38054051927](https://github.com/HodeTech/LearnStack/actions/runs/38054051927). -The exact first Linux substage remains unknown; this passing replay does not -establish the original cause. The completion correction addresses an independently -verified ordering assumption, not a claimed reconstruction of that failure. - -**Review round 1 — `7a2b4b2..37ec51e`.** GPT-6-astra and GPT-6.1-sol, both at -xhigh effort, review runtime/security and production proof/documentation -respectively. Both approve without actionable findings and independently pass -94 focused cases. They do not claim another full production-suite run. - -**Review round 2 — `7a2b4b2..37ec51e`.** Fresh GPT-6-astra and GPT-6.1-sol -reviewers at xhigh effort check runtime/lifecycle and proof/documentation. Static -runtime checks and 94 focused cases pass, but the runtime review's first -console-only production attempt fails as recorded above; its retained unchanged -replay passes. The proof reviewer records the early catalogue-status promotion: -`37ec51e` marked five rules Implemented after passing execution but before both -review rounds, contrary to the approved sequence. This process deviation is -preserved here rather than rewriting the plan. The later completed reviews and -fix verification support the current Implemented status. - -**Focused fix review round 1 — `9f785fc..b8d5199`.** Fresh GPT-6-astra at xhigh -effort verifies native observer ordering, independence from runtime counts and -unchanged active observations. It finds a real proof gap: one microtask wait lets -an already-resolved empty-pending mutant pass all six controls. Independent -verification reproduces that behavior; `100534f` crosses a deterministic -`setImmediate` turn before both pending assertions. The actual Vitest mutant now -fails three cases; restored production code passes all six. No wall-clock sleep or -runtime change is added. - -**Focused fix review round 2 — `9f785fc..100534f`.** Fresh GPT-6.1-sol at xhigh -effort approves without actionable findings, independently passes all six cases -and rejects the empty-pending mutant at all three corrected assertions. It -verifies native completion cannot conceal missing runtime cleanup and that the -existing ten-second IPC bound and API accounting remain unchanged. The guarded -full frontend replay passes 1,402 cases, zero skips/todos. - -The repeated optimizer-child cleanup comment is not applicable: `start()` -registers the child with its owner immediately, and failure unwinds through the -existing top-level `finally`/`owner.dispose()`. The implementation agent and an -independent proof reviewer verify that path; no redundant local cleanup is added. -The original manual browser/VoiceOver evidence retains its tested scope and commit. - -Closeout verification passes 198 architecture cases and seven ADR-workflow cases, -with no failures or skips. A local audit of the 37 changed Markdown files checks -2,392 relative links and 735 fragments without missing targets; inline/fenced -examples are excluded. Added prose respects 88 columns. CI's link gate still -checks file existence only. - -**Subsequent Linux capture failure — `b8d5199`.** Native completion checks pass, -but the admission Fact rejects an empty real API log capture; 866 other Docker -cases and five required jobs pass. The pinned Serilog hosting implementation uses -a process-global logger by default: another concurrent API host can replace it, -and disposing that host can close it. This verified shared-state mechanism does -not establish the exact historical interleaving. The public-read xUnit collection -now explicitly opts out of parallel scheduling with other collections, preserving -production logger configuration, enrichment, sink disposal and the nonempty-log -assertion. Forced overlapping HTTP requests inside each proof remain concurrent. -No logger replacement, synthetic event, polling or weakened assertion is added. -**Log-capture fix review round 1 — `ef05ab0`.** Fresh GPT-6-astra at xhigh -effort approves without actionable findings. It verifies the pinned xUnit runner -awaits parallel collections and their fixture disposal before starting an isolated -collection. It independently confirms the pinned Serilog global-logger mechanism, -sequential API phase ownership and the unchanged forced HTTP overlap gates. - -**Log-capture fix review round 2 — `ef05ab0`.** Fresh GPT-6.1-sol at xhigh -effort independently approves without actionable findings. It checks collection -and child-host lifetimes, awaited/idempotent fixture disposal, real-log assertions -and the four-arrival request barriers. Neither reviewer starts another Docker or -browser run or claims to reconstruct the earlier Linux interleaving. - -**Fix verification.** The full local Release Docker suite passes **867 cases**, -including the admission Fact and all six retained production modes, with zero -failures or skips. Release build has zero warnings/errors; format verification, -all **198 architecture cases**, seven ADR-workflow cases and the local link audit -pass. The previous guarded frontend execution remains **1,402 cases**, zero -skips/todos; this scheduling fix changes no frontend source. Two overlong prose -lines in this P6 delivery record are wrapped without changing their meaning. - -All three implementation steps and both subsequent focused fixes have completed -their two independent review rounds. The [PR #27 description](https://github.com/HodeTech/LearnStack/pull/27) -owns final exact-head CI after this documentation commit. Maintainer review and -merge remain pending. P02d-7 retains the full browser demo and Lighthouse; -Phase 06/11 retain their named broader accessibility and production-hardening work. - -**Latest external review follow-up — 2026-10-10.** The review against `d1cc011` -reports no Blocker or Major. Its fixed-port observation is valid: native listening, -Next's port option and redirect authority now share `PUBLIC_HTTPS_PORT`, preserving -the Accepted local HTTPS port 3000. Middleware explicitly narrows the verified -envelope instead of using a non-null assertion. - -The admission proof now also holds four scaffold requests at one real API barrier: -two hosts, each requesting `/studio` and `/portal`. Distinct seed palettes provide -positive controls; each HTML response contains its own palette and excludes the -other tenant's palette and name. Four separate immutable snapshots are released -after native completion. The driver asserts exactly four site calls and no -Education call for this checkpoint. The lifetime phase now uses **52** API calls; -wire **32** and browser/HMR **10** remain unchanged. The earlier **48**-call receipt -above describes the previous proof revision. - -The suggested silent/shared logger replacement is not applied. The unsupported -renderer warning is intentionally bounded to one event per request, contains only -fixed state/count fields and has a passing privacy/once-only test. Phase 11 owns -the broader frontend observability contract; removing this signal would weaken -the current diagnostic contract. - -**Follow-up review round 1 — `1496269`.** Fresh GPT-6-astra at xhigh effort -approves without actionable findings. It verifies shared port authority, explicit -envelope narrowing, real overlap, independent seed palettes, snapshot identity, -native completion, exact accounting and the bounded scaffold coverage claim. - -**Follow-up review round 2 — `1496269`.** Fresh GPT-6.1-sol at xhigh effort -independently approves without actionable findings. It reconciles the **32/52/10** -phase totals and checks provenance, cleanup, falsifiability and documentation. -Both rounds are read-only source reviews; runtime execution belongs to the parent. - -Focused local verification passes: the real admission Fact **1/1**, retained -rendering **20/20** (including all six production modes), architecture **198/198**, -guarded frontend **1,402/1,402**, typecheck, native compilation, lint and changed -C# format verification. TRX counters confirm zero failures/skips; the frontend -runner also refuses skips/todos. The PR description owns final exact-head CI -after this review-record commit. Maintainer review and merge remain pending. - -**Ingress instrumentation follow-up — `b073f35`.** The shared-port refactor also -changes a literal launcher anchor used by the separate native ingress fixture. -Its first [CI execution](https://github.com/HodeTech/LearnStack/actions/runs/38060818584) -rejects missing automatic-upgrade observations. The disposable copy now matches -the shared constant and checks that both instrumentation anchors occur exactly -once before rewriting. The fix changes no production code or assertion strength. -Local production build, native TLS/ingress proof, all **19** ingress cleanup/ -negative controls and lint pass. - -**Instrumentation fix review round 1 — `7ea14c5`.** Fresh GPT-6-astra at high -effort approves without actionable findings. In-memory checks reject missing and -duplicate anchors and confirm that the transformed launcher parses. It verifies -observer installation before Next's first-request upgrade registration, unchanged -upgrade assertions and compatible cleanup controls. - -**Instrumentation fix review round 2 — `7ea14c5`.** Fresh GPT-6.1-sol at high -effort independently approves without actionable findings. It checks actual -transformation syntax, one shared-constant listener, adjacent source anchors, -registration order and cleanup. Both rounds are read-only and start no runtime -services. The PR description owns final exact-head CI after this record commit. - -### P02d-6 merge and closeout (2026-10-10) - -The maintainer merged [PR #27](https://github.com/HodeTech/LearnStack/pull/27) at -2026-10-10 17:07:50 UTC. GitHub records final PR head -`46ed971bf976514fb451a162cc9450d147ed0441` and merge commit -`378346126949c90bb286b5217c24513fc2044f06`. The merge's second parent is that -head, and both commits have the identical tree. Development is fast-forwarded to -the verified merge without changing branches or rewriting history. The final -head includes the testing-standard correction marking both ADR-0055 Step 3 -review rounds complete. - -- All six required checks pass on the - [final PR head](https://github.com/HodeTech/LearnStack/actions/runs/38070332107) - and the [merge commit](https://github.com/HodeTech/LearnStack/actions/runs/38070479860). - Independently downloaded merge-run TRX confirms **2,946 passed**, zero failures - or skips: 1,705 unit, 198 architecture, four contract, 172 Docker-free - integration and 867 Docker integration cases. -- Merge-run frontend logs confirm **1,402 passed** (1,342 web, 60 SDK), successful - typecheck, lint, production build and SDK drift verification. Native production - ingress verification and all **19** setup/cleanup and negative controls pass. - Release builds report zero warnings and errors. These are merge-run receipts; - the documentation closeout does not rerun the full runtime suites. -- Read-only verification confirms `strict: true` and the same six required Actions - contexts, including OpenAPI diff and Docker integration. No protection setting - changes. Lighthouse remains disabled with activation owned by P02d-7. - -**P02d-6 is closed.** Localized catalog, course/outline and ordered plain-text -lesson pages, safe four-color themes, exact-locale metadata, scoped pagination -and controlled public states are delivered. ADR-0055 adds middleware-owned single -bootstrap admission, immutable request-local reuse and production lifecycle/ -isolation proofs. All implementation steps and focused fixes retain their -recorded independent review rounds. The -[packet closeout](#p02d-6-packet-closeout-2026-10-10) owns scoped keyboard, focus, -reflow and contrast observations and the maintainer's VoiceOver smoke; this -merge adds no new manual observation or full WCAG-conformance claim. - -**Next: P02d-7 — Demo, full-stack CI and exit.** Its decision pass and -implementation have not started. Resolve the remaining G20/G33/G38/G44/G45 parts -against the delivered renderer before harness implementation: - -- Define `make demo` and stop/re-run ownership on a clean checkout, environment - projection, readiness, non-destructive seeding and the printed host/locale URLs - (G45). Local use and CI reuse the selected entrypoint. -- Select Lighthouse's tools, both-host/locale URL set, assertions, budgets, - aggregation and artifacts; activate its currently disabled job and reconcile - standards/required-check carriers with the chosen enforcement (G44). -- Complete the shared full-stack/browser demo and trusted-hop CI evidence - (G33/G38), including anonymous catalog-to-lesson flows with Keycloak stopped. -- Implement and prove G20's remaining production/seed and frontend genericity - fences in required checks, preserving tenant-data-driven differences. -- Reconcile every exit criterion and register row with its evidence and record - the Education/seed preservation obligations and premises `P02b-0` re-verifies. - [Phase 02b](phase-02b-events-auth.md) follows only after the Phase 02d exit - decision, not this packet merge. - -Phase 06 retains full Studio/portal, authored composition and Playwright/axe; -Phase 11 retains broader production hardening and telemetry. Course Marketplace -commerce is not delivered by this closeout. Earlier dated delivery records, -including their pre-merge pending statements, remain historical and unchanged. - -**Documentation-only closeout validation.** All **198** local Release architecture -cases and seven ADR lifecycle/workflow controls pass, with zero failures/skips. -The six changed Markdown files resolve **873** relative links and **371** fragments -with zero errors in the local audit. Added prose wrapping and diff checks pass. -Earlier dated phase records are byte-preserved; no Accepted ADR or production -code changes. - -### P02d-7 decision package (2026-10-10) - -**Accepted — 2026-10-11; package and revised ADR-0056 approved.** Read-only -inspection starts from `f857437` on `development`, after the P6 merge closeout. -The maintainer approved the lifecycle, genericity, four-step review plan and -bounded seventh-check activation after real success. No implementation, passing -P7 test, enforcement delivery or phase exit is claimed. The user requires new -ADRs to be reviewed and approved before dependent work. Accepted -[ADR-0056](../decisions/0056-public-demo-browser-and-lighthouse-enforcement.md) -owns the new browser/Lighthouse measurement and required-check contract. - -P7 completes the walking skeleton's operational proof: a reviewer starts the -actual seeded sites with one command; the same lifecycle supplies CI's browser -and audit job; genericity and every phase-exit obligation receive named evidence. -Education writes, public DTOs, tenant authority, native ingress, anonymous quotas, -and request-local admission retain their Accepted contracts. - -#### P02d-7 inspection and document actions - -Three independent read-only review lenses covered demo/orchestration, -browser/Lighthouse, and genericity/exit. Source inspection was cross-checked with -the current branch and official tool metadata. This preparation executes no -runtime suite and does not reuse P6's counts as P7 results. - -| Area reviewed | Current premises and required action | -|---|---| -| README, CLAUDE, platform vision, MVP scope, roadmap index, principles and glossary | P1–P6 are merged; P7 is the remaining exit packet. Preserve the white-label/data-driven boundary and Proposed marketplace status. Keep current packet surfaces synchronized without rewriting dated delivery history. | -| ADR-0018/0035/0036/0040/0043/0048/0050/0051/0052/0053/0054/0055 and ADR-0027 | Existing content, RLS, read-only, exact-pin, TLS/provenance, quota and one-bootstrap contracts survive. G20/G45 implementation detail needs no ADR; new measurement/tool enforcement is Proposed ADR-0056. | -| Standards 03/06/07/08/11/12/13/14/15/16/20/21, CI and CONTRIBUTING | The Lighthouse job is still disabled. Qualify Testing 06's “None exist / first browser flow Phase 06” when P7's narrow flow ships; retain full Phase 06 Playwright/axe ownership. Update Performance status only with hard enforcement and distinguish CI targets from timeouts. | -| Makefile, compose dev/e2e, seed/public-local launchers, ingress/configuration and public server | No demo target exists. `make seed` runs migrations before the script's readiness gate. Wait for PostgreSQL before migration; parameterize one compose selection through start/wait/migrate/seed/stop. Health endpoints alone cannot prove seeded readiness or listener ownership. | -| SeedData, source-reader/name guards, module-reference guards and frontend source census | The existing source proof reads all strings, not just identities. Derive a typed identity vocabulary for G20 and canonical built-ins; add the whole-production Seeder-reference fence. Existing HTML/Flight schema-replacement proof supplies a behavioral companion, rather than a duplicate production mutation surface. | -| Production renderer fixture, admission browser, cleanup helpers, seed/local-dev/integration/test skills, compose and web READMEs | Reuse owned-process/TLS/private-output controls. Correct stale seeder activation, P6 merge and raw API restart guidance. Narrow old “CI uses Testcontainers only” and human-only browser statements when the compose-backed proof ships. | -| Phase 02b/05/06/11 and module handoff documents | Fix Phase 02b's mutable plain-HTTP/open-G32 premise; carry native HTTPS, visitor/peer accounting and single-bootstrap inputs into P02b-0 re-verification. Preserve Phase 05 migration obligations and Phase 06/11 ownership. | - -No accepted ADR body or prior delivery record is rewritten. Current contradictions -outside the new package receive bounded carrier fixes in the owning step; the exit -matrix verifies they are all resolved. - -**Preparation review — 2026-10-10.** Independent GPT-6-astra and GPT-6.1-sol -reviews verified the proposal against current contracts/source. Corrections -cover the package heading, complete seeded-ID vocabulary, actual Lighthouse -audit/navigation set and live status carriers. The maintainer's external review -additionally exposed the ADR lifecycle parser incompatibility; it was reproduced -and fixed. Metric/batch wording, tool pin/license placement, decimal gzip units -and the exact Testing 06 carrier action are now explicit. Earlier dated -“not started” statements describe their record time; this package and the top -packet table own current state, and Step 4 verifies that navigation at closeout. - -Documentation preparation passes all 198 Release architecture cases and all -seven ADR lifecycle/workflow controls, with zero failures/skips. These results -validate the draft corpus, not the unimplemented browser/Lighthouse harness. - -**Additional maintainer review — 2026-10-11.** The review identified ambiguity -between per-audit timeouts and the total deadline. Revised ADR-0056 specifies -one serial worker, nested deadlines and the 244-second quiet-window cost; the -first complete run must prove feasibility before activation, with no silent -parallelism or reduced census. It makes the potentially stricter gzip window, -origin coverage and exclusions explicit, names the four budgeted audits and -keeps FCP/Speed Index unasserted. The source-verified category name replaces the -imprecise agentic term. Tool ownership, behavioral script-rule ownership and -G33's retained human evidence are explicit. The revised ADR remains Proposed. - -An independent GPT-6-astra review found no unresolved revision finding. -Read-only upstream verification confirmed the audit/filter selection and the -pinned DevTools source for slow-4G constants. Revision validation passes 198 -Release architecture cases, seven ADR lifecycle/workflow controls and the -changed-document relative-link/anchor, wrapping and diff checks. No browser run -or timing feasibility is claimed by these preparation checks. - -#### P02d-7 accepted answers - -The maintainer approved the package on 2026-10-11. G20 detail, G33 CI topology, -G38's narrow browser-job scope and G45 lifecycle are Accepted planning decisions; -their implementation and proof remain pending. The maintainer subsequently -approved revised ADR-0056 on the same date, closing G44's measurement decision. -The seventh-check activation is authorized only after the approved ADR's complete -real PR run succeeds. The combined decision commit precedes implementation. - -| Gate | Approved scope / remaining decision authority | -|---|---| -| G20(b/c/d) | Typed exact identity matching, bounded canonical built-ins/exemptions and a whole-production Seeder-reference ban; the section below owns the detail. Implement the existing Registered rule and adopt the real schema-replacement companion. | -| G33 CI part | Same workstation-style loopback API/native TLS topology in the CI runner, one per-run secret, real migrated database and `learnstack_app`. Disposable CI certificates/resolver mapping; no system-trust mutation or additional trusted transport. | -| G38(c) job | A narrow managed-Chromium library script follows real catalog → course → lesson links in the three seed host/locale lanes. Existing product HTML/Flight proofs remain required; full Playwright/axe stays Phase 06. | -| G44 remaining detail | Accepted ADR-0056 owns direct pinned Lighthouse/Chromium, nine URLs × three runs, actual-page admission, hard gzip/CLS/accessibility checks, advisory timings, serial real-window pacing and artifacts. Its revised measurement contract was approved on 2026-10-11. Bounded activation of `public demo + lighthouse` as the seventh required check is approved only after the complete approved proof succeeds on a real PR, with protection read-back. | -| G45 | Foreground production-demo supervisor, shared full seed gate, persistent non-destructive local data and owned-process cleanup; the lifecycle below owns the details. | - -#### P02d-7 demo lifecycle - -`make demo` is the local entrypoint; `make demo DEMO_MODE=ci` selects isolated -automation through the same lifecycle. The mode selects environment/compose -ownership and the proof driver, not different product code or a bypass. Make -arguments are validated; startup, readiness, migration, seeding and cleanup share -one explicit compose project/file/env selection. - -1. Check installed prerequisites and refuse concurrent ownership or occupied - API/web listeners; never adopt or kill a foreign process. Restore locked - frontend, .NET and tool dependencies without changing Git hook configuration. - Prepare missing private root configuration from `.env.example`, validate - required values and refuse stale/disagreeing projections rather than overwrite - user values. Generate a missing hop secret through the existing preparation. -2. Local hosts/CA/leaf preparation remains the explicit manual G32 prerequisite. - Verify host resolution, certificate/key match, validity and trust with - actionable sanitized errors before infrastructure starts. Never edit system - hosts or install a root CA automatically. CI creates private disposable - configuration/certificates in its owned checkout and uses ADR-0056's scoped - browser trust and independent Node TLS checks. -3. Start the existing seven-service default compose stack, wait for PostgreSQL - before any migration, then retain the existing full default-service and both - Keycloak-realm seed gate. Apply all current migration chains with the migration - role and seed via the normal contextual request path as `learnstack_app`. - No destructive reset, overwrite or direct seed SQL is added. -4. Build the web production bundle and API, then launch the real API and mandatory - native HTTPS web listener in owned process groups. Use existing paired private - configuration, role validation and child-environment boundaries. These are - production builds with the accepted local Development deployment mode; - stock `next start` is not substituted for native ingress. -5. Declare ready only after owned-child readiness, verified TLS and positive - host/locale/content checks. Print catalog/course/lesson URLs for English - `en` and Yoga `tr-TR`/`en`, derived from the seed declaration. Static - `/healthz` or `/api/healthz` success alone is insufficient. -6. Ctrl+C, parent/control closure, child failure or a startup error stops and - joins owned API/web process trees. Local compose/data remains available; - `make down` is the explicit infrastructure stop. Re-run after shutdown - converges without reset; simultaneous invocations fail clearly. -7. CI uses the existing e2e overlay and a unique owned project. Stop its Keycloak - after successful seeding and assert the stopped state before fresh browser - navigation. On every exit, remove only that invocation's processes, project - and private files. Confirm child exit before deleting sensitive trees; fail - and preserve private diagnostics if cleanup cannot be established. - -Browser/Lighthouse uses actual limiter windows under ADR-0056. No API restart, -quota inflation, forged visitor or 429 retry is part of a successful proof. -API status/call observation must have a nonempty positive control; missing or -truncated observation fails. Reuse structured host completion events where -possible, retaining only sanitized counters/receipts in artifacts. - -#### P02d-7 genericity enforcement - -The typed `SeedData` declaration remains the single identity source. Build the -G20 vocabulary from every declared entity ID, including built-in row and theme -IDs; tenant/organization slugs, hosts and display names; course/lesson keys and -localized slugs/titles; customization keys, item keys, schema property names and -localized definition/field/band labels. Do not classify -ordinary body prose, locale codes, publication/access values or JSON-schema -keywords as tenant identities simply because the existing reader sees them. - -Compare complete decoded string values ordinally; compare GUID literals by -their parsed GUID value. This is an exact-literal fence, not a claim to prove -every possible dynamically assembled branch. Read C# literals, frontend TS/JS -literals and JSON values with syntax-aware readers, excluding comments. Fail on -unreadable/empty identity sources or production subjects. Preserve the frontend -census's refusal of unsupported source forms; no silent extension/import gap. - -Canonical platform built-in keys/labels come from their owning declarations/registries, -not copied into an expanding arbitrary allow-list. Preserve the accepted G20(c) -bounded exemptions: `SeedData`, explicitly identified seed/development launch -data, operational documentation and test-owned fixtures/assertions. Production -middleware, ingress, transport, renderer and message catalogues are subjects. -No blanket `scripts`, configuration or catalogue directory exemption is added. - -Additionally forbid every non-test production project except the Seeder itself -from referencing `LearnStack.Tools.Seeder`, both through compiled references and -restore-resolved project references. This catches identity comparisons through -`SeedData` symbols that contain no local literal. - -Planted failing controls cover backend identity/customization-ID comparisons, -renderer/transport branches, a shared frontend helper, message JSON values and -Seeder references. -Passing controls cover comments, canonical platform built-ins and specifically -allowed development/test data. Prove the actual production census is nonempty. -Re-run the existing real API/PostgreSQL/HTML/Flight presentation successor-revision -proof as the behavioral companion, with a field-assertion failure control; retain -original-pin and unaffected-tenant checks. The new browser proof observes -distinct ordered authored fields, without adding a production mutation endpoint. - -#### P02d-7 implementation plan - -Work remains on `development`; no alternate branch or worktree. Each step lands -its implementation commit, then two fresh independent agent review rounds. -Verify findings against current code, fix valid findings and commit before the -next round/step. A new architectural decision pauses only its dependent work. - -| Step | Delivery | Validation before completion | -|---|---|---| -| 1 — Shared demo lifecycle | Compose selection, pre-migration wait, locked restoration, private configuration, foreground ownership, production build/start, seeded readiness, non-destructive repeat/stop and local guidance. | Clean-checkout preparation with the documented manual TLS prerequisite; repeat convergence; stale/missing configuration; port collision/foreign listener; child failure, signal/parent closure and owned cleanup controls. | -| 2 — Genericity and exit foundations | Existing G20 production literal rule, whole-production Seeder-reference fence, canonical built-ins/exemptions, behavioral companion and preliminary criterion/evidence inventory. | Nonempty backend/frontend/JSON census; planted dirty/clean controls; architecture/unit/contract and relevant integration tests; existing exact-pin/schema-replacement product proof. | -| 3 — Browser and audit proof | Pinned tools/browser; seed-derived nine-URL manifest; Keycloak-stopped linked navigation; computed themes/ordered fields; actual audited-page admission, gzip collector, metrics/census validator, rate pacing and sanitized artifacts. | Real same-build/same-database run; no API 429; positive call observer; wrong/error page, invalid report, over-budget and missing-source controls; TLS and failure cleanup; all 27 report pairs. | -| 4 — Required CI and phase exit | Always-running seventh job, bounded protection activation after real success, standards/carrier alignment, complete evidence matrix and P02b-0/Phase 05 handoff. | All backend/frontend suites with zero skips; real CI and live protection read-back; links/anchors/wrapping; every gate/deliverable/criterion reconciled; zero 02d Registered/Awaiting rows; two review rounds and explicit exit verdict. | - -The new job does not replace any existing required suite or fixture. Preserve -the accepted P6 keyboard/focus/reflow/contrast and maintainer VoiceOver record, -with its actual limits; record new automated observations separately. Promoting -Performance to Active is conditional on delivering the proposed hard checks, -not on accepting this package. Its index/header/count change lands with the -enforcer; Accessibility is already Active for its delivered public-page scope. - -#### P02d-7 approval and exit boundary - -The complete lifecycle and G20/G33/G38/G45 answers, four-step review plan and -bounded seventh-check activation were approved on 2026-10-11. Revised ADR-0056's -tools/measurement/browser contract was subsequently approved on the same date. -Its register dependencies are recorded in the combined decision commit before -implementation. -No other unresolved product choice was found in this inspection. Unexpected -architectural changes need a separate reviewable decision; implementation details -inside the approved package proceed without further approval. - -At closeout, map every Deliverable and Completion Criterion to current named -evidence, including carried-forward evidence and its limits. Reconcile current -Phase 02b native-HTTPS/quotas/single-bootstrap premises without accepting its -auth/BFF gates. Record independent Course/Lesson roots, stable IDs/URLs, ordering, -scope, translated bodies, exact pins and access policy as Phase 05 preservation -obligations; re-seeding is not a migration. - -Do not declare Phase 02d exited merely because P7 code or its PR is complete. -The exit verdict must state which obligations passed, identify evidence/CI/protection -receipts and leave no unresolved 02d-owned gate or Registered/Awaiting rule. The -maintainer's PR review and merge remain separate from implementation completion. - -### P02d-7 Step 1 — shared demo lifecycle (2026-10-11) - -**Complete — both review rounds and their fixes verified.** -The foreground `make demo` supervisor shares explicit Compose selection, -PostgreSQL-before-migration readiness, full seven-service/both-realm admission, -contextual seeding, production builds and owned process cleanup. Local data is -retained; CI uses a unique project, disposable private configuration and the e2e -overlay. Its browser/audit driver remains Step 3 work and is not claimed here. - -`DemoManifest.Create` derives all three host/locale lanes, nine URLs, ordered field -expectations, palettes and excluded course titles from `SeedData`. Its export -requires no database. Configuration validation uses Npgsql's real parser to -refuse stale role/password/database/host/port combinations before infrastructure. -The runtime environment helper is shared with the existing paired API launcher; -migration and worker credentials are excluded. TLS prerequisites do not modify -hosts or system trust. The exclusive demo lock never kills a recorded foreign PID. - -**Initial verification.** The Release Seeder build has zero warnings/errors. -All 1,705 unit, 198 architecture, four contract, nine focused integration and -42 Seeder integration cases pass with zero failures/skips. Focused integration -includes eight manifest/configuration cases and the real-API/PostgreSQL local -launcher proof without a PlatformAdmin credential. The guarded frontend runner -passes 1,413 cases without skips/todos; the final 13-case focused suite also -covers structured API-listener readiness and an invocation-owned native cache. -Lint and typecheck pass. Node controls cover -explicit selection, readiness refusal, runtime credential isolation, foreign -listeners, bounded bodies, certificate mismatch, real process timeout/cancellation -and owned trees. These initial checks precede the complete startup and review -evidence below. - -**Complete isolated lifecycle proof.** An owned temporary checkout copy starts -all seven services with the e2e overlay, passes both realm gates, applies every -migration chain and seeds through the application role. Its owned production -API/native renderer passes positive lesson checks in all three seed host/locale -lanes. Re-running the ordinary Seeder leaves the nonempty audit count unchanged. -Teardown confirms process/project absence, removes its private configuration, -certificate tree and lock, and releases the API/web listeners. This is a Step 1 -startup/neutrality/cleanup proof; it is not Step 3 browser/Lighthouse evidence. - -**Workstation port prerequisite.** The first attempt correctly refused occupied -5080/5432 ports. After explicit maintainer authorization on 2026-10-11, the two -foreign containers were stopped only for validation and restarted afterward; -both returned healthy. LearnStack volumes remain intact. Its local PostgreSQL -and Keycloak cannot run concurrently while the foreign database retains 5432; -no port mapping or foreign project configuration was changed. - -**Step 1 review round 1 — `3160714..82459cb`.** Fresh GPT-6-astra and -GPT-6.1-sol reviewers independently covered the full diff through lifecycle/ -security and evidence/corpus lenses. Four distinct findings were verified: -selected-env migration fallback, terminal hangup cleanup, split UTF-8/byte-bound -capture and restricted-course marketing exclusions in the demo manifest. -Corrections add actual Make/configuration, process/signal/parent, split-output -and marketing-disjoint controls. Combined seeding now rejects disagreeing ambient -credentials before stack/migration actions. Default-service enumeration is shared -as reinforcement; the suspected gated-port defect was not reproduced. The -suspected parallel prerequisite race was rejected because global `.NOTPARALLEL` -already serializes those acts. The 18-case focused suite, typecheck, eight -manifest/configuration cases and all 198 architecture cases pass. Lint and the -guarded frontend run pass all 1,420 cases with zero skips/todos. The complete -isolated lifecycle rerun also passes real SIGHUP/repeated-signal cleanup and -listener release. The two authorized foreign containers return healthy afterward. - -**Step 1 review round 2 — `3160714..4966dca`.** Fresh GPT-6-astra and -GPT-6.1-sol reviewers independently inspected lifecycle/security and evidence/ -corpus. Both reran all 18 focused cases. Two additional findings were confirmed: -Docker can read `COMPOSE_PROFILES` from the selected dotenv file, and Development -API configuration can consult workstation user secrets through its profile. -The selected-file control now refuses reserved Compose assignments, including -export/whitespace/colon forms. A read-only real Compose control observes exactly -seven default services and refuses the planted file profile before Docker. -The demo API receives an empty invocation-owned HOME/APPDATA/TMPDIR; restoration -and builds retain their own profiles. A real API/PostgreSQL test accepts the -configured hop secret and rejects an additional secret planted in a foreign -profile. No user profile is modified. All 24 focused lifecycle cases, typecheck -and the real launcher cases pass with zero failures/skips. Lint, all 1,426 -guarded frontend cases and all 198 architecture cases pass. A fresh focused fix -review found that the foreign-secret request omitted its visitor header, allowing -an unrelated refusal to mask the regression. The corrected three-case real API -suite supplies that header and removes the profile boundary only in an owned -copy: the foreign secret now produces 200 in the mutant and 404 in the clean -runtime. All three cases pass. Both required review rounds and their verified -fixes are complete; Step 2 follows. - -### P02d-7 Step 2 — genericity and exit foundations (2026-10-11) - -**Implementation and both independent review rounds complete.** The exact-literal -G20 fence reads categorized `DemoIdentities.Create` values derived from typed -`SeedData`, including all declared IDs and translated identity/definition/field -labels. Ordinary body prose, locale/status/access values and schema keywords do -not become identities. Canonical platform values come from -`BuiltInCustomizations`, including collisions with demo values. - -Backend Roslyn and frontend TypeScript AST readers compare complete decoded -strings ordinally and GUIDs by value, including alternate spellings. Embedded -JSON strings and standalone JSON values are inspected. Source parse errors, -empty/malformed vocabulary and missing production subjects fail loudly. The -frontend fixture is derived, not a second declaration; architecture tests compare -it to the current typed projection. Regenerate it after editing `SeedData`: - -```sh -dotnet run --project backend/src/LearnStack.Tools.Seeder -c Release -- \ - --demo-identities > frontend/apps/web/src/test/fixtures/demo-identities.json -``` - -The backend scans Seeder orchestration as production and exempts only its exact -`SeedData.cs` declaration. Frontend scans app/package/configuration/native code -and root Node scripts, with exact named test-proof and development-launch data -exemptions. The existing unsupported-runtime-source/import census is preserved. -Every production project except the Seeder is checked for both compiled and -restore-resolved Seeder references, preventing symbolic `SeedData` access. - -The existing real API/PostgreSQL/HTML/Flight presentation successor proof calls -one shared ordered-field assertion. Planted label, value, ordering, active-markup, -language and internal-name controls exercise the same predicate without changing -production rendering. Original-pin and unaffected-tenant observations remain. - -**Initial verification.** Release suites pass 1,705 unit, 203 architecture and -four contract cases with zero failures/skips. The existing presentation-mode -real API/PostgreSQL/native production proof passes (one case), exercising both -HTML and Flight, successor/rebinding, original pins and the unaffected tenant. -Lint, typecheck, formatting and all 1,442 guarded frontend cases pass with zero -skips/todos. This is not Step 3 browser/Lighthouse evidence. - -**Review round 1.** Fresh GPT-6-astra and GPT-6.1-sol reviewers independently -checked backend identity/reference coverage and frontend subjects/behavioral -controls. Four verified omissions were fixed: conditional C# branches, UTF-8 -literals, emitted JSX values and runtime helpers hidden by test exemptions. -The initial fix exposed conditional branches conservatively; round 2 below -replaces that approach to preserve lexical semantics. JSX handling uses TypeScript's -emitter. Exact test directories replace name-wide directory exclusions, and -runtime relative imports include helpers even behind test filenames. Native HMR -and the shared process-stop helper are production subjects. Planted dirty/clean -controls cover all four findings. Release architecture (203), guarded frontend -(1,444), lint, typecheck, formatting and the documentation link audit pass. -Second-round review follows the fix commit. - -**Review round 2.** Fresh GPT-6-astra and GPT-6.1-sol reviewers verified three -census omissions and one ordering-control gap. Flattening C# branches could let -an inactive comment hide active code. The reader now parses feasible symbol -configurations independently, discovers conditional symbols to a fixed point, -and refuses more than eight symbols or unreadable configurations. UTF-8 and raw -literal semantics remain intact. Frontend generated-output exclusions now name -actual roots; nested source directories remain subjects. Runtime imports resolve -local module URL query/fragment suffixes and percent escapes, while computed -imports fail loudly. Literal `require.resolve` loads remain countable. The -ordering offender now swaps intact label/value pairs rather than corrupting them. -Release architecture (203) and all guarded frontend cases (1,446), lint, -typecheck, formatting and link/anchor checks pass. Fresh fix verification follows. - -**Fresh fix verification.** The prior omissions are closed. The verifier found -one new resolver-options gap: a relative `require.resolve` input could redirect -through `paths`. That unmodeled form now fails loudly, with a planted control; -the actual literal external-package ESLint load remains accepted. Both review -rounds and their verified findings are complete. Step 3 follows. - -#### P02d-7 preliminary exit evidence inventory - -This is an inventory, not a phase-exit verdict. Step 4 reconciles every individual -Deliverable and Completion Criterion against exact-head evidence, current CI and -protection receipts; historical delivery records retain their original limits. - -| Criterion group | Existing evidence to retain/recheck | P7 completion work | -|---|---|---| -| Two sites, linked catalog/course/lesson, distinct field sets and branding | P6 product/presentation HTML/Flight fixture; maintainer keyboard/focus/reflow/VoiceOver record; `DemoManifest` typed expectations. | Step 3 real Chromium linked navigation and computed themes, three host/locale lanes; same API/web/database with owned Keycloak stopped. | -| Clean preparation, non-destructive repeat and owned stop | Step 1 isolated seven-service/two-realm startup, audit-neutral Seeder repeat and signal/parent/process/TLS controls. | Step 3 shares the lifecycle; Step 4 records complete CI receipt and cleanup. | -| Education schema, RLS, scope, satellites, parents, privileges, migrations | `EducationIsolationTests`, migration/tenant-scoping/index/grant sweeps and P1 delivery record. | Re-run full backend suites at exit; Phase 05 preservation handoff. | -| Writer invariants, exact pins, locale/slug/state/body validation, MUST audit, branding and seed convergence | `EducationWriterTests`, `TenancyWriterTests`, `SeederTests`, P2 record. | Re-run with zero skips; retain typed inventories and bounded branding/access contracts. | -| Definition/settings reads, generations, rollback safety, fallback, no read validation | `CustomizationProjectionTests` and composition/cache/settings suites; P3 record. | Re-run; retain existing generation/family metrics and settings freshness boundary. | -| Public eligibility, cursor/scope/locale, DTO/HEAD/OpenAPI/SDK, no-store, read-only pipeline | P4 public HTTP, contract, transaction and dispatch guards. | Re-run SDK/contract/OpenAPI drift and all required checks; retain current seven-check read-back only after success. | -| Provenance/ingress/hop/visitor limits, private carriers, native production freshness, single bootstrap | P5 remediation and ADR-0055 real native/API proofs; P6 bootstrap/refusal coverage. | Step 3 uses identical ingress/limiter and records positive API calls with zero 429. | -| Localized renderer, inert authored text, metadata/status, manual accessibility | P6 i18n/route/HTML-RSC/a11y guards and recorded human checks. | Step 3 observes actual browser documents; Lighthouse supplements the bounded manual record. | -| G20 exact-literal/reference fence and schema replacement | This Step 2 backend/frontend dirty/clean controls and existing presentation successor fixture. | Both independent review rounds; Step 3 ordered fields. Computed comparisons remain a review/behavioral boundary. | -| Performance/accessibility audits, report/census/gzip guards | ADR-0056 accepted obligations, four Registered behavioral rules. | Step 3 implements 27 report pairs/hard checks; Step 4 activates mandatory CI/protection and updates statuses with enforcement. | -| Governance, all gates/catalogue rows, module/standard/skill/vision/MVP carriers and named exclusions | Existing decision register and P1–P6 records. | Step 4 complete criterion matrix, zero 02d Registered/Awaiting rows, owner-document checks and P02b-0/Phase 05 handoffs. | - -### P02d-7 Step 3 — browser and audit proof (2026-10-11) - -**Complete — both independent review rounds and verified fixes pass.** -The shared CI lifecycle invokes `verify-public-demo.mjs` over the same seeded -production API/native renderer. `DemoManifest` also derives hidden lesson titles -and field values, excluding values shared with eligible public content. The -browser follows the actual catalog/course/lesson links in all three host/locale -lanes and compares computed theme colors, identity and ordered authored fields. - -Exact development-tool pins are Lighthouse 13.5.0 and Playwright 1.64.0, using -its managed full Chromium 156.0.8078.4, revision 1248. The audit configuration -has an independently recorded 125-audit/14-artifact census and complete category -weights. A custom initial-navigation gatherer observes the actual document and -all delivered Script bodies; it never refetches or navigates. The shared policy -checks original inline source, complete decoded bodies, normalized gzip and the -actual audited product DOM before admitting a JSON/HTML report pair. - -The structured API completion observer retains only aggregate status/path-family -counts. A fresh HTTPS product read supplies its positive control. Four serial -batches preserve the real admission policy, with the approved quiet intervals -and subordinate deadlines. The public receipt records setup/proof/cleanup -milliseconds, versions, configuration, source digests, report inventory and API -counts. Browser profiles, certificates, private configuration and raw logs stay -outside the public evidence. CI cleanup confirms owned process/project absence -and removes owned private files, environment and lock within its separate bound. - -**Initial verification.** All 43 focused frontend controls and eight existing -manifest/configuration integration cases pass with zero failures/skips. Lint -and typecheck pass. The guarded frontend runner passes all 1,489 cases -(1,429 web + 60 SDK); all 203 architecture cases pass, with zero skips. -The controls include actual installed Lighthouse configuration -resolution, measured over-budget sources, wrong/error product documents, invalid -reports/census, missing/truncated/foreign-target sources and split API events. -The first complete serial feasibility run passes: lifecycle setup 61,468 ms, -proof 549,269 ms (9 min 9 s), and confirmed cleanup 10,656 ms. It produces all 27 -JSON/HTML pairs and nine browser screenshots. All hard checks pass: normalized -initial JavaScript is 106,381–106,573 bytes, CLS is zero, and scored automated -accessibility is 1 on every run. The four proof batches observe exactly -18/36/36/36 successful API calls; the separate observer control observes two. -Both untrusted/wrong-SPKI browser controls refuse before reaching the API. -The CI-owned Keycloak stays stopped. Owned processes/project/private files, -environment and lock are removed; the two authorized foreign containers restart. - -LCP samples are 2,008.544–2,166.836 ms, producing an advisory median warning for -each of the nine URLs. Server response is 15–23 ms and TBT 4–16 ms. These are -local simulated lab samples, not field/p95 performance or a new manual WCAG pass. -This is working-copy feasibility evidence over the `69ce613` baseline and build -`vCA7HXnit3froptth4IYD`; it is not an exact-head CI claim. Subsequent receipt-only -hardening records the complete expected/configuration census and startup/final -counters; the final committed CI run must validate those changes. Step 4 owns -CI enforcement, protection activation and phase exit. - -The first runtime attempts exposed harness defects before any audit verdict: -macOS's certificate verifier stalled when Chromium inherited the isolated Node -HOME, and optional `undefined` configuration properties differed from their JSON -receipt. A causal disposable TLS experiment confirms certificate refusal with -the real account HOME; only the managed browser receives it, with an explicit -owned disposable profile. Worker/API environments remain isolated. Configuration -comparison now uses the serializable receipt and an actual-resolution control. -The linked nine-page browser path subsequently passed, with exactly 18 successful -API calls and no 429, before the configuration comparison stopped that attempt. -These observations are preliminary validation, not the complete feasibility gate. - -**Transitive review.** Both direct tools are Apache-2.0 development dependencies. -The added tree includes MPL-2.0 `axe-core` 4.14.0, used by Lighthouse's development -accessibility audit; retain its package license/source obligations if distributing -that tool. Existing runtime package versions are unchanged. Resolving the added -OpenTelemetry API peer changes some lockfile peer identities without adding -application instrumentation. The full-workspace audit reports zero critical, -one high and one moderate advisory; neither path comes from the new tools. -The existing [security triage](#remediation-group-3--approved-security-maintenance) -owns Braces' unfixed build-glob recursion issue and the incompatible-major -selector-parser fix. Their maintainer/backport/parent-migration ownership and -Security Standards deadlines remain unchanged; this is not a clean-audit claim. - -#### Step 3 review round 1 - -Fresh GPT-6-astra (xhigh) runtime/measurement and GPT-6.1-sol (xhigh) -proof/corpus/dependency reviews cover `69ce613..d99d10b`. Both request changes; -three verified findings concern the proof, with no production-code defect. -Independent root reproductions confirm each failure before correction. - -- Completion observation silently ignored damaged JSON and unterminated records; - the receipt preceded final API output drain. Separate stdout/stderr decoders, - pending-tail refusal, joined EOF finalization and post-cleanup final census now - prevent malformed, late or 429 traffic from disappearing. Actual record controls - include split/interleaved clean output, damaged/newline/EOF records and late - success/refusal events. -- Lighthouse treats its navigation timeout as a warning. A real disposable - Chromium/Lighthouse run took 22,116 ms and admitted an incomplete image load. - Report admission now refuses warnings. The shared proof includes that actual - soft-timeout control with an otherwise passing report counterpart. -- Ancestor opacity and zero-area rendering hid product markers while the DOM gate - admitted them. Browser-native visibility plus positive-area rectangles now - apply to markers and individual field labels/values. Each real lesson navigation - plants ancestor-opacity, zero-area and hidden-label mutations, verifies refusal, - restores the document and re-admits the visible control, without new API calls. - -All 74 focused proof/lifecycle cases pass with zero failures/skips. Disposable -managed-Chromium controls verify visible admission and hidden/zero-area refusal. -A complete rerun and fresh independent round 2 remain pending; the earlier local -feasibility result is preserved and does not validate these subsequent changes. - -#### Step 3 review round 2 - -Fresh GPT-6-astra (xhigh) runtime/measurement and GPT-6.1-sol (xhigh) -proof/corpus reviews cover `69ce613..38c15d9`. Both request changes. Three -verified proof gaps remain; the existing 50 proof controls passed independently. - -- A completion record missing its opening brace or carrying a prefix was ignored, - as was an unexpected endpoint completion. The owned API emits structured - startup/output; only empty plaintext separators are now admitted. Damaged and - unexpected completion records refuse the entire census, including a 429. -- Process-group absence preceded child `close` and buffered stream EOF. An actual - child with deliberately deferred stdout demonstrated a 429 arriving after a - prematurely passing final census. Cleanup now joins `close` with a separate - shared five-second stop/output-drain bound before observer finalization. The - regression holds and releases the real pipe, proves cleanup waits, then refuses - the 429. -- Clip/filter/mask and offscreen/overflow styles could hide laid-out markers. - The bounded seeded-page predicate now refuses these ancestor styles and - horizontally unreachable/negative-area markers. Each lesson navigation checks - eight actual DOM mutations, restores and re-admits its positive control; - the receipt requires all 24 completed controls. This is not a general CSS - occlusion or visual-accessibility audit. - -All 78 focused proof/lifecycle cases, typecheck and lint pass. The full guarded -runner passes 1,500 cases (1,440 web + 60 SDK), with zero failures/skips/todos. -Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) fix reviews approve -`38c15d9..39cee01` and the final shared cleanup-deadline adjustment. Independent -controls reproduce the old observer/drain gaps, confirm joined stdout/stderr, -refuse daemon output errors and bound a TERM-resistant child plus held output -to 5,003 ms. Managed Chromium refuses all eight DOM mutants and re-admits each -restored counterpart; the five added cases passed the old predicate. - -The complete `38c15d9` rerun passes: setup 60,270 ms, proof 571,089 ms, -cleanup 10,688 ms, all 27 report pairs and nine screenshots, actual soft-timeout -refusal, nine visibility controls and 134 successful API completions, with zero -429/malformed/pending records. The authorized foreign containers restart healthy. -That receipt precedes round-2 fixes. The complete `39cee01` rerun also passes: -setup 60,374 ms, proof 585,644 ms and cleanup 10,719 ms. Build -`d0bzXjXoImUdH317X83rK`, invocation `825982bee2ed568f43208368f99f332d`, -produces all 27 report pairs, nine screenshots and 24 completed visibility -controls. The actual soft-timeout and both TLS refusal controls pass; final -observation contains 134 successful calls, zero 429/malformed/pending records. -All owned cleanup checks pass and the authorized foreign containers restart. -The subsequent shared-bound change has focused verification above and must also -run in final CI. Both independent review rounds and fresh fix verification are -complete. Step 4 owns CI enforcement and phase exit; neither is claimed here. - -### P02d-7 Step 4 — CI enforcement and phase exit (2026-10-11) - -**Implementation, both independent review rounds and real CI complete.** The -[CI and exit closeout](#p02d-7-ci-and-phase-exit-closeout-2026-10-11) records -successful artifacts and the activated seventh required context. -The always-running `public demo + lighthouse` job replaces the disabled -placeholder. It installs the exact locked browser tools and managed Chromium, -then invokes `make demo DEMO_MODE=ci` over the shared seven-service lifecycle. -The 20-minute job includes setup, the 12-minute serial proof, separate bounded -cleanup and artifact handling. An unconditional bounded workflow receipt records -failure even when setup prevents a product receipt. Uploads allow only public -JSON/HTML reports, screenshots and sanitized workflow/proof receipts. - -The [individual exit evidence matrix](phase-02d-exit-evidence.md) maps all -36 Deliverables, 79 Completion Criteria, 39 exclusions and nine exit obligations. -It preserves prior human/PR evidence and names the verified CI receipts; -implementation alone does not constitute phase exit. - -**Criterion reconciliation.** Published roots cannot receive new translations -under ADR-0050. The third-locale proof therefore creates and publishes new -French-only roots through supported commands, preserving the existing EN/TR -public responses and all five migration histories. Organization branding writers -remain unrouted. The branding criterion now separates API-root command refusal -from mapped-host reads and distinguishes a successful business audit from the -required standalone denied-attempt audit. This corrects the mutable criterion's -no-audit overclaim; ADR-0033/0044 and production auditing are unchanged. - -**Education preservation handoff.** Phase 05 inherits separate Course/Lesson -roots and their contained Pattern A translations. Its migration preserves stable -IDs and published localized URLs, `(sort,id)` lesson order, tenant/organization -scope, translated bodies, exact content-type/taxonomy revision pins and course -access policy. `SeedData.All` supplies both tenant curricula: eight courses, -ten lessons and 27 translations at their declared scopes, including draft and -restricted controls. Carry those persisted fixtures through the migration; -reseeding is not a migration strategy. - -> **Reconciliation — 2026-10-12.** The settings-event ownership below records -> P7's expectation at closeout. Accepted -> [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) -> selects completed provisioning as the first useful event; the -> [Tenancy catalogue](../modules/tenancy/README.md#integration-event-catalogue) -> promises no settings-invalidation event. Settings remain uncached. Any future -> cached consumer needs its scope/key/freshness decision; Phase 11 owns the -> distributed adapters on their existing triggers, without a settings-event promise. -> The dated handoff text is retained. - -**P02b-0 re-verification handoff.** Re-read the four `/api/v1/public` GET/HEAD -pairs and contract; retained `*.learnstack.local` seed hosts over native HTTPS, -manual local hosts/CA setup and private paired hop configuration; coordinated -60/min visitor and 600/min physical-peer accounting; tenant-wide English versus -organization-scoped Yoga seed context; one live bootstrap with two calls per -normal product document and three for a followed missing-content chain; and the -uncached settings reader plus `learnstack.tenancy.settings` eager-invalidation -event owned by Phase 02b. These delivered premises do not Accept future -session/BFF/authenticated-rate-limit decisions. - -**Initial validation at `bf5bc9c`.** Both third-locale/branding cases pass locally -with zero skips. Release build has zero warnings/errors; 1,705 unit, 203 architecture, -four contract and 180 Docker-free integration cases pass, as do all 1,500 guarded -frontend cases. Typecheck, lint, whitespace and 2,042 relative links (666 fragments) -pass. All 871 Docker integration cases pass with zero skips; execution guards pass. -Two fresh review rounds, a real -successful PR job and the authorized seventh-context activation/read-back remain. -No PR, live check activation or phase exit is claimed yet. - -#### Step 4 review round 1 (2026-10-11) - -Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) agents reviewed -`06d46ad..bf5bc9c` for runtime/CI ownership and corpus/exit evidence. Their -confirmed findings concern proof completeness and CI prerequisites, not a -production contract defect. C40–C42 now share one HTTP test: 17 requests pair -foreign-only/shared slugs, exact-locale omissions and organization/tenant host -controls with exact raw translation sets on each request's own enlisted -application connection. The third-locale case now enables French on the foreign -host and proves its positive catalog before checking the same French detail -URLs are hidden. Missing Cache-Control can no longer bypass its assertions. - -The CI job starts an absolute deadline before checkout, bounds setup steps and -interrupts the shared lifecycle by minute 16, reserving four minutes inside the -unchanged 20-minute ceiling for owned cleanup, policy cleanup and artifacts. -Four controls execute the actual workflow shell: first-step reservation, -remaining-budget arguments and two exhausted-budget refusals. An actual GNU -timeout → make → shared Node-owner experiment exits 124 only after child cleanup. -The internal 12-minute serial proof deadline remains unchanged. - -The GitHub-hosted Linux prerequisite loads only an invocation-owned AppArmor -userns profile for the exact managed Chromium when the kernel restriction needs -it, then performs a sandbox-enabled launch smoke. Fifteen isolated controls -exercise ownership, literal paths, failed load/removal and cleanup without -changing workstation policy. A real Linux job remains required; the initial -runner risk was source-supported inference, not a reproduced hosted failure. -The exit matrix, stale review guidance, Phase 02b risk premises and mutable -renderer/writer scope descriptions now match delivered contracts. - -All three focused locale/branding Docker cases pass with zero skips and the -execution guard. The guarded frontend rerun passes 1,504 cases (1,444 web + 60 -SDK), zero failures/skips/todos; typecheck, lint, scoped backend formatting and -whitespace pass. The initial full backend totals above precede the added combined -case. Final complete PR CI, round 2 and protection read-back remain required. - -#### Step 4 review round 2 (2026-10-11) - -Fresh GPT-6-astra (xhigh) and GPT-6.1-sol (xhigh) agents reviewed -`06d46ad..100b022` across runtime/CI ownership, security, correctness, -maintainability, test quality and the complete changed corpus/exit matrix. -Both approve with no remaining Blocker or Major. The corpus reviewer confirmed -two Minor navigation/census remnants: the matrix still called the expanded -three-case class two cases, and CONTRIBUTING still described completed -ADR-0055 reviews as remaining. Both are corrected; the reviewer independently -checked the bounded follow-up. One overlong P7 prose line is wrapped without -changing its content, and catalogue navigation names the new deadline/sandbox -controls. Earlier P1–P6 delivery records remain unchanged. - -The runtime reviewer independently passes all 15 Chromium-prerequisite controls, -four actual-workflow deadline controls and all three focused Docker HTTP cases, -with zero skips, plus whitespace. The corpus reviewer verifies all 36/79/39/9 -inventory counts, complete named evidence, 175 Implemented rules, 21 Active/one -Adopted standards and future-owner scope. Root checks pass seven ADR lifecycle -and 14 OpenAPI-CI controls. The complete PR's 33 unique Markdown files resolve -2,188 relative links and 686 fragments with no errors before these closing -navigation additions. Fenced and inline examples are excluded from link counts. -Both review rounds and verified fixes are complete. Actual successful Linux PR -CI, complete artifact receipts and authorized protection activation/read-back -remain required before a positive phase-exit verdict. - -#### P02d-7 CI and phase-exit closeout (2026-10-11) - -**Verdict: implementation and Phase 02d exit verification complete.** All four -P7 steps completed both fresh independent review rounds; verified findings are -fixed and committed. [PR #28](https://github.com/HodeTech/LearnStack/pull/28) -remains open for maintainer review and merge. No merge is claimed. - -All seven jobs passed in the first real -[PR run](https://github.com/HodeTech/LearnStack/actions/runs/38106505383) for source -head `8605fc94f7ba343d5cd7cc15d28001d99349735b`. GitHub tested synthetic merge -`15109c3a80a41ee7b6d6f9832880c7b2b13877f5`, whose parents are that source and -main `378346126949c90bb286b5217c24513fc2044f06`. The sanitized workflow receipt -records both identities. Downloaded TRX files confirm 1,705 unit, 203 architecture, -four contract, 180 Docker-free integration and 872 Docker integration passes: -2,964 backend tests, zero failures/skips. All three locale/branding/combined-scope -cases are present and Passed. Frontend job output confirms 1,444 web + 60 SDK -passes, zero failures/skips/todos; typecheck, lint, builds and SDK drift pass. -Meta, secret scan and OpenAPI compatibility pass too. - -The `public-demo-lighthouse` artifact contains exactly 27 JSON/HTML report pairs, -nine screenshots and two sanitized receipts; no private logs, profiles, env files -or keys are included. Report digests, nine URL/three-run census, configuration, -invocation, build and synthetic checkout identities match. The invocation is -`aab02c37c71c02569f71ef8829a96c09`; build is `yTmMjFs6JVE2ea_W-jFzX`. -Node 22.23.1, Lighthouse 13.5.0, Playwright 1.64.0 and Chromium revision 1248 / -156.0.8078.4 run on the four-CPU Ubuntu 24 hosted runner. Its sandbox-enabled -launch passes with the exact-executable temporary AppArmor prerequisite; -the owned policy removal passes afterward. - -All nine linked navigations and 24 planted visibility refusals pass. Every audit -has normalized initial JS gzip 106,359–106,553 bytes, CLS 0 and automated -accessibility 1. Per-URL timing medians remain advisory, not production p95. -All 134 API observations are 200, with zero 429, malformed or pending records: -six startup + two observer-control + 18 linked-browser + 3 × 36 audit calls. -Both TLS refusal controls and the actual audit-timeout control pass. Keycloak is -stopped before anonymous navigation. Setup/proof/cleanup take -228,127 / 650,154 / 11,041 ms; the proof stays inside 12 minutes and cleanup -inside 30 seconds. The complete job takes 15 minutes 51 seconds, within its -20-minute ceiling and absolute setup/proof deadline. - -After that successful run, the authorized API update adds only -`public demo + lighthouse` to main's required contexts. A fresh full read-back -confirms seven GitHub Actions contexts (`app_id: 15368`), strict up-to-date -checking, all six prior contexts retained and every unrelated protection setting -identical to the immediately preceding API response. The current list lives in -[CONTRIBUTING](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main). - -The [individual evidence matrix](phase-02d-exit-evidence.md) reconciles all -36 deliverables, 79 criteria, 39 explicit exclusions and E01–E09. All 45 register -rows have dated Accepted closure links; no Phase 02d-owned Registered/Awaiting -catalogue rule remains. All four ADR-0056 rules are Implemented; corpus checks -confirm 175 Implemented catalogue entries and 21 Active/one Adopted standards. -The existing P6 human/VoiceOver evidence retains its original attribution and -limits; this closeout claims no new final-head manual WCAG or zoom audit. -Phase 05 preservation and P02b-0 premises are handed off above and in their -owning documents; no future-phase decision is accepted by this exit. -Closing-document checks pass all five CorpusConsistencyTests with zero skips; -the 33 changed/new Markdown files resolve 2,197 relative links and 694 fragments -with no errors. Added prose respects 88 columns; ADR-0056 changes are insertion-only. - -##### Reviewed implementation head verification (2026-10-11) - -The first run above owns activation history. The separately downloaded -[reviewed-head run](https://github.com/HodeTech/LearnStack/actions/runs/38108622191) -passes all seven jobs for source `d47ef17c8473e17e0950361dc35e419ba6c0825c`, -tested merge `ba44563af66fbd7744b6625673e61286a8e77fa4` with the same main parent. -Its invocation is `170c02e7741fbc6c79895ce718cecd89`; build is -`rlL6ubYmcf7_VQaPBN-fA`. TRX/frontend receipts confirm the same 2,964 backend -and 1,504 frontend passes, zero failures/skips/todos. - -All 27 report pairs, nine screenshots, nine navigations and 24 visibility -refusals pass. Report digests and source/build/invocation/configuration identities -match. Normalized gzip is 106,358–106,551 bytes, CLS 0 and automated -accessibility 1 throughout. Both TLS refusals, the audit-timeout control and all -134 API observations (200 only, no malformed/pending records) pass. -Setup/proof/cleanup take 214,616 / 644,207 / 12,962 ms; all cleanup flags pass. -Sandbox-enabled Chromium and owned AppArmor cleanup pass. These numbers belong -to the exact implementation head reviewed externally, not to later commits. - -##### External review follow-up (2026-10-11) - -The maintainer's review of `3783461..d47ef17` reported no Blocker/Major and -four bounded documentation/maintenance findings. All four are verified and -addressed: the reviewed-head receipt above supplements activation history; -runtime imports move to the file header; installed tool/browser metadata feeds -the shared census and remains checked against independent committed pins; and -ADR-0056 gains dated acceptance-baseline navigation without changing history. -Tool versions, budgets, admission and cleanup behavior are unchanged. - -Local validation passes 1,454 web + 60 SDK tests, zero failures/skips/todos, -typecheck, lint and all 203 architecture tests. Ten added cases cover installed -metadata/pin mismatch, malformed or missing browser metadata, stale census and -wrong-version report refusal, each retaining a clean passing control. Both fresh -independent remediation rounds reviewed `d47ef17..dca3a7b` and approved without -findings. Each independently checked installed dependency resolution, fail-closed -metadata/census comparison and the downloaded historical receipts. All five -corpus tests pass; the complete PR's 33 changed/new Markdown files resolve -2,201 relative links and 698 fragments without errors. The new remediation head -must still pass full seven-job CI through the PR rollup before merge. - -##### Systematic review remediation (2026-10-11) - -The later review examined source `aebefee`. Its findings were re-verified against -current code before changes; this is a separate record from the historical -`d47ef17` review above. No new architecture decision or budget change is needed. -Work remains on `development`; PR #28 is not merged by this record. - -1. **Lifecycle and launcher — complete.** `cd6affd` removes the unsupported - Seeder launcher argument, attempts independent process/observer/Compose - cleanup stages even when a preceding stage fails, and retains failure causes - internally without echoing private diagnostics. Private files are removed - only after confirmed cleanup. Socket errors distinguish occupied ports from - other bind failures; declaration files describe the actual lifecycle API. - `/artifacts/` is ignored. All 34 lifecycle tests, lint and typecheck pass. - Two first-round reviewers and a fresh second-round reviewer approved without - findings. -2. **Genericity census — complete.** `db6bcdf`, `90114f0` and `c6cd69f` close - source-root/format admission and supported static import gaps. Local and - inherited-config candidate ambiguities are conservatively included or - refused; workspace manifests have explicit ownership. Backend evaluation - checks `Compile` and `ProjectReference` coverage, exact output roots and - bounded build shapes/properties. First-round frontend/backend reviewers - identified five verified resolution/build-admission gaps, fixed in - `90114f0`. The fresh second round found inherited-config shadowing, fixed in - `c6cd69f`; its same counterexample now refuses and its clean control passes. - All 18 frontend genericity cases, seven backend genericity cases, all 203 - architecture cases, lint, typecheck and targeted format pass. This remains a - bounded exact-literal/static-import fence, not arbitrary program analysis. -3. **Proof helpers and carriers — complete.** `9a0d285` extracts actual worker - network-inventory reconciliation and verifier advisory aggregation for fast - dirty/clean controls. Navigation counts come from completed - observations; upload globs admit only named reports/screenshots/receipts. - Current architecture, infrastructure, standards and route-authoring guidance - describe delivered G44/G45 enforcement. Two first-round reviewers and a fresh - second-round reviewer approved without findings. The second round also - reproduced all historical advisory medians from the downloaded receipt. - All 128 focused tests, 1,537 frontend cases (1,477 web + 60 SDK) and 2,092 - Docker-free backend cases (1,705 unit + 203 architecture + four contract + - 180 integration) pass with zero failures/skips/todos. Release build, format, - lint, typecheck and production frontend builds pass; 15 sandbox-policy and - seven ADR-status controls pass. The complete PR's 36 Markdown files resolve - 2,289 relative links and 719 fragments; added prose respects 88 columns. - The final PR rollup must still pass all seven required jobs, including the - real Docker and 27-audit lifecycle proof, before merge. - -**Late automatic-review follow-up.** Run 38125035732 passes all seven jobs for -source `4541d63`, including 2,964 backend and 1,537 frontend cases, the real -27-audit proof and cleanup. A later CodeRabbit comment exposed a local-DX gap: -ignored `.env.local` and OS/editor files reached raw filesystem classification. -The follow-up admits only explicitly known machine filenames that Git also -ignores. Ignored source files, unknown formats and compiler coverage retain -fail-closed behavior. The first independent round approved `d16d2d7`. The fresh -second round reproduced an automatically imported `.csproj.user` build hook; -`.user` is therefore excluded from the machine-file exemption in `9343e99`, -with explicit refusal controls. The reviewer independently re-ran the actual -collector: clean ignored files pass and the original build-hook counterexample -refuses. Both review rounds are complete, with no remaining findings. All 19 -frontend and seven backend genericity cases pass; the complete guarded frontend -rerun passes 1,538 cases (1,478 web + 60 SDK), zero failures/skips/todos. -Owned temporary ignored-file controls pass both actual raw collectors and are -removed afterward. Whitespace and the complete PR's link/fragment audit pass. -The final PR rollup below owns replacement final-head CI; all seven jobs remain -required before merge. - -**CI stability follow-up.** Run 38126790757 reports one unit-test failure in -`A_Factory_That_Ignores_Its_Token_Is_Still_Bounded`; all 203 architecture cases, -including the new admission controls, pass. This pre-existing test races an -80 ms cache deadline against a 600 ms factory delay. It now holds the factory -behind an explicit release signal until the cache's own timeout is observed, -checks that a replacement waits and retains the late-result/cache assertions. -The bounded test wait cannot masquerade as the cache timeout: its message must -identify the cache's own deadline. The release is guaranteed in `finally`. -Production cache behavior and its budget are unchanged. `32a7951` delivers -this test-only fix. Fresh GPT-6.1-sol (high) and GPT-6-astra (high) reviews approve -in two separate rounds with no findings; the second reviewer independently -passes the focused Release case. All 51 cache cases and all 1,705 unit cases -pass with zero skips. Replacement final-head CI remains required by the rollup -below; the initial failed job is not counted as passing evidence. - -**Other finding dispositions.** The gzip adapter equality checks wiring; the -independent Script observer checks source-window coverage, not a second byte -measurement. Existing fast tests already cover report admission, source-byte -normalization, completion accounting and gatherer cleanup; full orchestration, -TLS refusal, real visibility and report-file checks remain real lifecycle/CI -proofs. The added helpers supplement those proofs rather than replacing them. -The review's zero-fast-coverage claim was therefore broader than the actual gap. - -The reported PR-body count/gzip mismatch compared different receipts. Downloaded -[run 38119659152](https://github.com/HodeTech/LearnStack/actions/runs/38119659152) -for source `aebefee`, tested merge `0bb897c`, verifies 2,964 backend and 1,514 -frontend passes, gzip 106,358–106,552 bytes. Historical `d47ef17` numbers above -remain correct for that earlier head; neither substitutes for final remediation -CI. The newer proof took 619,309 ms inside the accepted 720,000 ms deadline; -cleanup took 10,595 ms inside 30,000 ms. No deadline increase is justified. - -Ordinal complete-value matching and strict readable JSON are accepted G20 -behavior, so host case-folding and JSON-comment tolerance are not introduced. -Below-fold laid-out content remains valid full-page evidence; adding a viewport -bottom cutoff would reject legitimate long lessons. Bounded child ownership -records are retained through process-group/EOF confirmation; no sustained leak -was demonstrated. The older `public-local` exit behavior, dormant platform -branches and test-project placement are unchanged maintenance suggestions. -Census regeneration instructions already name the authoritative Seeder command. - -Mutable Action tags are pre-existing throughout CI, with no accepted SHA-pinning -policy. This patch does not introduce a repository-wide dependency policy; -[Security Standards](../standards/11-security.md#dependency-hygiene) already assign -update automation to Phase 11. Accepted ADR-0053/0056 baseline and dated notes -remain historical; their then-pending wording is not rewritten as a correction. -Current carriers link delivered P7 evidence instead. No new human/WCAG evidence -is claimed by these orchestration and proof changes. - -Closing documentation commits must also pass the seven required jobs before -merge; the [PR check rollup](https://github.com/HodeTech/LearnStack/pull/28/checks) -owns that moving-head result. Next after maintainer review and merge is -**P02b-0 re-verification and decision pass**, before Phase 02b implementation. - -### P02d-7 merge and closeout (2026-10-11) - -The maintainer merged [PR #28](https://github.com/HodeTech/LearnStack/pull/28) at -2026-10-11 09:38:58 UTC. GitHub records final PR source -`8d9d2195cfadf1d83807613ea22d792b7ce329f4` and squash merge -`d37f46ccf0ebbf909f02c81a59d9019af3e9a1ca`, whose parent is the previous main -`378346126949c90bb286b5217c24513fc2044f06`. Source and squash merge have the -identical tree `7f83bee243fe17626ef10af051e54a9218fd7aaa`. Development incorporates -the main merge without switching branches or rewriting published history. - -All seven required checks pass in the -[final PR run](https://github.com/HodeTech/LearnStack/actions/runs/38127402847) -for that source. The tested synthetic merge is -`2d8ff6b23cd1b27691ea0038859944ca6c0ce395`, with the final source and previous -main as parents. Independently verified downloaded receipts confirm: + and `plain` taxonomy, owned per tenant, and every Customization command bumps the + tenant's generation + ([Packet 8](phase-02a-kernel-tenancy.md#delivery-record-packet-8)). + `Customization.Application.Contracts` exposes no read; the module spec's § Primary + read flow says "Not implemented". **G12**, **G22**. +- **The seed.** [Packet 7](phase-02a-kernel-tenancy.md#delivery-record-packet-7) seeds + two tenants through the request path, maps the English school's host tenant-wide and + the yoga studio's host to its default organization, and writes both host rows on names + under `*.learnstack.local` that a browser reaches only after a hosts-file edit. Every + seeder step after provisioning announces the tenant's default organization. **G7**, + **G14**, **G32**. +- **The frontend scaffolds.** `frontend/apps/web/src/middleware.ts` answers `503` + whenever `NODE_ENV` is `production` (so under `next start`), writes the raw host into + `x-tenant-id`, copies every inbound header, matches `/api/healthz` too, and carries + TODOs that assign the work to Phase 02a. + `frontend/packages/sdk/src/{server,client}.ts` take a `tenantId` option and return + `{}`, which stops compiling once the generated `paths` is non-empty, and the package + root re-exports the server entry. `frontend/apps/web/.env.local.example` points the + API origin at APISIX, which only `make dev-gated` starts. The root layout fixes + `lang="en"` and a platform `<title>`. The Vitest harness, Packet 3b's placeholder page + test and Packet 10's `src/test/lint-rules.test.ts` exist; + `lib/customization/composites.ts` registers four composite keys and no component. + **G31**, **G35**, **G36**, **G38**, **G43**. +- **CI and the development loop.** The `openapi diff` and `lighthouse budget` jobs are + placeholders behind unset `vars.ENABLE_*` variables and report as skipped; activation + takes the edits + [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) + lists. The SDK pipeline is wired with empty output, and + [Frontend Architecture Standards § SDK](../standards/07-frontend-architecture.md#sdk) + gives its drift gate to this phase. The contract suite asserts only a `200` + ([Testing Standards § API Contract Tests](../standards/06-testing.md#api-contract-tests)). + The `backend integration (Testcontainers)` job runs on every pull request and is + required as of P02d-1. The inherited required-check gaps, including the renamed `meta` + check, are [repaired and verified in Step 3](phase-02d-delivery-log.md#step-3--packet-completion-2026-09-14). + `make dev` starts containers only, `dotnet run` reads no `.env`, and + `make seed` waits on every default-profile service and both Keycloak realms + ([Infrastructure Standards § Healthchecks and the readiness gate](../standards/12-infrastructure.md#healthchecks-and-the-readiness-gate)). + No job starts the API or `next start` as a process a browser can reach. **G31**, + **G44**, **G45**. +- **Standards that meet their first subject here.** A new module owes its spec and + audit-coverage matrix + ([Documentation Standards § Per-Module Specifications](../standards/13-documentation.md#per-module-specifications), + [Audit Coverage Standards](../standards/18-audit-coverage.md)). + [Accessibility Standards](../standards/16-accessibility.md) binds the first public + surfaces, and the [standards index](../standards/README.md#honest-status-today) row + for Localization Standards places the i18n runtime in Phase 04. **G39**, **G43**. +- **What Phase 02b expects of this phase.** The development-transport part of its gate + **G12** + ([Phase 02b § The decision register](phase-02b-events-auth.md#the-decision-register)), + now **G32**; the shared-peer premise of its **G14**, now **G34**; and its criterion + that both sites still render anonymously with Keycloak stopped. -- **2,964 backend passes**, zero failures/skips: 1,705 unit, 203 architecture, - four contract, 180 Docker-free integration and 872 Docker integration cases. -- **1,538 guarded frontend passes**: 1,478 web and 60 SDK, zero - failures/skips/todos; lint, typecheck, builds and SDK drift also pass. -- Exactly 27 Lighthouse JSON/HTML report pairs, nine screenshots and two - sanitized receipts. Report digests, source/checkout/build/invocation identities - and the nine-URL/three-run census match. Normalized initial JS gzip is - 106,358–106,552 bytes, CLS 0 and automated accessibility 1 throughout. - Per-URL timing medians remain advisory. -- Nine linked navigations, 24 planted visibility refusals, both TLS refusals and - the actual audit-timeout control pass. All 134 API observations are 200, - with zero 429, malformed or pending records. Setup/proof/cleanup take - 170,462 / 618,055 / 10,695 ms; all owned-cleanup flags pass. -- A fresh protection read-back retains `strict: true` and all seven GitHub - Actions contexts, including `public demo + lighthouse`. This closeout changes - no protection setting. +P02d-1 implements Education's roots, translations, migration and isolation. +P02d-2 implements its six commands and seeded data. P02d-3 supplies internal reads; +P02d-4 supplies public endpoints and contract/SDK controls. P02d-5 supplies native +HTTPS ingress, coordinated anonymous admission, the configured trusted server +caller and live-host/locale entry. Public product pages, text-card components, +theme injection and accessibility remain P02d-6; the browser/demo/Lighthouse +harness and phase exit remain P02d-7. -The [post-merge main run](https://github.com/HodeTech/LearnStack/actions/runs/38129121225) -tests the squash commit separately; its result is not inferred from source CI. -At this documentation check, five jobs pass; Docker integration and the -demo/Lighthouse job are still running. +### Explicitly not in this phase -**P02d-7 and Phase 02d are closed.** All seven implementation packets are merged; -all four P7 steps and verified fixes retain their recorded independent reviews. -The [individual exit evidence](phase-02d-exit-evidence.md) reconciles all -36 deliverables, 79 completion criteria, 39 exclusions and nine exit obligations. -Earlier dated delivery/review records, Accepted ADRs and their acceptance-time -or pre-merge wording remain historical and unchanged. No new human/VoiceOver, -full WCAG, zoom, production-p95 or deployment-readiness claim is added. +Named so that no reader has to guess, and so no later phase can assume it was done here: -**Next: P02b-0 — phase-entry re-verification.** The -[Phase 02b packet table](phase-02b-events-auth.md#packets-and-decision-gates) -requires re-reading code, corpus and Hub premises against HEAD, including the -[P7 handoff](#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11). -P02b-0 has not started; each later packet closes its own gates in its decision -pass. No Phase 02b implementation or auth/BFF decision is accepted here. +| Capability | Owning phase | +|---|---| +| Authentication, sessions, login | [Phase 02b](phase-02b-events-auth.md) | +| Token-keyed authenticated and write rate-limit budgets, and what the pre-authentication limiter does once a caller is validated | [Phase 02b](phase-02b-events-auth.md) (G14) | +| Keycloak realm reconciliation (a seed step that writes to Keycloak) | [Phase 02b](phase-02b-events-auth.md) (G12) | +| Future settings caching and any required invalidation | A future cached consumer's scope/key/freshness decision; [Phase 11](phase-11-production-hardening.md#demand-gated-building-blocks) owns triggered distributed adapters. The [Tenancy catalogue](../modules/tenancy/README.md#integration-event-catalogue) declares no settings-invalidation event | +| Isolation tests through authenticated or id-addressed routes | [Phase 02b](phase-02b-events-auth.md) | +| Identity domain, roles, permissions, invitations; permission keys for public reads; the rule that every endpoint carries `[Authorize]` or `[AllowAnonymous]` | [Phase 03](phase-03-identity-admin.md) | +| A tenant-scope read across all organizations on a tenant host (the `app.scope` carrier) | [Phase 03](phase-03-identity-admin.md) | +| CMS editing, page builder, media library and tenant media origins | [Phase 04](phase-04-cms-media-pages.md) | +| Per-locale publish readiness workflow, `tenant_route_slugs` registry | [Phase 04](phase-04-cms-media-pages.md) | +| Studio authoring of translated field values (titles, bodies, slugs) and the view of untranslated gaps — where it lives is an open question | [Phase 04](phase-04-cms-media-pages.md#admin-studio-cms-screens); its screen row goes in [Phase 06 § Admin Studio — screen ownership](phase-06-renderer-admin-studio.md#admin-studio--screen-ownership) | +| `Accept-Language` negotiation for API-returned messages; the per-tenant locale fallback chain; the `/{locale}/{slug}` page routing shape | [Phase 04](phase-04-cms-media-pages.md) | +| Authoring and translating a content type's field order and labels; the closed set of built-in primitive field types (number, boolean, date/time, select) | [Phase 04](phase-04-cms-media-pages.md) | +| The schema-version migration path for stored instances; deleting a content-type revision after a zero-instance count | [Phase 04](phase-04-cms-media-pages.md) | +| Customization deprecate and revise commands, and per-band taxonomy editing | [Phase 04](phase-04-cms-media-pages.md) and [Phase 05](phase-05-education-learning-content.md), consolidated in [Phase 06](phase-06-renderer-admin-studio.md) | +| Tenant-authored page composition (`TenantPageBlock` rows and their cache family) | [Phase 04](phase-04-cms-media-pages.md); the block resolver is [Phase 06](phase-06-renderer-admin-studio.md)'s | +| Deciding whether a customization change owes an integration event | [Phase 04](phase-04-cms-media-pages.md), per [the Customization spec § Integration-event catalogue](../modules/customization/README.md#integration-event-catalogue) | +| The `Redirect` model the CMS auto-creates when a published slug changes | [Phase 04](phase-04-cms-media-pages.md) | +| Search — the `ITenantSearch` port and its PostgreSQL default | [Phase 04](phase-04-cms-media-pages.md) | +| Search — the Meilisearch adapter behind that port | [Phase 09](phase-09-billing-integrations-analytics.md) | +| Course versioning, programs, lesson items, completion rules; richer publish-readiness validation and versioned publication; catalog visibility separate from publication | [Phase 05](phase-05-education-learning-content.md) | +| The migration that brings this phase's courses and lessons under course versions and modules | [Phase 05](phase-05-education-learning-content.md) | +| The authenticated course and lesson authoring surface, with the commands that edit a course or lesson or reorder lessons after the seed | [Phase 05](phase-05-education-learning-content.md) | +| The `Level` aggregate and the catalog API's levels resource; the `TenantLevelTaxonomy` editor | [Phase 05](phase-05-education-learning-content.md) | +| The `TenantLessonItemType` read, the batched reference walk and the measured customization cost model; the `embed-html` sanitisation contract | [Phase 05](phase-05-education-learning-content.md) | +| Admin Studio, navigation menus, SEO metadata beyond what G40 settles for translated public pages, full block registry | [Phase 06](phase-06-renderer-admin-studio.md) | +| The full `UnknownVersionBlock` / `UnknownBlock` placeholders and per-block error boundary; tenant-authored error pages; redirect handling | [Phase 06](phase-06-renderer-admin-studio.md) | +| Branding configuration surface — tenant-admin editor, theme preview, logo, header and footer settings; the per-organization branding override (`OrganizationBranding`) and the token merge | [Phase 06](phase-06-renderer-admin-studio.md) | +| Preview of draft courses and lessons through the production renderer | [Phase 06](phase-06-renderer-admin-studio.md) | +| Browser end-to-end flows (Playwright) and axe checks through Playwright | [Phase 06](phase-06-renderer-admin-studio.md), per [Testing Standards § End-to-End Tests](../standards/06-testing.md#end-to-end-tests); any narrow smoke this phase adopts is G38 | +| Enrollment, learner portal, progress tracking; [Course Access](../glossary.md) — whether content published anonymously here stays on the public path once enrollment exists | [Phase 07](phase-07-enrollment-learner-portal.md) | +| Live classroom | [Phase 08c](phase-08c-classroom.md) | +| Billing | [Phase 09](phase-09-billing-integrations-analytics.md) | +| Hub, entitlement gating | [Phase 02c](phase-02c-hub-foundation.md) | +| APISIX as the edge gateway for a non-development deployment; gateway or CDN caching; edge rate limiting | [Phase 11](phase-11-production-hardening.md#security), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | +| Plan-differentiated API rate limits (`LimitKeys.ApiRatePerMinute`) | [Phase 11](phase-11-production-hardening.md#security) for the key's gate; [Phase 02c](phase-02c-hub-foundation.md) for its enforcement path | +| The L2 cache tier behind `ICacheService` (default `InMemoryCacheService`) | [Phase 11](phase-11-production-hardening.md), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | +| Content-Security-Policy and the other secure headers | [Phase 11 § Security](phase-11-production-hardening.md#security), per the [standards index](../standards/README.md#honest-status-today) row for Security Standards | +| `GET /readyz`; the production Dockerfile and image pipeline; the performance baseline and load tests against [Performance Standards](../standards/15-performance.md) | [Phase 11](phase-11-production-hardening.md) | +| Custom-domain TLS automation | [Phase 11](phase-11-production-hardening.md), on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s trigger | -Phase 05 retains versioned-curriculum migration and preservation of existing -Education/seed records; Phase 06 retains full renderer/Studio and Playwright -Test/axe; Phase 07 retains enrollment, learner portal, progress and access grants. -Phase 11 retains production hardening, telemetry and demand-gated adapters. -Course Marketplace ADR-0049 and Phase 09a remain Proposed; commerce, commissions, -payouts and cross-installation federation are not delivered. +Decisions made or referenced in this phase: -**Documentation-only closeout validation.** All 203 local Release architecture -cases and seven ADR lifecycle/workflow controls pass, with zero failures/skips. -The seven changed Markdown files resolve 1,088 relative links and 478 fragments -with zero errors; added prose wrapping and whitespace checks pass. Prior dated -phase delivery records and all Accepted ADR files are byte-preserved. Full runtime -suites are not rerun locally for this documentation-only change; the final PR -receipts above supply their evidence. +- [ADR-0003 Tenant Isolation Defense in Depth](../decisions/0003-tenant-isolation-defense-in-depth.md) + (Amendment 3's template, Amendment 5's organization write guards and the accepted + Amendment 6 INSERT and parent-mirror correction every Education table takes) +- [ADR-0048 Publication Before Course Versioning](../decisions/0048-walking-skeleton-publication.md) + (independent course and lesson state, combined anonymous-read eligibility, and + Phase 05 preservation obligations) +- [ADR-0008 Localization Schema](../decisions/0008-localization-schema.md) (satellite + translation tables; slugs on the translation row, unique within `(tenant_id, locale)`) +- [ADR-0010 Cross-Module Communication](../decisions/0010-cross-module-communication.md) + (Education reads Customization and Tenancy only through their application contracts) +- [ADR-0013 Page Block Schema Versioning](../decisions/0013-page-block-schema-versioning.md) + (the pin rule + [Tenant Customization Model § 4](../architecture/32-tenant-customization-model.md) + extends to content types, and the placeholder for an unknown version) +- [ADR-0017 Tenant / Organization Hierarchy](../decisions/0017-tenant-organization-hierarchy.md) + (organization scope; `OrganizationBranding` as Phase 06's override) +- [ADR-0018 Tenant-Driven Customization Model](../decisions/0018-tenant-driven-customization-model.md) + (genericity, the renderer architecture, and its 2026-09-04 key and locale amendment) +- [ADR-0023 Strongly-Typed Id Source Generator](../decisions/0023-strongly-typed-id-source-generator.md) + (the new aggregates' identifiers) +- [ADR-0024 API Versioning Policy](../decisions/0024-api-versioning-policy.md) (what the + breaking-change check freezes) +- [ADR-0032 Exception Handling, Logging, and Observability Architecture](../decisions/0032-exception-handling-logging-and-observability.md) + (the pipeline, `Result<T>`, Problem Details, the controller shape) +- [ADR-0033 Audit Durability Model](../decisions/0033-audit-durability-model.md) and + [ADR-0044 Audit Write Path](../decisions/0044-audit-write-path.md) (classification of + the anonymous reads and of the MUST-class writes) +- [ADR-0034 Hub Contract Surface Invariant](../decisions/0034-hub-contract-surface-invariant.md) + (host resolution never calls the Hub) +- [ADR-0035 Demand-Gated Infrastructure](../decisions/0035-demand-gated-infrastructure.md) + (this scope fires no trigger) +- [ADR-0036 Tenant Resolution and Trusted Inputs](../decisions/0036-tenant-resolution-trusted-inputs.md) + (host resolution, the trusted hop and the pre-classification limiter; G33 and G34 may + owe it an amendment) +- [ADR-0039 The Optimistic Concurrency Token](../decisions/0039-optimistic-concurrency-token.md) + (`row_version` and the one ETag derivation) +- [ADR-0040 Ambient Unit of Work](../decisions/0040-ambient-unit-of-work.md) (the closed + setter set G15, G22 and G23 test against, and the read-only mode G28 may add) +- [ADR-0041 Correcting False Statements in Accepted ADRs](../decisions/0041-correcting-false-statements-in-accepted-adrs.md) + (how an erratum a decision pass finds is written) +- [ADR-0042 Tenant Provisioning Cross-Aggregate Transaction](../decisions/0042-tenant-provisioning-cross-aggregate-transaction.md) + (each locale and setting row by its own command; one aggregate root per command) +- [ADR-0043 Customization Payload Validation](../decisions/0043-customization-payload-validation.md) + (lesson-body validation on the command path; no compiled-validator cache) +- [ADR-0045 Entitlement and Feature-Flag Socket](../decisions/0045-entitlement-and-feature-flag-socket.md) + (`tenancy.white_label_branding`, whose meaning G16 asks) +- **Accepted [ADR-0027](../decisions/0027-frontend-i18n.md)** — the frontend i18n + library and catalogue contract; P02d-6 first consumer, accepted with G39 on + 2026-10-09. Phase 04 consumes the foundation; implementation is separate. -### P02d-1 decision pass (2026-09-14) +## Scope -**Accepted — 2026-09-14, verified against `6c58343`.** The maintainer approved -this decision package before implementation. The -[Education spec](../modules/education/README.md) owns the accepted schema detail and -matrices, with its pinned module-list registration. No production implementation is -claimed by this decision pass. The kickoff remains the historical entry record; -[P02d-1's delivery record](#delivery-record-p02d-1) records this pass separately. +### Packets and decision gates -#### P02d-1 accepted answers +Phase 02a needed twelve packets for a narrower scope. This phase declares eight, in +dependency order. `P02d-0` writes no code. Every packet after it opens with the decision +pass [Roadmap § Decision Timing](README.md#decision-timing) describes: its gates are +Accepted, and its catalogue rows registered, before its first line of code. -| Gate or part | Accepted answer | Decision/detail owner | +| Packet | Contents | Cannot start until | |---|---|---| -| G1 | Roadmap-wide closure notation: preserve the original question, record `Accepted — YYYY-MM-DD` with an anchor to the answer and its accepted vehicle; identify the exact closed part of a split gate. Packet status and delivery record list the closed parts. A proposed document closes nothing | [Decision Timing](README.md#decision-timing) | -| G2 | Separate `Course` and `Lesson` roots; natural-key translation entities contained by their own root; Lesson → Course `RESTRICT`, translations → root `CASCADE`; no independent satellite soft deletion. Stable ids and URLs survive Phase 05's migration | [Education data model](../modules/education/README.md#data-model-and-invariants) | -| G3 — values and publication contract | Both roots have `draft` / `published`; publication permits anonymous reading, with both states required for a lesson. No version snapshot or cascade publication. The transition contract is decided with the column; command names and seed acts stay with P02d-2 | [ADR-0048](../decisions/0048-walking-skeleton-publication.md); P02d-2 still closes the remaining G3 details | -| G4 | One exact content-type revision pin on `lessons`; JSON object body per locale on `lesson_translations`; repeated non-translatable values remain per locale. No schema-profile keyword or cross-chain FK | [Education data model](../modules/education/README.md#data-model-and-invariants); Standards 08 removes the unimplemented `isLocalized` claim | -| G5 — column | Optional all-or-none, revision-pinned taxonomy/band triple on `courses`. A successor cannot relabel or remove the course's stored band by rebinding it | [Education data model](../modules/education/README.md#data-model-and-invariants); Phase 05 carries an explicit pin-preservation obligation | -| G6 (a) | The shipped `LocaleTag` spelling in `varchar(35)`, including script Title case and region uppercase | [Education locale identity](../modules/education/README.md#localization-and-url-identity); Standards 08 and Standards 05 satellite sketch | -| G7 — database control | Exact organization write scope, including INSERT; an invoker INSERT/UPDATE trigger checks each parent mirror in addition to factory derivation and tenant-composite FKs. No audit exception to the stricter INSERT rule | [ADR-0003 Amendment 6](../decisions/0003-tenant-isolation-defense-in-depth.md#amendment-6--insert-scope-and-parent-mirrors-2026-09-14); writer contract details remain in P02d-2 | -| G8 | Structural proofs for tenant-composite foreign keys, organization immutability, parent-scope mirroring and Pattern A storage, each with a planted offender; shared immutability errors must not read `OLD.id` | Register rows in Standards 21 before implementation; Standards 05 owns the SQL and chain dependency | -| G9; G26 — slug grammar | Content slugs: 1–160 lowercase ASCII characters with single interior hyphens; refuse UUID `N` and `D` shapes, and do not normalize invalid input silently. No Tenancy or Customization FK. Role grants are enumerated below | [Education URL identity](../modules/education/README.md#localization-and-url-identity); Standards 08 and Standards 05. G26 route templates remain open | -| G10 — order | Catalog `(created_at ASC, id ASC)`, oldest-created first; lessons `(sort ASC, id ASC)` with nonnegative sort and permitted ties | [Education data model](../modules/education/README.md#data-model-and-invariants); the cursor codec remains P02d-4's decision | - -**Database privileges for P02d-1.** On both roots, `learnstack_app` gets -`SELECT, INSERT, UPDATE`; updates are needed for publication, root concurrency and -later translation writes. On both satellites it gets `SELECT, INSERT`; P02d-2's -writers add a locale once, and no replacement or editing command is introduced here. -`learnstack_platform` gets `SELECT` on all four tables. `learnstack_outbox_admin` and -`PUBLIC` get none. Migration ownership is unchanged. A later command needing more -privileges brings its own migration; grants do not anticipate that command. To prove -an UPDATE/DELETE policy independently of a missing privilege, a separate disposable -test database commits the owner's test-only grant, then asserts through a separately -authenticated `learnstack_app` connection. The database is discarded afterward. The -real grant matrix is tested against an untouched migrated fixture. - -**Organization-immutability scope.** G8's shorthand "every table carrying -`organization_id`" needs a table-class qualification. The guard covers tables -classified organization-scoped by Standards 05. `platform_host_to_tenant` is a -platform-scoped host projection, and `outbox_messages` is tenant-wide with organization -metadata; neither becomes organization-scoped because it has that column. -`audit_log`'s append-only guard counts only if its behavior demonstrably refuses an -organization change. The catalogue must enumerate these distinctions and prove its -exemptions cannot hide a newly unguarded organization-scoped table. - -#### Review findings and implementation obligations - -The four accepted catalogue identifiers are -`Every_TenantOwned_Foreign_Key_Includes_TenantId`, -`Every_OrgScoped_Table_Has_An_Organization_Immutability_Guard`, -`Every_Organization_Mirroring_Child_Has_A_Parent_Scope_Guard` and -`Pattern_A_Content_Uses_Translation_Satellites`. They are Registered in Standards -21 by this decision pass and become Implemented with their proofs. The last rule -rejects ad-hoc per-locale columns as well as a misplaced translatable parent column. - -Two independent pre-development reviews checked the model/localization and database -isolation surfaces. The following are confirmed against this pass's baseline: - -- The `WITH CHECK` on `tenant_settings` and `audit_log` admits a null organization - from an organization-scoped session. ADR-0003 Amendment 5 tightened UPDATE and DELETE - only; the adjacent erratum and Amendment 6 correct its broader statement. Both - existing tables need forward migrations; old migrations remain untouched. -- `fn_organization_id_immutable` refers to `OLD.id`, which neither satellite - has. The shared function needs a Tenancy-chain replacement and a no-id regression - case. Education must migrate after that dependency, including in rollback tests. -- A generated normalized scope key with a three-column FK worked in PostgreSQL but - failed the natural EF graph mapping on the repository's pinned packages. The pass - therefore chooses the invoker INSERT/UPDATE parent check, tested independently - under the application role, rather than prescribing an unproven EF workaround. -- An unlocked parent lookup admitted a delete/reinsert race under test-only DELETE - privileges: a parent could be replaced under the same id with another organization - before the child FK ran. `FOR KEY SHARE` prevented the replacement; the child and - parent retained matching scopes. Amendment 6 requires that lock. -- A BEFORE parent check can refuse a malformed child before RLS or the FK does. The - Education suite needs a separate disposable fixture with only that parent guard - removed by committed owner setup, followed by assertions through an authenticated - `learnstack_app` connection, to prove each lower layer independently. The normal - fixture proves all controls together; no production bypass is introduced. -- The level revision pin must be preserved by Phase 05's future `Level` projection; - its current active-only wording cannot silently reinterpret a stored course. -- Plain satellites retain slug reservations after parent soft deletion. The spec - states this explicitly; applying a soft-delete filter to a nonexistent column is - not a valid uniqueness strategy. -- Standards 08 now records canonical locale casing and removes the unimplemented - `isLocalized` marker. Schema `$ref` recursion and content-entry reference depth are different - mechanisms: ADR-0043 refuses all schema cycles. The Phase 05 wording is corrected. -- The extension overview's stale phase table and runtime claims, and Phase 04's stale - customization uniqueness premise, are corrected against the canonical owners. -- The decision-pass inspection found that live GitHub branch protection required - `meta (commit hygiene + link audit)` while CI reported - `meta (compose + commit hygiene + link audit)`, and did not require - `backend integration (Testcontainers)`. The approved exact repair preserves the - other checks and maintainer-approved settings; [Step 3](#step-3--packet-completion-2026-09-14) - records its application and verification. +| **P02d-0** | Phase entry: this plan — the inherited baseline, the packet table, the decision register, criteria that name their evidence, and the corrections to the documents that contradicted the phase. It answers no gate. The required-check edits identified at kickoff belong to `P02d-1`; its [delivery record](phase-02d-delivery-log.md#step-3--packet-completion-2026-09-14) records their repair | Phase 02a exits (met) | +| **P02d-1** | Education schema and database-level isolation: the Education migration chain (`courses`, `lessons`, both translation satellites) with its policies, grants, foreign-key indexes and immutability triggers; the insert-time organization control; aggregates and EF configuration; the structural guards; the schema-level Education isolation suite as `learnstack_app`; the Education module spec skeleton and its pinned-list entry | G1, G2, G3 (values), G4, G5 (column), G6 (a), G7, G8, G9, G10 (order), G26 (slug grammar) Accepted | +| **P02d-2** | Writers and seed: the Education write commands and the Tenancy locale and setting commands, with their catalogue sources, matrices and composition-root registration; the Customization contract the lesson writer calls; the seeder's acts, contexts, ordering and re-run behaviour; each tenant's own content type, taxonomy, locales, branding, courses and lessons; `SeederTests` and the Packet 7 suite recomputed | G3 (commands and seeded states), G5 (validation), G7 (child derivation), G11, G12 (contract), G13, G14, G15, G16 (a–e), G17, G18, G19, G20 (literal source), G21 (subresources), G23 (bound) Accepted; P02d-1 | +| **P02d-3** | Read internals, no HTTP: the generation-keyed customization projection and its cache families; the typed settings accessor | G12 (cache key), G22, G23 (accessor), G24 Accepted; P02d-2 | +| **P02d-4** | Public read API and contract checks: the `[PublicSurface]` reads, their table rows and classification; response contracts, read eligibility, the cursor and the locale matrix; the cache directive; the committed OpenAPI snapshot with the breaking-change check, the regenerated SDK types and the drift gate, activated and required; the request-level Education isolation suite with positive controls | G5 (unresolved band), G6 (b), G10 (codec), G12 (response), G16 (f, g), G24 (response), G25, G26, G27, G28, G29, G30, G31 Accepted; P02d-3 | +| **P02d-5** | Server-rendering path: the development hostnames and transport; the development trusted-hop configuration; the server SDK transport; the middleware replacement and entry behaviour; the anonymous limiter over the hop; the rendering mode; the hop runtime evidence; the frontend skip refusal and the hop predicates' tests | G6 (c), G20 (exemptions), G21 (cookies), G30 (headers), G32, G33, G34, G35, G36, G37, G38 (a, d), G44 (whether) Accepted; P02d-4 | +| **P02d-6** | Public renderer: the `(public)` route tree, pages and page states; the UI message layer; lesson field rendering and its fallbacks; theming injection; the accessibility minimum; the renderer's tests | G5 (unresolved band), G12 (page state), G16 (g), G20 (subjects), G38 (b, c), G39, G40, G41, G42, G43 Accepted; P02d-5 | +| **P02d-7** | Demo, full-stack CI and exit: `make demo` and its stop behaviour; the full-stack Lighthouse job if G44 activates it here; the Keycloak-stopped check; the standards-index transitions; the outbound carrier re-verification; the delivery record naming what `P02b-0` re-verifies; the exit checks | G20 (Implemented), G33 (CI), G38 (c's job), G44, G45 Accepted; P02d-6 | -The relevant corpus includes the roadmap baseline and exit criteria; Domain Model, -module boundaries, tenant isolation, localization and customization architecture; -ADRs 0003, 0008, 0010, 0013, 0017, 0018, 0023, 0033, 0039–0044; the Tenancy, -Customization and Audit specifications; and Standards 01, 02, 05, 06, 08, 11, 13–15, -17–19 and 21. Accepted decision bodies are preserved, with the bounded ADR-0041 -erratum beside Amendment 5's false statement. The approved records and their carrier -documents form the packet's first commit, before production implementation. +`P02d-2` precedes `P02d-3` because the projection reads the definitions the seed +publishes, and because the lesson writer — not the renderer — is the first caller of the +Customization contract. `P02d-4` regenerates the SDK, so the SDK surface that must +compile against non-empty `paths` is decided there. The rendering mode and the entry +behaviour close in `P02d-5`, not `P02d-6`, because the middleware replacement and the +SDK transport are written there and change under a different answer. G32 closes in +`P02d-5` unless an earlier packet writes a seed-host literal outside `SeedData`. -#### Approved implementation sequence +#### The decision register -All work stays on `development`. No destructive migration, new package, Hub change or -cross-module Domain reference is planned. +Each row is a question this phase must answer before the packet it blocks starts. The +**Leaning** column preserves the reviewers' original proposal and is **not** a +decision; where the reviews disagreed, it states each position. The **Decision status** +column links the accepted answer for each closed part. The **Vehicle** column +is what this repository's own rules require for the answer to count. A gate whose +vehicle is an amendment is Accepted **before** the code it governs is written, not +alongside it. It closes in the decision pass of the first packet whose code it shapes, +together with any coupled gate that blocks the same packet; where its parts shape +different packets, the **Blocks** cell names the part each packet waits on. Every +premise a row cites is re-verified at that pass rather than trusted. -0. **Decision commit.** Accept the records, close the exact gate parts above, register - the structural rules, and reconcile the carrier documents and Education spec. -1. **Shared database controls.** Tighten the two existing INSERT policies by forward - migrations, fix the shared immutability function, and add structural/regression - proofs over existing tables, including audit, no-organization and pooled-GUC cases. -2. **Education schema and isolation.** Add both roots and their satellites, EF mapping, - the Education migration chain, its role grants and parent-scope control. Add unit, - schema-level isolation and Pattern A proofs with positive controls, and wire every - fixture, migration runner and matrix-discovery list that must see the new chain. -3. **Packet completion.** Apply and re-read the exact GitHub required-check changes; - run the complete relevant checks, verify fresh migration and reverse-chain behavior, - update all counts/status carriers and the packet delivery record, then commit. +| # | Question | Leaning | Vehicle | Blocks | Decision status | +|---|---|---|---|---|---| +| G1 | How does a row whose vehicle is a phase-doc statement, a standard or a catalogue row show that it is Accepted, so that the exit's "no row open" can be checked — and is the answer this phase's or roadmap-wide? | The row stays and gains a closed date and a link to the statement, and each packet's Status row and delivery record list the rows it closed. Roadmap-wide if Phase 02b's phase-doc rows should close the same way | A sentence in [Roadmap § Decision Timing](README.md#decision-timing) if roadmap-wide, or in this register's framing paragraph if local. No ADR | P02d-1 (the first pass to close such a row; it shapes no code) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): G1 | +| G2 | Which aggregate does `Lesson` belong to, and what is its parent: an entity inside `Course`, its own root referencing `Course`, or a minimal `CourseVersion` and default `Module` now? With it: how the satellites are mapped (base type, markers, `deleted_at`), the `sort` invariant and tie-breaker, and what the shape obliges Phase 05 to preserve — course and lesson ids, published slugs, order, organization scope, the inline body | The reviews split. One brings the version spine forward so Phase 05 enriches rather than re-parents; two keep this phase thin and record the preservation obligations, with Phase 05 designing the move. Between the thin shapes: inside `Course` means `ON DELETE CASCADE` and one audit row, but a lesson edit mutates `Course` structurally, which [Domain Model § Education Catalog](../architecture/02-domain-model.md#education-catalog) says a published course never is; its own root means `RESTRICT`, its own `row_version` and its own audit subject | Contract: a dated phase-doc statement; no Accepted ADR holds the `Course` / `CourseVersion` hierarchy, so a new ADR only if the answer needs a cross-root write ([ADR-0042](../decisions/0042-tenant-provisioning-cross-aggregate-transaction.md)). Detail: the Education spec's data model; an interim note in [Domain Model § Learning Content](../architecture/02-domain-model.md#learning-content) where the answer departs from it; the class count in [Database Standards § Foreign keys between tenant-owned tables](../standards/05-database.md#foreign-keys-between-tenant-owned-tables) if `Lesson` cascades | P02d-1 (the lessons foreign-key target, `ON DELETE`, `row_version`, the root mapping and satellite `deleted_at`) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): G2 | +| G3 | Which of `courses` and `lessons` carry a publication state, with which values and transitions, and what does "published" mean to an anonymous reader — publicly readable, or only listed? Which command sets it, which states does the seed write, and may a course with no lessons, or untranslated in an enabled locale, be published? And for any transition or deletion this phase does not ship (unpublishing a course or lesson, deleting either), which phase owns it? | `courses` `draft` / `published`, meaning publicly readable (Phase 05 adds catalog visibility as its own concept); lessons carry a state and show only when both are published; draft → published only; an empty course may be published, since publish validation is Phase 05's. One review leaned "listed in the catalog" | Contract: a new ADR, or a dated phase-doc statement recording why a two-value, one-transition column is not the state machine Decision Timing reserves for a decision record; no Accepted ADR decides publication ([ADR-0018](../decisions/0018-tenant-driven-customization-model.md) reserves the lifecycle to LearnStack). Detail: the `CHECK` ([Database Standards § Constraints](../standards/05-database.md#constraints)), the Education spec's state diagram, the publish row [Audit Coverage Standards](../standards/18-audit-coverage.md) makes MUST | P02d-1 (column presence and value set), P02d-2 (publishing commands and seeded states; transition contract closed in P02d-1) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): commands and seed states; independent lifecycle retained. Anonymous access superseded by [ADR-0050 / dated G3 record](phase-02d-delivery-log.md#g3-supersession-2026-10-02); original P02d-1 answer retained as history | +| G4 | Where does a lesson body's binding to the content-type key and `schema_version` it was validated against live — on `lessons` or on each translation row — and where does the body live: its column, type, per-locale placement, and how non-translatable field values are carried? May a constraint cross into the Customization chain? What becomes of Localization Standards' `isLocalized` marker, which nothing implements? | A value pin `(content_type_key, schema_version)` on `lessons`, as Phase 04 plans for `ContentEntry`, with no foreign key; the field document per locale in `lesson_translations`, every locale validated against the one pin, duplicated non-translatable values accepted until Phase 05's lesson items retire them; the marker removed or given its introducing phase | Detail: this document's § Localization schema, the Education spec, [Localization Standards § Pattern A](../standards/08-localization.md#pattern-a--side-translation-table-default-for-content-shaped-entities) in the same diff. Contract: a dated ADR-0043 amendment if a localization keyword enters the schema profile; its own ADR or amendment if a cross-chain foreign key is chosen, as ADR-0044 § 9 did, with Phase 04 and [Database Standards § Migrations](../standards/05-database.md#migrations) in the same diff | P02d-1 (the first `lessons` and `lesson_translations` DDL; a pin added later needs a backfill that guesses between two Active content types) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): G4 | +| G5 | Before Phase 05's `Level` exists, how does a course or lesson carry the level band criterion 1 shows? Does the reference pin a taxonomy revision, how is a band validated on write, and what renders when the resolved revision no longer declares the stored band? | The reviews split: (a) a nullable, non-translatable `(taxonomy_key, band_key)` on `courses`, resolved against the live revision, because the criterion names the catalog; (b) a revision-pinned triple; (c) no column, the band shown through a lesson-page `x-taxonomy` field, with the criterion reworded. No shipped path validates a band value under any of them | Detail: a phase-doc statement, the Education spec, and a Phase 05 inherited row if a reference ships. Contract: a dated ADR-0010 amendment or a new ADR if an Education table takes a foreign key into Customization | P02d-1 (whether and where a column exists), P02d-2 (validation, seeded references), P02d-4 and P02d-6 (the unresolved-band state) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): column; [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): validation and seeded references; [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): unresolved public-band response. [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): renderer state | +| G6 | Locale identity on the content path. (a) What spelling and column type do the satellites' `locale` columns store, and which rule replaces Localization Standards' "Lowercase", which the shipped `LocaleTag` does not follow? (b) Is the `locale` parameter canonicalized before lookup, the membership check and every cache or cursor key, or is a non-canonical spelling refused? (c) What does a non-canonical `/{locale}/` segment get? | (a) `LocaleTag`'s canonical case (`tr-TR`, `zh-Hans`) in `varchar(35)`, as `tenant_locales` stores it — [ADR-0018](../decisions/0018-tenant-driven-customization-model.md)'s 2026-09-04 amendment already makes case variants one locale; (b) well-formedness, then canonicalization, then lookup; (c) a redirect to the canonical segment, decided with G36 | Detail: [Localization Standards § Locale Codes](../standards/08-localization.md#locale-codes) and the Database Standards satellite fence in the same diff. No ADR: ADR-0008 states no casing rule | P02d-1 (a: the first stored rows), P02d-4 (b: validators, cursor binding), P02d-5 (c, with G36) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): (a); [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): (b); URL-segment redirects (c) remain P02d-5; [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): (c) URL redirects; prior (a,b) answers retained | +| G7 | Organization write scope. (1) Does a lesson carry its course's organization scope? (2) What forces a satellite's — and a lesson's — mirrored `organization_id` to equal its parent's at insert: writer derivation alone, or that plus a database backstop, and which? (3) May an organization-scoped session `INSERT` a tenant-wide row through the `organization_id IS NULL` arm of `WITH CHECK`, which [ADR-0003](../decisions/0003-tenant-isolation-defense-in-depth.md)'s Amendment 5 and Database Standards say it cannot and which it can at `HEAD`? | (1) Identical scope for a course, its lessons and every translation. (2) Writers derive the child's organization from the authorised parent; the reviews split on the backstop — a stored generated scope column with an organization-inclusive composite key, which structural sweeps can see, or a `BEFORE INSERT` trigger reading the parent under the caller's policies — and one review requires database enforcement. A nullable three-column key is already excluded, because `MATCH SIMPLE` skips the check. (3) Tighten, after the pass confirms no audit writer composes a null-organization row under an announced organization | Contract: one dated ADR-0003 amendment for (2) and (3), with an ADR-0041 erratum beside any sentence the pass finds false when it entered the record; the template replaced in place in [Database Standards](../standards/05-database.md) with its disclosure; forward migrations for `tenant_settings` and `audit_log` if (3) tightens. Detail: [Database Standards § Translation satellite tables](../standards/05-database.md#translation-satellite-tables); a catalogue row with a planted offender if a database mechanism is chosen | P02d-1 (policy SQL, the generated column or trigger, aggregate factories), P02d-2 (child derivation in the commands) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): database controls and factory derivation; [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): command derivation | +| G8 | Which structural guards does the Education chain register, so its tables cannot regress with the suite green: every foreign key between two tables carrying `tenant_id` includes it; every table carrying `organization_id` has the immutability trigger (and how `audit_log`'s append-only guard counts); the Pattern A rule, which would make [ADR-0008](../decisions/0008-localization-schema.md)'s "the migration linter rejects ad-hoc per-locale columns" true? And how does `fn_organization_id_immutable` — which reads `OLD.id` and is declared only in the Tenancy chain — serve satellites that have no `id`? | Three rows, each with a planted-offender companion; the function replaced by a Tenancy-chain migration that reports `OLD.organization_id` or reads the row key through `to_jsonb(OLD)`, which (as in the audit append-only guard's row comparison) never names a column the table may lack, with the cross-chain dependency recorded under Database Standards § Migrations | Detail: Standards 21 rows Registered and Implemented in the packet; the Database Standards immutability fence and § Migrations; `MigrationRollbackTests`. Contract, only if ADR-0008's sentence is left untrue: an ADR-0041 erratum if it was false when entered, otherwise a dated amendment | P02d-1 (a guard shipped with its first new subject is the only point its companion is written against real tables) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): G8 | +| G9 | Education schema detail: the content slug's character shape, normalization, width and database backstop — including whether a GUID-shaped slug is refused, which G26's shared-slot path needs; whether an Education table holds a foreign key into `tenants`, `organizations` or `tenant_locales`; and each runtime role's privileges on the four tables | `UrlSlug`'s shape with its own width constant and a `ck_<satellite>_slug_format` backstop, since restrictive now is the reversible choice (ASCII-only slugs exclude native-script URLs, a product choice); no foreign key into Tenancy; `learnstack_app` `SELECT, INSERT` plus exactly what G11's commands need, `learnstack_platform` `SELECT` | Detail: Localization Standards § Pattern A for the shape; the Database Standards satellite fence and [§ GRANT matrix](../standards/05-database.md#grant-matrix); § Migrations only if a cross-chain key is chosen | P02d-1 (the creating migration writes the `CHECK` and the grants; the grants couple with G11) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): G9 | +| G10 | What is the catalog's default order and tie-breaker, and what is the cursor it mints: its payload and version; what it binds (tenant, organization, locale, sort, filters, endpoint); its integrity (none, a MAC with a key version, or server-side state); its direction; what happens when a row changes between pages; which list parameters the endpoint binds; where it is decoded; whether the codec is this endpoint's or the kernel's; and which cursor classes answer `400`? | The reviews split between a keyless versioned payload with a binding fingerprint, decoded at binding so a garbage cursor opens no transaction, and an HMAC-authenticated cursor with key rotation. Both keep tenant and organization out of the cursor, and bind `CursorPaginationRequest` rather than `ListRequest`, whose `q` is Phase 04's search | Contract: a phase-doc statement if the codec is endpoint-local and keyless; a new ADR if it becomes a kernel rule later lists follow, or a MAC adds a secret and a rotation posture. Detail: [API Standards § Pagination](../standards/04-api-design.md#pagination), which drops "Nothing validates its *shape* yet"; Standards 21 rows | P02d-1 (the order part: an ordering column, publication timestamp or collation), P02d-4 (the codec part) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): order; [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): resource-local cursor codec | +| G11 | The write surface the seed needs. Which Education commands write courses, lessons and their translations; is a translation written separately from create; is publishing its own command; which command reports a slug collision as `business_rule_violation` rather than a raw unique violation, and does Localization Standards' "from the publish command" still hold? What shape do the Tenancy commands raising `tenancy.locale.write` and `tenancy.setting.write` take? How are the non-baseline writes classified, and how does a re-run converge? | Create course, write course translation, add lesson, write lesson translation, publish course (MUST); one locale command over `Tenant.AddLocale` and `SetDefaultLocale`; a create-or-update setting command keyed on context scope and key; ordering taxonomy → content type → course → lessons; idempotent by conflict, with an ownership check per act and a second-run test. None has a route | Contract: a phase-doc statement plus the Education spec (README write sequence, `audit.md`, `permissions.md` as a forward declaration on [the Tenancy precedent](../modules/tenancy/permissions.md)). Detail: catalogue sources, the Tenancy `audit.md` and `permissions.md`, Localization Standards § Pattern A if the collision sentence changes. An ADR only if a handler must write two roots | P02d-2 (commands, handlers, catalogue sources, seeder acts) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): commands, failures, audit classifications and convergence | +| G12 | Through which `Customization.Application.Contracts` surface does an Education write obtain the schema a body is validated against — exact `(key, schema_version)` including Deprecated revisions, or a key that binds the Active one — and is it an interface or a MediatR query, classified how? Which revisions may a writer bind, and what refusal answers an absent, cross-tenant or ineligible one? On the read side: what the cache keys on, whether the lesson response carries the binding or resolved field descriptors, and what the API and the page show when a binding cannot be resolved | One exact-revision query, Deprecated included, never falling back to Active; only Active revisions bindable for new writes, since a Draft's body can still change; absent and cross-tenant refused indistinguishably as `validation_failed` naming the binding; resolved descriptors in the response; an unresolvable binding shows a bounded placeholder with a warning log, never a `500` and never another revision's fields ([ADR-0013](../decisions/0013-page-block-schema-versioning.md)'s placeholder rule) | Detail: the Customization spec's contract and § Primary read flow, the Education spec's invariants, a phase-doc statement. No ADR: ADR-0010 settles the mechanism. A dated ADR-0013 amendment only if the unresolvable outcome departs from the placeholder rule | P02d-2 (the contract and write eligibility: the lesson writer is its first caller), P02d-3 (the cache key), P02d-4 (descriptors, the unresolvable outcome), P02d-6 (the page state) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): contract and write eligibility. [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02): cache key; [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): public response; [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): page state | +| G13 | May an Education translation be written for a locale absent from, or disabled in, `tenant_locales`, and how is membership checked across the module boundary? Does a read resolve under a disabled locale? What does a tenant with no locale rows serve — [Localization § Tenant Locale Configuration](../architecture/12-localization.md#tenant-locale-configuration) promises platform `en`, and nothing implements it? Does a platform registry bound the enabled set, as Localization Standards names one in a namespace that does not exist? What happens to translations when `RemoveLocale` runs? | A Tenancy application contract checks membership on write; a read resolves only an enabled locale, checked once per request; no cross-chain foreign key; no platform registry in this phase; a tenant with no locale rows serves nothing until it has one | Contract: a phase-doc statement over ADR-0010's application-contract mechanism. Detail: the Tenancy and Education specs; Localization architecture and Localization Standards § Locale Model reconciled in the same diff; Database Standards § Migrations only if a key is chosen | P02d-2 (the translation command's check and the locale command the seed uses; the read half is written to the same answer in P02d-4) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): write eligibility, no platform registry and no implicit no-row locale; public reader implementation remains P02d-4 | +| G14 | Seed inventory. At what scope is each seeded row class written — courses, lessons, translations, branding settings — and from what seeder context, given that `SeedTenantContext` requires an organization? Where do the rows the criteria need live — a sibling-organization course, an organization-scoped course on the tenant host, a `(locale, slug)` held in both tenants, draft and wrong-course rows, more courses than one catalog page, a disabled locale holding translations — `make seed` or test-owned data? Which key the yoga taxonomy uses, which tenant is bilingual, what state do the built-in `card` / `plain` keep, which record holds it all, and how do the Packet 7 fixture's raw settings rows coexist with seeded ones? | English content tenant-wide; the yoga studio gets a tenant-wide, a Studio One and a Studio Two course; a seed context that announces no organization; branding tenant-wide; rows in the seed with `SeedData` as the record; built-ins stay Active and are never selected implicitly; expectations recomputed as enumerated sets. An English organization-scoped row is still needed for the tenant-host criterion, seeded or test-owned — the demo database's contents are the owner's preference | Detail: a phase-doc statement, the `SeedData` remarks, the `seed-tenant` skill, the writers delivery record. No ADR: [Security Standards § Forbidden](../standards/11-security.md#forbidden) already makes scope come from context | P02d-2 (seeder steps, the seed-context constructor, `SeedData`, `SeederTests`; moving placement later rewrites the seed and every request-level case) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): inventory, ownership and test-owned controls | +| G15 | `SeedRunner` calls `IUnitOfWork.SetTenantContextAsync` on its own transaction, and neither [ADR-0040](../decisions/0040-ambient-unit-of-work.md)'s closed setter set nor [Security Standards § The out-of-band setters](../standards/11-security.md#the-out-of-band-setters) lists it. Is that method's caller set mechanically closed, and is the seeder's call reconciled by routing its ownership check through `ISender`, or by admitting the seeder? | Route the ownership check through `ISender`, and add a source scan that admits `TransactionBehavior` (and Phase 02b's transport) with a planted offender | Contract: a dated ADR-0040 amendment plus a setters-table row only if the seeder is admitted. Detail: a Standards 21 source-scan row with its companion | P02d-2 (the Education seed acts reach the ownership check's refusal arm today) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): contextual verification and Registered caller fence | +| G16 | The branding token contract. (a) Where does the settings key registry live, what does a descriptor carry, and does `tenancy.setting.write` refuse keys outside it? (b) Which branding keys exist — per-token keys or one theme document — and is a layout option among them? (c) What value does each accept, fonts and logos included, and what happens to a stored value that fails it? (d) Does a failed contrast check refuse the write or record a warning — [Accessibility Standards § Color and Contrast](../standards/16-accessibility.md#color-and-contrast) says a Studio warning? (e) What does an organization-scoped branding row do here — refused, ignored or applied? (f) Which tokens may leave an anonymous response? (g) Does `tenancy.white_label_branding` — which reads true under `NullEntitlementProvider`, whose projection grants every registered feature, falls back to its catalog default `false` from a projection that omits it, and which the Hub's Starter plan sets false — govern applying theme tokens or only removing LearnStack attribution? | (a) a registry beside `FeatureKeys` and `LimitKeys`, as `Tenant.SetFeatureFlag` already refuses unregistered keys; (b) per-token keys, at most one enumerated layout option or none; (c) `#rrggbb` colours, one font key from a closed self-hosted set, no remote logo; (d) refuse; (e) tenant-wide only, keeping Phase 06's override and ADR-0017's `OrganizationBranding` true; (f) a closed projection of publicly readable keys; (g) not gated — tokens are baseline presentation, and the key's meaning is agreed with the Hub. That token values are tenant settings is settled by [Frontend Architecture Standards § Tenant Branding](../standards/07-frontend-architecture.md#tenant-branding) | Contract: a phase-doc statement plus Frontend Architecture Standards § Tenant Branding; a new ADR if the registry becomes an admission rule for every `tenant_settings` key; a dated ADR-0017 amendment if (e) applies overrides; Accessibility Standards if (d) replaces the warning. Detail: the Tenancy spec and permission matrix, [Frontend Architecture § Theming](../architecture/14-frontend-architecture.md#theming), the `FeatureKeys` descriptor with a matching note in the Hub repository for (g) | P02d-2 (a–e: validation and the seeded keys, which Phase 06's editor later edits), P02d-4 (f, g: the anonymous projection the OpenAPI baseline freezes), P02d-6 (g: whether rendering consults the flag) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): (a–e); [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): public projection and attribution (f/g); [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): injection and attribution (g) | +| G17 | Does `TenantSetting.Value` carry `[PiiSensitive]`? [Phase 03](phase-03-identity-admin.md) sequences the decision before the first command writing `tenant_settings`, and this phase ships that command | Not marked, provided `tenancy.setting.write` admits only G16's closed key set, so the answer cannot stretch to keys a tenant invents; modelling a sensitive part as its own property stays open to Phase 03 | Contract: a dated phase-doc statement, reflected in `TenantSetting.cs`, the Tenancy spec and `audit.md`. Whole-value redaction of `jsonb` is settled by [ADR-0044](../decisions/0044-audit-write-path.md) Amendment 4 § 1 | P02d-2 (the first MUST-class settings audit row is written by the seed, and rows cannot be redacted retroactively); closes with G16 (a) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): generic whole-value PII redaction before the writer | +| G18 | How is a tenant content type presented? `json_schema` is `jsonb`, which keeps no key order, and the schema profile collects only `x-renderer`, `x-taxonomy` and `x-language`. How are field order, a label per enabled locale and a composite's field roles carried; which registered composite draws a lesson for each seeded type; which primitives does this phase implement, and does `markdown` render; how do types with no primitive row (`integer`, `number`, `boolean`, enums) map; may a rendered type declare a field outside the subset; and is a presentation entry naming a missing property refused at save? | A LearnStack extension — `x-order` and `x-label`, or one ordered `x-fields` list — carrying Pattern B labels, resolved at write like `x-taxonomy`; one composite already in both registries; the reviews split on the subset — `text`, `list` and `link`, with `markdown` without raw HTML, or a placeholder until Phase 05's sanitiser; the seed uses only the subset | Contract: a dated ADR-0043 amendment for a keyword or a save-time refusal; a dated ADR-0018 amendment for a presentation column; a phase-doc statement for `title` plus `required`, which cannot carry two locales. Detail: [Tenant Customization Model § 2](../architecture/32-tenant-customization-model.md) and § 8.1, the Customization spec, the profile's extension and reference-graph skip lists, `composites.ts` | P02d-2 (the seed publishes both content types as `schema_version` 1 with their renderer keys and field kinds; a later answer needs successor revisions) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): ADR-0051 profile and first-render subset. Component placement/fallback remains G41 | +| G19 | URL and markup policy for tenant-authored values on an anonymous page: which schemes (`https` only, or `http` too), credentials and `target`, which media origins, whether the rule is enforced on write — in the Education command, or as a validation gate Phase 04's entries share — whether the public API filters too, and whether URLs inside markdown fall under it. The write-time check constrains structure, not schemes: `format: uri` admits `javascript:` and `data:` | The reviews split on `http`; all refuse `javascript:`, dangerous `data:` and credentials; checked on write by a LearnStack rule and again on render; no third-party media in the seed | Detail: one home for the scheme list — [Security Standards § XSS & Output Encoding](../standards/11-security.md#xss--output-encoding) or [Frontend Architecture Standards § Security](../standards/07-frontend-architecture.md#security), not both; the Education spec's write rules; Tenant Customization Model § 8.1 if checked on write. Contract: a dated ADR-0043 amendment if it becomes a shared validation gate | P02d-2 (the lesson command's validation and the seed values; the render-time check reuses the answer) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): no active sink in the seeded text profile; future URL/markup contracts precede Phase 04/05 sinks | +| G20 | What mechanically backs "no production code branches on which tenant it serves"? The shipped domain-term scan strips literals and exempts seed data. (a) The mechanism and its literal source; (b) its subjects, matching and the platform built-ins; (c) its exemptions, including development hosts in frontend or infrastructure configuration; (d) whether a ban on production references to `LearnStack.Tools.Seeder` and a behavioural same-code, different-data test accompany it | A Standards 21 sibling row scanning production backend and `frontend/` sources, comments stripped, for exact identity literals read from `SeedData` (slugs, ids, hosts, display names, customization keys), built-ins excluded, with planted offenders; plus the behavioural test. The exemption policy is the owner's judgement | Detail: a Standards 21 row Registered in the first pass that uses it and Implemented before exit; a phase-doc statement in § Genericity proof. No ADR | P02d-2 (a: every seed literal lives where the source reads it), P02d-5 (c: the first host outside `SeedData`), P02d-6 (b: frontend subjects), P02d-7 (Implemented and required) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): (a) SeedData literal source and Registered guard. [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): (c) exemptions; [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): (b) frontend subjects; implementation and behavioral proof remain P7; [Accepted — 2026-10-11](phase-02d-delivery-log.md#p02d-7-decision-package-2026-10-10): matching, canonical built-ins, Seeder-reference fence and behavioral ownership; Step 2 implements the required fences and schema-replacement companion | +| G21 | Does the anonymous public path set any cookie — the [Frontend Architecture Standards § Tenant Resolution](../standards/07-frontend-architecture.md#tenant-resolution) flowchart sets them — and may a public page load any cross-origin subresource, such as the CDN-hosted logo and font assets Frontend Architecture describes? | No cookies, since the locale is already in the path and a locale-less request redirects ([Localization Standards § URL Strategy](../standards/08-localization.md#url-strategy)); same-origin subresources only; both asserted by a check. Whether tenant branding may point visitors' browsers at third-party hosts is a data-protection choice for the owner | Detail: a phase-doc statement; the Standards 07 flowchart and Frontend Architecture § Theming reconciled in the deciding pass | P02d-2 (subresources, if G16 admits a URL-valued token), P02d-5 (cookies: the middleware replacement is the first code that could set one) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): subresources. Cookies remain open for P02d-5; [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): cookies; prior subresource answer retained | +| G22 | How does the customization definition projection load and stay correct? In the request's ambient transaction, or as a ninth out-of-band tenant-context setter (ADR-0040's set is closed at eight)? In what order are the generation and the rows read; what does an absent generation row mean; how is a cache filled inside a transaction that bumped and rolled back kept unreachable, when the bump is an upsert increment that can reissue a number; what does an absent definition set return; which families are registered, and how does the adapter's exact-tuple `cache.name` mapping match generation-embedded names; what do the TTLs bound; and is the contract batched so a public read issues a bounded number of statements? | Load in the ambient transaction; read the generation first, then the rows; fill only from non-bumping transactions; treat cache faults as misses; restate the module's cache-hit budget; a batched contract, with statement-count assertions cold and warm | Contract: the Customization spec § Primary read flow and a [Tenant Customization Model § 8.2](../architecture/32-tenant-customization-model.md#82-cache-strategy) statement on how a request learns the generation; a dated ADR-0040 amendment and a setters row only if the loader is out-of-band. Detail: the [Infrastructure Stack Standards](../standards/20-infrastructure-stack.md) cache table, the `cache.name` mapping, the Observability Standards metrics family list | P02d-3 | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02) | +| G23 | The typed settings accessor and its freshness. With no declared settings-invalidation event and the seed writing from its own process, what bounds staleness: a TTL with a stated bound, a writer-coupled Tenancy settings generation counter, or no settings cache here? What are the accessor's name and glossary headword; how is a cached read keyed so tenant-wide and organization rows never cross organizations — a settings read depends on `app.organization_id` today, and the policy's tenant-scope read gains a carrier in Phase 03; and does its loader run in the ambient transaction? | The reviews split on freshness — a TTL bound, a counter, or no cache. For keys: tenant-wide rows loaded with an explicit `organization_id IS NULL` predicate under `CacheKey.ForTenant`, each organization's overrides under `CacheKey.ForOrganization`, merged in memory; an ambient loader. The documented tenant-only key is rejected, because it would serve one organization's overrides to another | Detail: if settings are cached, the Infrastructure Stack Standards cheat-sheet rows and `cache.name` mapping; the Tenancy spec's event catalogue and budget; a glossary headword. Contract only for a counter (the Tenancy spec, Database Standards § Table classes and § GRANT matrix) or an out-of-band loader (an ADR-0040 amendment) | P02d-2 (a counter is bumped inside the setting command's transaction), P02d-3 (name, keys, loader) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-2-accepted-answers): no settings cache in P02d-2/3. [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02): typed ambient accessor/scoped merge | +| G24 | Display fallback. Which document owns the chain — [Localization § Fallback Rules](../architecture/12-localization.md#fallback-rules) or [Localization Standards § Locale Model](../standards/08-localization.md#locale-model), which state different chains, while the shipped `LocalizedText.Resolve` narrows one subtag at a time and ends at the first authored value? What is the terminal state of a nullable Pattern A field and of a Pattern B label? Does a response say which locale a fallback value resolved in, so the page can mark its language (WCAG 3.1.2)? | Localization architecture owns the chain and Localization Standards links it, both recording the shipped narrowing and the first-authored terminal for labels; a nullable Pattern A field renders absent; each fallback-capable field reports its resolved locale | Detail: Localization Standards § Locale Model linking its owner, reconciled with `LocalizedText` in the same diff; the Customization contract's signature; the response schema under G26. No ADR | P02d-3 (the first caller that passes a fallback chain), P02d-4 (response fields) | [Accepted — 2026-10-02](phase-02d-delivery-log.md#p02d-3-decision-package-2026-10-02): internal fallback; [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): public response locale fields; renderer language attributes remain P02d-6 | +| G25 | Site data and the page set. How does the renderer get the per-host data none of the Education reads returns — enabled and default locales, branding tokens, taxonomy display values, content-type field lists: fields embedded in the course reads (which cannot supply a default locale before a locale is known), a separate `[PublicSurface]` read resolved from the effective host, or the edge host lookup [Frontend Architecture Standards § Tenant Resolution](../standards/07-frontend-architecture.md#tenant-resolution) and [Infrastructure Stack Standards § Host → Tenant Resolution](../standards/20-infrastructure-stack.md#host--tenant-resolution) prescribe today, which must then state the effective host over the hop? Does the frontend ever hold a tenant or organization id? And which `(public)` pages ship — catalog, course with ordered lesson links and lesson, or two pages with bounded lesson links in the catalog response? | One `[PublicSurface]` site-data read with no host parameter, returning a closed projection and no ids, and three pages, which gives the course-detail read a consumer; one review keeps two pages with an explicit catalog outline. The first two options change what two Active standards prescribe | Contract: a phase-doc statement in § Read API and § Public renderer; for the first two options, edits to the two standards named, with an ADR if the pass judges the change non-trivial (no ADR carries the edge-lookup rule). Detail: the API Standards § Public surface rows; the Frontend Architecture sketch, sequence diagram and cache rows; the Localization architecture's edge locale sentence; the glossary; Phase 06 § What Phase 02d already shipped; Phase 05's inherited row if the course-detail read changes | P02d-4 (the endpoint set and DTOs the OpenAPI baseline freezes; a two-page answer changes the catalog response) | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): bootstrap and page set; page implementation remains P02d-6 | +| G26 | The v1 public read contract. The path shape beside Phase 05's authoring `/courses/{id}` — a shared slot, a distinct public prefix, or `/courses/by-slug/{slug}`; each response as an allow-list and what it never carries; the embedded lesson list's fields, order and bound, and whether an empty list is valid; per-locale alternates; how enums and envelopes stay additive; and which Problem Details responses each operation documents, given that no non-idempotent operation documents any today and a baseline of `200`s cannot see a status change | Fields limited to what the pages render; object envelopes, extensible enums, a deny-list contract test (`tenantId`, `organizationId`, `createdBy`, `updatedBy`, `deletedAt`, `rowVersion`, `slugKey`); the embedded list carries title, slug and order under a cap; `alternates` for enabled, translated locales; one shared transformer declaring each operation's statuses as `application/problem+json`. No review settled the path | Contract: a phase-doc statement recorded before the breaking-change check stores its baseline. Detail: the OpenAPI snapshot; [API Standards § URL Structure](../standards/04-api-design.md#url-structure) for a prefix class, § Pagination for an embedded list, § OpenAPI; the gateway's public-band row. [ADR-0024](../decisions/0024-api-versioning-policy.md) settles that later additions are non-breaking | P02d-1 (whether the slug grammar must refuse GUID shapes, with G9), P02d-4 (route templates, records, snapshot) | [Accepted — 2026-09-14](phase-02d-delivery-log.md#p02d-1-accepted-answers): slug grammar; [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): route and response contracts | +| G27 | The cache posture of public reads. What directive do anonymous responses carry — the `200`s, the Problem Details `400`s and `404`s, the tenancy edge's unmapped-host `404` — what freshness do a newly published or unpublished course and a not-found have, and do anonymous reads emit an `ETag` and honour `If-None-Match`? [API Standards § Optimistic Concurrency](../standards/04-api-design.md#optimistic-concurrency) says mutable resources expose an `ETag`, and [ADR-0039](../decisions/0039-optimistic-concurrency-token.md) fixes one derivation, which a composite read cannot use without publishing `row_version` | An explicit `Cache-Control: no-store`, asserted by a test, and no `ETag` on anonymous reads — a response without explicit freshness may be cached heuristically by a shared cache. One review proposed no directive, stated | Contract: a phase-doc statement. Detail: API Standards — the directive, and a § Optimistic Concurrency sentence on anonymous read contracts, owed under either answer. A dated ADR-0039 amendment if a body-hash validator ships; [Performance Standards § Caching](../standards/15-performance.md#caching) if the answer caches | P02d-4 (the header-setting code and the headers the snapshot documents) | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): no-store without response validators | +| G28 | Public-surface controls. (a) What audit class do `[PublicSurface]` requests register, and does a rule make `Off` the only permitted one? (b) `GET` only, or `GET` and `HEAD`, and what does the catalogue's permitted-methods leg compare a row against? (c) What mechanically stops a marked request from writing — a `READ ONLY` unit of work, a structural scan, or both? (d) What control beyond review keeps a controller dispatching only through `ISender` — a controller taking a module `DbContext` fails loudly, SQL on `IUnitOfWork.Connection` reads zero rows, and code that announces the tenant itself reads real rows? | (a) `Off` for every marked type — a SHOULD or MAY class would make every anonymous `GET` a best-effort write a caller controls — with a sibling rule and companion; (b) one review `GET` only, one the standard's `GET` / `HEAD`; (c) a `READ ONLY` transaction for marked requests, which three shipped setters already open before announcing, and which refuses any in-transaction MUST write, so it is checked against (a); (d) a type-reference rule over controller bodies with a planted offender | Detail: the API Standards § Public surface rows; Standards 21 rows and companions, including the two legs of `PublicSurface_Marker_Set_Is_Enumerated` not yet implemented; an [Error Handling Standards § Controller Mapping](../standards/09-error-handling.md#controller-mapping--resultt--iactionresult) sentence for (d). Contract: a dated ADR-0040 amendment if the unit of work gains a read-only mode | P02d-4 (the first marked query's registration, method attributes and handler; if P02d-3 writes on the read path, (c) closes there) | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): Off, GET/HEAD, mandatory dispatch and read-only controls | +| G29 | Which rows do the anonymous reads serve, and what does every hidden row answer? The rule covers course state, lesson state (G3), the lesson's membership in the course its URL names — lesson slugs are unique per tenant, so a lesson resolves without its course segment unless the read checks — and soft deletion. Does every hidden cause (draft, deleted, wrong course, untranslated, other tenant, sibling organization, nonexistent) answer one `not_found` body with no per-cause detail, compared with `instance` and `correlationId` masked? | One eligibility rule used by every read; a lesson resolves only under its eligible parent, only when it belongs to it, only in the requested locale; lists show only eligible entries; deleted rows excluded now; one masked-equal body | Contract: a phase-doc statement whose single record is the Education spec. Detail: the failure constant. Settled and linked: a cross-tenant row is a `404` ([Security Standards § Error Messages](../standards/11-security.md#error-messages)), and an organization-scoped row is served only on its own organization's host ([Localization § Slugs and URLs](../architecture/12-localization.md#slugs-and-urls)) | P02d-4 (handlers, the failure constant, documented `404`s); the fixture rows close with G14 in P02d-2 if they live in the seed | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): explicit eligible reads and uniform masking | +| G30 | The locale error matrix and transport. On each read, what answers an empty, repeated, malformed, over-length, non-canonical, not-enabled or enabled-but-untranslated locale? Does a not-enabled locale answer the Active `unsupported_locale` `400` or the not-found body? Is `X-Locale`, which [Frontend Architecture Standards § Locale Resolution](../standards/07-frontend-architecture.md#locale-resolution) still names as the API carrier, withdrawn, so that locale reaches the API only as the query parameter? | Missing or malformed → `400` `validation_failed` naming `locale`; untranslated → an empty catalog page; the query parameter only. The reviews split on not-enabled — not-found, amending the Error Handling row, or the Active `400`; a uniform answer after the enabled check hides pre-launch rows under either | Detail: a phase-doc statement; the [Error Handling Standards](../standards/09-error-handling.md) table only if not-found; Standards 07 § Locale Resolution; the Frontend Architecture SDK sketch; the API Standards § Pagination example gains `locale` | P02d-4 (validators, OpenAPI parameters and responses), P02d-5 (the server SDK's header set) | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): query/error matrix; trusted server header transport remains P02d-5; [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): header transport; prior API query-locale answer retained | +| G31 | Contract checks and the SDK surface. The committed OpenAPI snapshot's path, and how the contract suite proves it equals the served document; how the base copy is read; how the first run behaves; which `oasdiff` version and fail level, and which ADR-0024 rows that level detects (a tightened validator or a changed status may be invisible to any diff); what is uploaded on failure. The drift gate's source — the committed snapshot through `LEARNSTACK_OPENAPI`, or a running API — and its job. Whether an activated deferred job keeps its `if: vars.ENABLE_*` condition, given that GitHub treats a skipped required job as passing, or loses it as the integration job's did. And what the SDK surface becomes when regeneration makes `paths` non-empty: a hand-written transport over `paths` or a typed client library, the fate of `createClientSdk`, and whether the package root keeps re-exporting the server entry | A committed snapshot the contract suite asserts equal, diffed against the base ref's copy with `oasdiff` pinned; drift generated from the snapshot in the required `frontend` job; the condition removed on activation; a thin hand-written transport, and no root re-export of the server entry | Detail: [Testing Standards § API Contract Tests](../standards/06-testing.md#api-contract-tests), the API Standards § OpenAPI links, `ci.yml`, [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) (its activation procedure follows the answer), [Frontend Architecture Standards § SDK](../standards/07-frontend-architecture.md#sdk); a package pin with its licence verdict if a client library is chosen | P02d-4 (the first operation, its snapshot and assertion, the drift gate, and the regenerated types the factories must compile against) | [Accepted — 2026-10-03](phase-02d-delivery-log.md#p02d-4-accepted-answers): snapshot, SDK, diff/drift and approved required-check activation | +| G32 | **The development-transport part of [Phase 02b](phase-02b-events-auth.md#the-decision-register)'s G12.** Which development hostnames and transport serve the two seed tenants — keep `*.learnstack.local`, with a hosts-file step and local TLS with a trust step, or move the seed hosts under `*.localhost`? What does a reviewer do between a clean checkout and both sites, and which carriers move, including host rows already on warm databases, where the host is the primary key and the seeder removes no mapping? | `*.localhost` over HTTP, provided the pass verifies in each browser the team uses and in CI's Chrome that both hosts resolve with no hosts entry and that a `Secure` cookie set on them is stored and returned; otherwise `*.learnstack.local` with local TLS and a named trust step. Tenants are never told apart by port: the effective host strips it | Detail: a dated phase-doc statement in [§ Host-based tenant resolution, end to end](#host-based-tenant-resolution-end-to-end), with `SeedData`, `scripts/seed.sh`, the README Quickstart, the `seed-tenant` and `local-dev-setup` skills and `apps/web`'s dev script and Next configuration in the same packet; Infrastructure Standards only if a TLS proxy publishes a port. No ADR | P02d-5 (the development transport, and the hop configuration a TLS proxy would change), or the first earlier packet that writes a seed-host literal outside `SeedData` | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): local hosts and TLS | +| G33 | The server-rendering topology and its evidence. Where do Next.js and the API run relative to each other — the workstation loopback, containers, gated APISIX; which networks are trusted; how does one hop secret reach both processes; what is the server-only API origin — and the same for the CI job that renders the pages? What evidence discharges ADR-0036's "Phase 02d's browser test" and its matrix rows "a direct socket bypassing the hop" and "the Phase 02d anonymous two-host browser render", given that Testing Standards gate this phase on a human? And ADR-0036 § Consequences says the root refuses to start outside Development when the secret list is empty or short, while the shipped rule, in every mode, refuses a half-configured hop, a network entry that is not CIDR and a blank secret or one under 32 characters (characters, not bytes), and admits both lists empty: is that recorded or restored, and is non-development hop configuration this phase's or Phase 11's? | Both processes on the loopback, networks `127.0.0.1/32` and `::1/128`, one generated secret from a single source and never under `NEXT_PUBLIC_`, with networks and secrets arriving together (committing networks without secrets breaks every Development-environment fixture); the API called directly; a per-run secret in CI. Evidence: request-level hop tests as `learnstack_app` — no `X-Tenant-Id`, a non-hop peer, a wrong secret, a repeated header — beside the human walkthrough, with one review adding an automated browser smoke. Record the shipped startup rule; non-development hop configuration is Phase 11's | Contract: one dated [ADR-0036](../decisions/0036-tenant-resolution-trusted-inputs.md) amendment if the evidence departs from the ADR's words, recording the startup rule, and carrying G34 if G34 changes the key or budget. Detail: `.env.example`, `apps/web/.env.local.example`, `appsettings.Development.json` or the demo recipe; a Standards 21 row for the hop runtime test; a Testing Standards § End-to-End Tests sentence only if ownership moves; a Phase 11 scope row | P02d-5 (the hop configuration and the fixture shape — in-process test hosts have no socket peer), P02d-7 (the CI part) | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): local topology, shared source and ingress; [Accepted — 2026-10-11](phase-02d-delivery-log.md#p02d-7-decision-package-2026-10-10): shared CI lifecycle/topology; ADR-0056 measurement Accepted on the same date; Step 3 local proof passes; Step 4 owns real CI receipts | +| G34 | How does the pre-classification anonymous limiter treat a request arriving over the authenticated trusted hop? Every server-rendered call reaches the API from the renderer's peer, so every visitor of both tenants shares one partition, and one client sending random `Host` values through the renderer can starve both sites. The partition key, the budget and how the renderer derives any visitor identity it states — while unknown-host floods stay bounded before database work, and a direct peer is still limited per peer | The reviews differ: a visitor address stated over the hop, in a dedicated single-valued header or through `X-Forwarded-For` with the peer captured first, as ADR-0036 anticipates; a separate hop budget with limiting in the renderer; or an explicitly sized shared quota. A per-host ceiling as the only backstop multiplies under a random-`Host` flood | Contract: a dated ADR-0036 amendment if the hop changes the key or the budget, stating the new input's trust rule and whether it may be logged or audited; otherwise a phase-doc statement. Detail: API Standards § Request and Response Limits, [Security Standards § Rate Limiting](../standards/11-security.md#rate-limiting), the catalogue's per-peer rule. `P02b-0` re-verifies Phase 02b's G14 against the answer | P02d-5 | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): authenticated visitor and peer budgets | +| G35 | The server SDK transport. Its options — visitor host, locale, an optional assertion, never a tenant id as selector; where the host comes from; how the API origin is configured; the server-only guard, timeouts and cancellation; and whether it forwards W3C `traceparent`. With it: which parts of [Observability Standards § Frontend Observability](../standards/10-observability.md#frontend-observability) — Next.js error capture, web vitals — ship here, and which phase owns the rest, since no phase names them | Host and locale plus an optional assertion; hop headers and origin from server configuration, never from request input; a `server-only` guard; Problem Details mapped to the `AppError` union [Error Handling Standards](../standards/09-error-handling.md) already fixes; `traceparent` forwarded; Next.js error capture and web vitals assigned to Phase 11, whose § Observability lists error tracking | Detail: Frontend Architecture Standards § SDK and the Frontend Architecture SDK sketch; a pin and licence verdict if a guard package is added; an exclusion row naming frontend observability's owner, with an Observability Standards sentence | P02d-5 (the transport's headers and configuration read); the ownership half closes by exit, because a deferral names its phase | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): configured caller, deadlines and observability owners | +| G36 | The edge middleware and entry behaviour. Does the middleware resolve anything (with G25)? What does it carry inward, and under which header name — the Frontend Architecture sketch reuses `x-learnstack-host`, the hop header's own name? Which inbound internal headers are removed or overwritten, including `x-organization-id` when resolution has none — a deny-strip or an allowlist rebuild? What does the matcher exclude? What do `/` and a locale-less path answer, with which status, target and default-locale source; what do a disabled, malformed or non-canonical locale segment (G6 c), a platform host and an unknown host answer; does this run in middleware or the route tree, and may an i18n library own the middleware? Does this phase build the locale-less redirect [Localization Standards § URL Strategy](../standards/08-localization.md#url-strategy) requires, or keep the standards index's i18n-runtime carve-out while Phase 06 claims redirect handling? | Normalise the host; strip every client-supplied `x-tenant-id`, `x-organization-id`, `x-locale` and `x-learnstack-*`; drop the scaffold's `503` guard and TODOs; `/` redirects to the tenant's default locale; a disabled locale is a `404` before any content call; a platform or unknown host gets a `404` with no platform text; the redirect built minimally here, with Phase 06's rows reworded to "deepens" | Detail: a phase-doc statement; the Standards 07 § Tenant Resolution flowchart and the Frontend Architecture middleware sketch; Phase 06's rows in the same diff; if less is built, a dated narrowing of the standards index row for Localization Standards naming the owning phase | P02d-5 (the middleware replacement rewrites the scaffold's locale fallback, so every placement answer changes it first) | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): membership-first entry and redirects | +| G37 | How do tenant-varying `(public)` routes render, and which Next.js caches may hold tenant data — the full-route cache, the fetch data cache, `unstable_cache`, `generateStaticParams` — so one host's page is never served on the other? A public URL carries no tenant, and both tenants send the same request line over the hop, so a path-keyed cache leaks. What freshness does a page have after a customization or content write? | All three reviews: dynamic rendering with uncached SDK fetches — no `revalidate`, no `generateStaticParams`, no `unstable_cache` — relying on the API's generation-keyed cache; no ISR here | Detail: [Frontend Architecture Standards § Public Site Renderer](../standards/07-frontend-architecture.md#public-site-renderer), which prescribes `revalidate` today, and [Frontend Architecture § Rendering Strategies](../architecture/14-frontend-architecture.md#rendering-strategies), rewritten with the `add-frontend-route` skill; [Performance Standards § Caching](../standards/15-performance.md#caching) if the answer caches; an ADR if the pass judges the Standards 07 change non-trivial | P02d-5 (one mechanism: a host-bearing rewrite target is middleware code and fetch cache options are transport code, both written before the renderer) | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): dynamic no-store renderer policy | +| G38 | The frontend test set. (a) Which predicates of the middleware and the server SDK does Vitest cover, and in which packages — `pnpm -r test` runs only packages with a test script, which `packages/sdk` lacks? (b) How are async Server Component pages and field components covered below the browser, given vendor guidance that Vitest does not render async Server Components? (c) What automated evidence, if any, re-proves the page-level two-host claim after exit — an HTTP smoke against `next start`, one narrow Playwright smoke pulled forward from Phase 06, or a dated manual record? (d) By what mechanism does the `frontend` job refuse skipped and todo cases, which it does not today, since `No_Architecture_Test_Is_Skippable`'s runner leg reads only the backend `.trx` files? | (a) host normalization and header stripping, locale parsing and entry answers, hop headers with no tenant selector, `not_found` mapping — each with an inversion companion; (b) async pages covered through their synchronous children; (c) the reviews split three ways; (d) a reporter-output check or a lint ban on disabled tests, failing also on a package with tests and no script, proven with a planted skip | Detail: a phase-doc statement; the test files; the Standards 21 entry `No_Architecture_Test_Is_Skippable` extended rather than a second name; `ci.yml`. Contract for (c) only if a browser smoke moves: a Testing Standards § End-to-End Tests edit citing this row, with its carriers | P02d-5 (a; d at the latest), P02d-6 (b, c), P02d-7 (c's job) | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): (a,d) tests and non-skippability; [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): (b,c) synchronous tests and required production HTML/RSC product proof; P7 owns the browser/demo job; [Accepted — 2026-10-11](phase-02d-delivery-log.md#p02d-7-decision-package-2026-10-10): narrow browser-job scope; ADR-0056 measurement Accepted on the same date; browser proof delivered in Step 3; CI receipts owned by Step 4 | +| G39 | Is [ADR-0027](../decisions/0027-frontend-i18n.md), the frontend i18n library, Accepted in this phase rather than Phase 04, or do this phase's pages meet a library-neutral message contract under the standards index's carve-out? Where does the one UI string catalogue live — the carriers name three paths? | The reviews differ: Accept at first use (`next-intl` composed with the tenant middleware, with its pin and licence verdict), or move only the minimum slice — catalogue loading, lookup, layout locale, `lang`. A third option, no platform-authored text, is hard for a skip link or a not-found page | Contract: ADR-0027 Accepted, with the decisions index row, Phase 04's ADR-0027 lines and the standards index row in the same diff — which, under [the decisions index SLA](../decisions/README.md#open-adr-drafts), makes it an exit blocker here — or a narrowed carve-out plus a phase-doc statement. Detail: [Localization Standards § Strings in Code](../standards/08-localization.md#strings-in-code), [Localization § UI String Catalogue](../architecture/12-localization.md#ui-string-catalogue), the `add-i18n-key` and `add-frontend-route` skills | P02d-6 (the first platform string, message loading and catalogue files) | [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): ADR-0027, exact pin and one checked UI catalogue home | +| G40 | Route files, page states and site chrome. What happens to `(public)/page.tsx`'s platform placeholder, and to `/studio` and `/portal` on tenant hosts; is the `courses` segment fixed, and which phase owns localized section names? Does this phase ship `(public)` loading, error and not-found files — [Frontend Architecture Standards § Routing](../standards/07-frontend-architecture.md#routing) requires `loading.tsx` and `error.tsx` per route group, and a not-found page is this phase's own choice; how do SDK `not_found`, a cursor `validation_failed`, unavailable and `429` map to page states; what do an empty catalog and a course with no eligible lesson show; does the catalog render a next-page link? Does a minimal chrome ship? Are `hreflang`, canonical and `og:locale`, which [Localization Standards § SEO](../standards/08-localization.md#seo) requires on translated public pages, built here or carved out? | The placeholder leaves the public tree; a fixed `courses` segment with the section-name owner named; minimal state files in tenant tokens; `not_found` → an HTTP `404` page; unavailable or `429` → the route group's error page without disclosure; an explicit empty state; a next-page link over enough seeded courses; in-page links rather than chrome, keeping Phase 06's navigation rows true | Detail: a phase-doc statement; Phase 06's § What Phase 02d already shipped rows reworded; a dated carve-out in the standards index row for Frontend Architecture Standards or Localization Standards, naming the owning phase, for whatever this phase builds less of | P02d-6 | [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): product routes, approved status/URL chain, page states and metadata | +| G41 | How does the lesson page draw what the subset does not implement — an out-of-subset `x-renderer`, a missing optional field, an array of objects, a stored value whose type differs from its declaration, an `x-taxonomy` value and its missing band? And where do composite and primitive components live — Frontend Architecture Standards names `packages/blocks`, Frontend Architecture names `components/blocks/`, and the registry sits in `apps/web/src/lib/customization/`? | A safe placeholder, never an exception and never raw JSON; a missing optional field renders nothing; `integer`, `boolean` and enums as text; an `x-taxonomy` value as the band's display name in the requested locale. No review addresses the component home | Detail: Tenant Customization Model § 2 (the implemented subset, not a second list) and § 8.1; Frontend Architecture Standards § Public Site Renderer and the Frontend Architecture tree. A new primitive would be an ADR-0018 release, which this row must not assume, since Phase 04 owns the field-type set | P02d-6 | [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): ordered plain-string components and bounded fallbacks | +| G42 | How do validated branding tokens reach the server-rendered HTML — a `style` attribute on the root element, which needs `unsafe-inline` or `unsafe-hashes`; a nonce-compatible `<style>` element built from validated values; or a per-tenant stylesheet route — without constraining [Security Standards § HTTP Headers](../standards/11-security.md#http-headers)' nonce-based target before Phase 11 documents it per surface? | A `<style>` element built only from registry-validated values, emitting only the `--ls-*` vocabulary, never a `style` attribute; a nonce would force dynamic rendering (G37) | Detail: Frontend Architecture Standards § Tenant Branding for the mechanism; Frontend Architecture § Theming | P02d-6 (the layout's token injection; closes with G37's answer and G16's grammar) | [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): atomic four-token style-element injection | +| G43 | Which accessibility checks on this phase's pages fail a build — route tests asserting `lang`, one `<main>`, the heading outline, a skip link and a descriptive title; `jsx-a11y` at error severity, where most of the shipped config's rules warn; or jsdom axe, which Testing Standards puts through Playwright in Phase 06? Is catalog → lesson a critical flow that needs [Accessibility Standards § Testing](../standards/16-accessibility.md#testing)' screen-reader smoke test? | Route tests in the `frontend` job for the checkable semantics; keyboard, focus and 320 CSS px reflow in the manual record; failing `jsx-a11y` with a planted companion. No review addresses the screen-reader question | Detail: a phase-doc statement; [Accessibility Standards § Tooling](../standards/16-accessibility.md#tooling) if lint severity or component axe becomes a rule; the lint configuration. Whether failing lint enforces the standard couples with G44; its index row changes only in the enforcing pull request | P02d-6 (page components and their tests) | [Accepted — 2026-10-09](phase-02d-delivery-log.md#p02d-6-accepted-answers): failing lint/semantics and mandatory manual assistive-technology proof | +| G44 | The Lighthouse job. Does it activate in this phase, and on what full-stack harness — a migrated stack, a seed written as `learnstack_app`, the API as a process over the hop with a per-run secret, `next start` on a production build, both seed hosts reachable from CI's browser, a readiness and tenant-marker check before the audit — or does activation move to the phase that brings a browser harness? What does it assert: the URL set and which [Performance Standards](../standards/15-performance.md) row each page answers to (its LCP row names a landing page this phase does not ship); which rows, under which throttling preset; the 200 KB budget or the 250 KB forbidden line; hard or warning, run count and aggregation; categories, including the accessibility audit [Accessibility Standards § Tooling](../standards/16-accessibility.md#tooling) requires; the runtime ceiling, tool install and report destination; and what the standards index rows for Performance and Accessibility say afterwards? | Activate here, reusing the `make demo` entrypoint; catalog, course and lesson on both hosts plus the bilingual tenant's second locale; hard assertions on deterministic audits (script transfer size, CLS, the accessibility category or contrast over both palettes) and median-of-N timings as warnings, with TBT rather than a lab INP; tooling from the lockfile; reports to workflow artifacts only; Accessibility promoted if asserted hard, Performance kept Adopted as a pre-baseline check unless a hard budget makes it Active for what ships. The budget authority is settled: [Frontend Architecture Standards § Performance](../standards/07-frontend-architecture.md#performance) names Performance Standards | Contract: a phase-doc statement plus a committed Lighthouse configuration. Detail: `ci.yml`, CONTRIBUTING's activation edits, the `run-tests-locally` skill; Performance Standards only if a number or lab profile changes; the standards index rows and status headers in the enforcing pull request. Moving activation edits `ci.yml`, CONTRIBUTING and the skills, and leaves Phase 01's and 02a's records as written | P02d-5 (whether it activates, as an input to G32: the hosts must work in CI's browser), P02d-7 (the harness and assertions) | [Accepted — 2026-10-08](phase-02d-delivery-log.md#p02d-5-accepted-answers): whether: activate in P7; harness details stay P7; [Approved — 2026-10-11](phase-02d-delivery-log.md#p02d-7-approval-and-exit-boundary): bounded seventh-check activation after real success; [Accepted — 2026-10-11](phase-02d-delivery-log.md#p02d-7-accepted-answers): ADR-0056 measurements and serial feasibility gate; local enforcement passes; live CI/protection receipts owned by Step 4 | +| G45 | What does `make demo` start and guarantee on a clean checkout? The process model — a foreground supervisor over detached compose, or detached processes with a stop target; the web app's mode; how environment reaches host processes, given `dotnet run` reads no `.env` and nothing creates `apps/web/.env.local`; readiness waits before Phase 11's `/readyz`; stale-`.env` detection; re-run and stop behaviour; whether its seed step keeps `make seed`'s wait on every default-profile service and both Keycloak realms; and what it prints, including the bilingual tenant's second-locale URLs | The reviews differ on attached versus detached processes; both reject a destructive reset, wait on both processes, keep re-runs idempotent and have CI reuse the entrypoint | Detail: the `Makefile` targets with help lines and a dated phase-doc statement; README § Quickstart, `scripts/seed.sh`'s closing output and the `local-dev-setup` and `seed-tenant` skills in the same packet; Infrastructure Standards § Healthchecks if the seed's gate narrows. No ADR | P02d-7 (with G44, whose job invokes the same entrypoint; if G44's harness moves earlier, this row moves with it) | [Accepted — 2026-10-11](phase-02d-delivery-log.md#p02d-7-demo-lifecycle): shared foreground lifecycle; implemented with both review rounds complete in Step 1 | -Each implementation step is committed after its checks, then receives two independent -review rounds from fresh agents. Confirmed findings are fixed and committed before -the next round or step. Reviewer assignments cover security/isolation, correctness, -concurrency, migration/rollback, tests that can fail, maintainability and corpus drift. -The available review models are used; this environment provides no Opus or Sonnet. +Gates that define one mechanism are answered against each other. Where their parts shape +different packets' code, the mechanism is split as +[Roadmap § Decision Timing](README.md#decision-timing) splits a gate: parts that block +the same packet close together in its pass, and a part that blocks a later packet closes +with or after the earlier one, never contradicting it: -Validation includes warnings-as-errors builds, backend formatting, architecture, -unit, contract and integration suites (real PostgreSQL as `learnstack_app`, zero -skips), a documentation link audit and migration-chain coverage. The pre-change run on -2026-09-14 passed **2,039** tests: 1,373 unit, 175 architecture, 490 integration and one -contract, with zero skips. This is a baseline, not validation of the accepted schema. -P02d-1 does not claim the later packets' writer, HTTP or browser evidence. +- G2 and G3 — the aggregate boundary decides where the state lives. +- G4 and G12 — the pin and the contract that resolves it. +- G7 — one ADR-0003 amendment — with G14's seed context in `P02d-2`. +- G8 and G9 — the Education chain's detail and the guards that hold it. +- G11, G14 and G15 — the writers pass. +- G16, G17 and G21 — the closed key set the PII answer rests on, and what a token may + point at. +- G18 and G19 — what the seed may publish. +- G22, G23 and G24 — the read internals. +- G25 through G31 — one public contract and one OpenAPI baseline. +- G32 through G37 — one hop; G33 and G34 share any ADR-0036 amendment. +- G39 and G40 — routing and strings. +- G44 and G45 — one stack entrypoint. ### Education content — minimum viable @@ -6837,7 +489,7 @@ What those documents already require of this phase's tables: - Each table's grants are written by the migration that creates it ([§ GRANT matrix](../standards/05-database.md#grant-matrix)). -The [accepted P02d-1 answers](#p02d-1-accepted-answers) close the aggregate and +The [accepted P02d-1 answers](phase-02d-delivery-log.md#p02d-1-accepted-answers) close the aggregate and satellite mapping, publication contract, exact content-type and taxonomy pins, stored locale identity, slug grammar, foreign-key boundaries, grants and default orders. The [Education spec](../modules/education/README.md) owns the detail; later writer, @@ -6875,7 +527,7 @@ and `Tenant.AddLocale` and `SetDefaultLocale` had no caller outside tests. requires locale rows to be written by their own command in their own transaction: the one raising `tenancy.locale.write` in [the Tenancy audit matrix](../modules/tenancy/audit.md). P02d-2 delivered those -commands and seeded locale configuration; see its [delivery record](#p02d-2-implementation-delivery-2026-10-02). +commands and seeded locale configuration; see its [delivery record](phase-02d-delivery-log.md#p02d-2-implementation-delivery-2026-10-02). Case variants of one tag are one locale ([ADR-0018](../decisions/0018-tenant-driven-customization-model.md)'s 2026-09-04 amendment), and how the shipped table spells a locale is in @@ -6981,7 +633,7 @@ Obligations already imposed: P02d-3 delivered **G12**'s cache contract, the loader/correctness contract (**G22**) and internal display fallback (**G24**) under the -[accepted gate answers](#accepted-gate-answers). P02d-4 delivered public response +[accepted gate answers](phase-02d-delivery-log.md#accepted-gate-answers). P02d-4 delivered public response parts; P02d-6 delivered page-state behavior. **The typed settings accessor** over `tenant_settings`, which Phase 02a left to its @@ -6995,12 +647,12 @@ the accessor selects organization-over-tenant whole-value precedence only for registrations that permit it; `branding.theme` stays tenant-wide. Seed writes run in their own process, so **G23** selects the uncached, ambient `ITenantSettingsAccessor` under the -[accepted typed settings contract](#typed-settings-and-display-fallback-contract). +[accepted typed settings contract](phase-02d-delivery-log.md#typed-settings-and-display-fallback-contract). ### Read API **P02d-4 implemented — 2026-10-04.** The -[accepted public contract](#public-routes-and-dto-contract) fixes four logical reads +[accepted public contract](phase-02d-delivery-log.md#public-routes-and-dto-contract) fixes four logical reads under `/api/v1/public`, each GET/HEAD: site bootstrap, course catalog, course detail with pageable outline, and lesson detail. The DTO allowlists, alternates and cursor codec are fixed before the first v1 snapshot; they expose no raw settings, schema, @@ -7018,12 +670,12 @@ rebind to a successor. The public prefix uses no-store on successes/errors, without validators/304 or a site/Education representation cache. Internal definition caching remains independent. -The [locale contract](#locale-and-display-applicability), -[pagination contract](#catalog-and-outline-continuation) and -[contract/SDK/CI plan](#openapi-sdk-and-required-check-plan) own the detailed decisions. +The [locale contract](phase-02d-delivery-log.md#locale-and-display-applicability), +[pagination contract](phase-02d-delivery-log.md#catalog-and-outline-continuation) and +[contract/SDK/CI plan](phase-02d-delivery-log.md#openapi-sdk-and-required-check-plan) own the detailed decisions. Production marker/table rows and structural guards now cover all four request types. Runtime verification and real app-role consumer query plans are recorded in -the [delivery record](#p02d-4-step-3-public-education-reads). P02d-5 owns trusted +the [delivery record](phase-02d-delivery-log.md#p02d-4-step-3-public-education-reads). P02d-5 owns trusted server transport; P02d-6 owns pages. ### Public renderer @@ -7082,7 +734,7 @@ language and direction follow the route's locale per layout's fixed `lang="en"` and platform `<title>` do not survive this phase. What evidence fails a build is **G43**; the language of fallback-resolved fields is **G24**. -The [Accepted P02d-6 package](#p02d-6-accepted-answers) closes UI strings/library +The [Accepted P02d-6 package](phase-02d-delivery-log.md#p02d-6-accepted-answers) closes UI strings/library (**G39**), routes/states/pagination/chrome (**G40**), bounded presentation (**G41**), theme injection (**G42**), accessibility (**G43**) and renderer tests (**G38 b,c**). Implementation and its passing proof remain separate from acceptance. @@ -7189,7 +841,7 @@ are hard-coded route segments. Lighthouse is neither an end-to-end suite nor WCAG conformance. - **Activation and required checks.** Each deferred job activates through the edits [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) - lists, with its skip condition per **G31**. P02d-1 [repairs and verifies](#step-3--packet-completion-2026-09-14) + lists, with its skip condition per **G31**. P02d-1 [repairs and verifies](phase-02d-delivery-log.md#step-3--packet-completion-2026-09-14) the two inherited required-check gaps — `backend integration (Testcontainers)` and the `meta` check under its current name — before the first Education migration merges, because @@ -7300,7 +952,7 @@ catalogued legs are not implemented (**G28**), and the tenant-branching check is committed snapshot and the SDK drift gate (**G31**), each activated through CONTRIBUTING's edits and shown able to fail, and the Lighthouse budget likewise if **G44** activates it in this phase; and the two inherited required-check edits, - [verified in P02d-1](#step-3--packet-completion-2026-09-14) before the first Education migration merges. + [verified in P02d-1](phase-02d-delivery-log.md#step-3--packet-completion-2026-09-14) before the first Education migration merges. **Server-rendering path** @@ -8023,297 +1675,3 @@ served by one backend binary, one `apps/web` application and one database — an - no catalogue row whose Phase names 02d is Registered or Awaiting backfill, and the standards index rows this phase changes agree with their documents; - the delivery record names the Phase 02b premises this phase moved, for `P02b-0`. - -## Delivery Record (P02d-1) - -**Decision pass — 2026-09-14.** Maintainer approval closes G1, G2, G3 (values and -publication/transition contract), G4, G5 (column), G6 (a), G7 (database controls and -factory derivation), G8, G9, G10 (order), and G26 (slug grammar), through the -[accepted answers](#p02d-1-accepted-answers). ADR-0048 is Accepted and ADR-0003 gains -Accepted Amendment 6. At this decision commit, the Education spec became design stable, -the module matrix list gained Education, and the four structural rules were Registered. -The following records distinguish that accepted design from its implementation and -verification. - -### Step 1 — Shared database controls (2026-09-14) - -The Tenancy and Audit forward migrations require exact organization scope for -INSERT while preserving reads, existing restrictive write policies and stored rows. -Tenancy's shared immutability function now supports natural-key rows without `id`. -The tenant-composite FK and organization-immutability catalogue rules are Implemented, -with planted violations and repaired positive controls over the applied schema. - -Behavioral proofs use authenticated `learnstack_app` connections. They cover both -existing tables, the tenant reporting hatch, pooled-session reuse after commit and -rollback, the no-id function and audit's append-only alternative. Disposable databases -keep test-only grants and control removal outside the shared schema. A populated -historical-schema test proves upgrade, exact Down restoration and reapplication. - -The full backend suite passes **2,082** cases: 1,373 unit, 175 architecture, -533 integration and one contract, with zero skips. Backend formatting and generated -SQL checks pass. The first full run exposed three legacy audit tests whose manually -declared intents omitted the organization their transaction announced; those fixtures -now copy the execution context exactly as `AuditLogBehavior` does. No production audit -exception or policy relaxation was needed. The localization overview and storage -examples also now distinguish accepted Education storage from later authoring behavior. - -Commit `807049a` completed two independent review rounds: three reviewers in round 1, -two fresh reviewers in round 2, covering security, migrations, runtime writers, proof -soundness and corpus consistency. Both rounds approved without findings or a required -fix commit. Each round independently reran 39 focused schema/migration cases; round 2 -also reran six architecture/corpus checks. All reported zero skips. - -### Step 2 — Education schema and isolation (2026-09-14) - -Both aggregate roots and their natural-key translations are implemented. Education's -fifth migration chain creates four tables with exact organization INSERT scope, -restrictive UPDATE/DELETE policies, immutable organization ids, tenant-composite FKs, -parent-scope checks and the accepted grants. The API and seeder resolve its context on -the existing ambient transaction. No command or endpoint is introduced here. - -The parent-mirror and Pattern A catalogue rules are Implemented. Their companions -plant absent subjects, weakened trigger controls, misplaced localized fields and -widened slug uniqueness. The applied schema sweeps and populated fixture include all -four Education tables. Domain tests constrain independent publication, locale -identity, exact pins, slug grammar and mutation atomicity. Actual app-role EF writes -prove graph persistence, contained audit capture and optimistic concurrency for -translation additions. Raw and filter-bypassing reads independently prove RLS. - -Disposable databases isolate tests that grant missing mutation/TEMP privileges or -remove the parent trigger to reach RLS and foreign keys separately. Parent checks are -tested on insertion and reparenting, against temporary-table shadowing, and while a -test barrier holds execution between the lookup and the FK. This distinguishes the -required lookup lock from the FK's later lock. Reversal removes dependent chains first; -reapplication then persists populated Education rows as `learnstack_app`. - -The full backend run passes **2,363** cases: 1,453 unit, 177 architecture, -732 integration and one contract, with zero skips. The migration model has no pending -changes; backend formatting, generated Up/Down SQL and the documentation link audit pass. PostgreSQL text -validation reuses the shared predicate instead of introducing an Education copy. - -Round 1 reviewed commit `e5b8187` with three independent reviewers. Domain/EF/audit -and security/migration reviews approved; the latter independently reran all twelve -parent-scope cases and the complete reverse/reapply case. The proof review found one -Major gap: Pattern A's parent-field detector omitted `description` and -`seo_description`, although Standards 08 explicitly forbids them on a parent. The -production schema contained neither field. Three new applied-schema companions -failed against the old detector (plain, locale-suffixed and SEO-prefixed descriptions), -then passed after both the schema and CLR/model predicates were corrected. Each -companion also removes its planted column and verifies the same detector is clean. -All 41 Education structural cases pass with zero skips after this repair. - -Round 2 reviewed the implementation and fix with three fresh reviewers. All approved -without further findings. Independent focused runs passed 281 security/persistence -cases and 129 structural/schema/migration cases, each with zero skips. The final full -run after the repair passes **2,366** cases: 1,453 unit, 177 architecture, 735 integration -and one contract, with zero skips. - -### Step 3 — Packet completion (2026-09-14) - -The approved GitHub repair was applied only to `main`'s `required_status_checks` -endpoint. A fresh full-protection API read at **2026-09-14 13:04 UTC** verified the -following snapshot, comparing check identities as a set because GitHub reordered the -entries. All five retain GitHub Actions `app_id: 15368`; `strict` remains `true`. - -```json -{ - "strict": true, - "checks": [ - { "context": "backend (build + unit + arch + contract)", "app_id": 15368 }, - { "context": "frontend (typecheck + lint + build + test)", "app_id": 15368 }, - { "context": "secret scan (leakwatch)", "app_id": 15368 }, - { "context": "meta (compose + commit hygiene + link audit)", "app_id": 15368 }, - { "context": "backend integration (Testcontainers)", "app_id": 15368 } - ] -} -``` - -Verification command: -`gh api repos/HodeTech/LearnStack/branches/main/protection/required_status_checks`. -The full before/after comparison also verified that every field outside -`required_status_checks` remained unchanged, including the separately approved -single-maintainer exceptions. CONTRIBUTING and both affected standards-index rows now -state the live setting. The later OpenAPI and Lighthouse gates retain their owning -packets and open decisions. - -The previous packet's `main` merge commit was merged into `development` without -rewriting history or switching branches. The tree before and after that merge was -identical, and `origin/main` is now an ancestor of the packet branch. This satisfies the -strict up-to-date requirement without changing the reviewed implementation. - -The final full backend run passes **2,366** cases with zero failures or skips; the -nonempty-run checker verifies all four assemblies. Fresh-schema, populated upgrade, -full reversal and app-role reapplication proofs pass. The manual aggregate review -also confirms the accepted roles match the applied foreign keys: Lesson is a separate -root with RESTRICT to Course; each plain satellite CASCADEs only to its own root. -Education commands and public-read eligibility remain the explicitly owned work of -P02d-2 and P02d-4. - -Informational coverage combines successful unit and integration runs by source -line/branch identity, excluding generated `obj` and EF migration files: Education -Domain is **235/235 lines and 80/80 branches (100%)**; Infrastructure is **139/152 -lines (91.45%) and 0/2 branches**. The uncovered lines and branches belong only to the -design-time factory, exercised separately by the EF CLI model and SQL checks. The -first solution-wide coverage attempt failed when a Coverlet-injected tracker type -could not be resolved by NetArchTest's IL/reflection sweep; it is not passing evidence. -The subsequent unit/integration coverage runs and uninstrumented **177-case** -architecture run pass. The local-test skill now records that working procedure; -no test or assertion was skipped or weakened. - -Backend formatting, all 177 architecture cases, 1,479 changed-Markdown relative -path/anchor checks, the tracked-file `docs/analysis/` residual scan and strict commit -hygiene pass. The two fresh-agent review rounds and PR required-check rollup -comparison are recorded below. - -Round 1 reviewed commit `7c50e01` with two fresh reviewers. The delivery reviewer -recomputed the TRX and coverage figures, checked the migration assertions and reran -the link audit without findings. The operational reviewer independently verified the -live protection setting and found one stale inherited-baseline paragraph still saying -integration was not required; it is corrected above. The author's PR preparation also -found that CONTRIBUTING and the commit skill prescribed headings different from -Standard 14. Both now follow its canonical description structure, with the skill's -existing isolation-risk disclosure retained. These are carrier corrections, not new -decisions. - -Round 2 reviewed `4d46560..ddb3454` with two fresh reviewers. Both approved without -further findings. They independently recomputed test/coverage figures, reran the -1,479-link audit, checked migration evidence, verified the live required-check names -and attribution against CI, and confirmed that the merge tree matches its first -parent and all unrelated protection fields remain unchanged. All three implementation -steps and their two review rounds are complete. - -#### PR verification (2026-09-14) - -[PR #22](https://github.com/HodeTech/LearnStack/pull/22), `development` → `main`, -passed [CI run 34848230938](https://github.com/HodeTech/LearnStack/actions/runs/34848230938) -on head `158f67da62dd6d8b4b542ec27ca0107c980d3ff5`. At **13:20 UTC**, a fresh live -protection read was compared with the commit's check runs. Each of the five required -contexts appeared exactly once with `app_id: 15368`, status `completed` and conclusion -`success`; none was satisfied by a skipped job or a legacy name. - -| Required context | Result | -|---|---| -| `backend (build + unit + arch + contract)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296320) | -| `frontend (typecheck + lint + build + test)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296248) | -| `secret scan (leakwatch)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989295976) | -| `meta (compose + commit hygiene + link audit)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296236) | -| `backend integration (Testcontainers)` | [Success](https://github.com/HodeTech/LearnStack/actions/runs/34848230938/job/103989296276) | - -The backend jobs reran the same **2,366** cases: 564 Docker integration, 171 HTTP -integration, 1,453 unit, 177 architecture and one contract, all with zero skips. -Both jobs' nonempty-run checks passed. - -The deferred OpenAPI and Lighthouse placeholders are outside this required set and -retain their later packet gates. The PR's current check rollup is the verification -source for any later head. P02d-1 is complete and the PR is ready for the maintainer's -detailed review. - -The PR's subsequent automated review identified three corpus corrections: a remaining -CODEOWNERS reference in the extension overview, omitted P02d-1 expansion metadata on -the migration-order rule, and an ambiguous Phase 04 revision paragraph. The first two -now match their current owners. The revision clarification records the shipped -Draft-only body guard and links the lifecycle question that ADR-0043 § 6 already leaves -with Phase 04; it does not introduce a successor-draft/history-storage design or change -the accepted versioned identity. These documentation corrections preserve P02d-1's -implementation and accepted scope. - - -#### Independent PR review follow-up (2026-09-14) - -The maintainer's review report was assessed against `35e54eb` and the accepted -P02d-1 answers. Two bounded follow-up steps address its verified findings without -adding production behavior or changing an accepted decision. - -**Step 1 — proofs (`c98bcb2`, `58afa6d`).** All eight Education field-level refusal -keys now have exact field and message-key assertions. Invalid summary controls cover -NUL and unpaired high/low surrogates while preserving prior content and the root's -version. Pattern A detects localized slug/locale suffixes in the applied schema and -uses separate probes for unmapped CLR fields and EF shadow columns. The old detector -fails six new controls; the repaired detector passes all 49 structural cases. -Application-role checks now cover the remaining constraint and organization-scope -connection boundaries, including both pool checkouts. - -Two fresh reviewers approved round 1. Round 2 used two different reviewers and found -that publication tests sampled invalid values without proving the database's complete -closed set. `58afa6d` compares the validated applied CHECK's whole predicate and value -set with each root's actual EF converter. Four planted constraints cover extra states -and an OR bypass on both roots; each is rejected by the comparison and passes after -repair. The reviewer who identified the gap verified the fix and closed the finding. - -**Step 2 — corpus reconciliation.** The result of every report item is recorded below; -items that proposed a new rule are distinguished from defects in the accepted scope. - -| Report item | Disposition | -|---|---| -| H1 | Corrected Database Standards' stale P02d-1 completion statement. | -| H2 | Exact field/reason assertions cover all eight Education keys, including dedicated Summary refusals. | -| H3; T1; T2 | Repaired slug/locale suffix detection; added applied, unmapped-CLR and shadow-column controls. | -| H4; Doc4 | Kept the accepted Education column inventory; aligned Standard 08's illustrative satellite with `summary` and clarified the inventory's scope in the test catalogue. Pattern A does not require every possible SEO field on every entity. Also corrected the stale publish-only collision wording: a draft reserves its slug on translation insertion. | -| H5 | Indexed existing Amendments 4–6. Preserved ADR-0003's Status under [the immutable-metadata rule](../standards/13-documentation.md#when-the-body-says-something-false). No ADR body or decision changed. | -| D1 | No nonblank rule exists for optional Summary in the accepted model. Whitespace acceptance is not a demonstrated defect; the proposed rejection policy was not introduced. | -| D2 | Canonicalization remains the shipped application responsibility, per [Localization architecture](../architecture/12-localization.md#tenant-locale-configuration). A new database locale-shape policy was not part of the accepted P02d-1 contract. | -| D3 | Parent scope and public eligibility are separate contracts. [ADR-0048](../decisions/0048-walking-skeleton-publication.md) assigns combined parent/deletion eligibility to reads; an active-parent creation rule was not silently added. | -| D4 | The private helper's `nameof(key)` names its actual parameter. Assigned-id helper reuse, parsing consolidation and cached read-only wrappers are optional refactors without a demonstrated correctness or workload defect; no production cleanup was bundled. | -| C1 | Corrected the ordering claim: fixtures and `make migrate` both honor Tenancy's dependencies; their independent Audit/Customization order need not match. | -| C2 | Documented the full-index versus live-only ordered-index purposes in the [Education performance section](../modules/education/README.md#performance-budget); retained the indexes. | -| C3 | Aligned the illustrative `created_at` DDL with the existing application-clock audit convention. No database timestamp fallback was added. | -| C4 | Compared actual converter output with the applied closed-set constraint, including the additional round-2 mutation controls above. | -| T3 | Added explicit authenticated/effective application-role and no-superuser/no-bypass assertions at the reported connection boundaries. | -| Doc1 | Not a defect: the earlier wording names the repository policy scan, not a private artifact. Its exact historical wording is preserved under the [delivery-record rule](../standards/13-documentation.md#doc-types). | -| Doc2 | Added glossary entries for publication, revision pin and parent organization mirror, with links to their existing authorities and from the module spec. | -| Doc3 | Kept normative slug grammar in [Standard 08](../standards/08-localization.md#education-slug-grammar) and executable checks in Standard 05; architecture and module prose link to them. The accepted-answer table remains its historical decision summary. | -| Doc5 | Added the current resource/action/scope matrix with no registered permissions or default grants, preserving the named owners of later command surfaces. | -| Doc6 | Distinguished Standard 14's canonical PR sections from the commit skill's existing risk and attribution supplements. | -| Doc7 | Stale at the reviewed head: the final-check checkbox was already checked for `35e54eb`. Later heads are verified through the live PR rollup. | - -The report's R1–R5 observations introduce no new packet defect. The -[isolation template and role model](../standards/05-database.md#tenant-owned-and-organization-scoped-tables), -[migration dependency and reversal rules](../standards/05-database.md#migrations), -[accepted database privileges](#p02d-1-accepted-answers) and -[Education scope/locale contract](../modules/education/README.md#data-model-and-invariants) -remain their authorities. No new production writer, cross-chain foreign key or -publication/deletion policy is inferred from those observations. - -The full Release backend run after the test fixes passes **2,381** cases: -**1,456 unit, 177 architecture, 747 integration and one contract**, with zero failures -or skips. The nonempty-run checker verifies every assembly. The earlier 2,366-case -and coverage figures above remain dated evidence for their original heads. This -follow-up changes no production source or migration. [PR #22](https://github.com/HodeTech/LearnStack/pull/22) -remains the current check-rollup and review surface. - -#### Merge and closeout (2026-09-14) - -[PR #22](https://github.com/HodeTech/LearnStack/pull/22) merged into `main` at -**20:22:17 UTC**, with final PR head `bc181702e379fec99da43015b2ee357ad772d6d1` -and merge commit `1d3a0f717523bebbf8c397ae9facba7c80eafae9`. The merge tree is -identical to the final PR head. `development` was fast-forwarded to that merge -commit without switching branches, rewriting history or changing file contents. - -- [x] P02d-1's accepted decision parts, all three implementation steps and their - two review rounds are complete, as recorded above. -- [x] The final review's three verified documentation findings are resolved in - `bc18170`: README delivery status, the Course/Lesson glossary distinction between - Phase 02d and Phase 05, and Phase 02b G19's stale module count. -- [x] The README refresh and the requested removal of mandatory commit coauthor - attribution (`dde8e0b`) are included in the merged head. -- [x] The final PR-head and merge-commit CI runs both completed successfully. - -| Verified revision | CI evidence | Result | -|---|---|---| -| Final PR head `bc18170` | [Run 34892449509](https://github.com/HodeTech/LearnStack/actions/runs/34892449509) | All five required jobs succeeded | -| `main` merge commit `1d3a0f7` | [Run 34892508893](https://github.com/HodeTech/LearnStack/actions/runs/34892508893) | All five required jobs succeeded | - -The live required-check list still has the five contexts recorded in Step 3, with -GitHub Actions `app_id: 15368` and `strict: true`. The merge run verifies **2,381 -backend tests**: 1,456 unit, 177 architecture, 171 Docker-free integration, -576 Docker integration and one contract, with zero failures or skips. The frontend, -meta and secret-scan jobs also pass. The OpenAPI and Lighthouse placeholders remain -outside the required set, with their existing P02d-4 and P02d-7 decision gates. -Both completed runs were verified at **20:25 UTC**. - -**P02d-1 is closed. Phase 02d remains in progress.** P02d-2 through P02d-7 have not -started. P02d-2 first resolves its writer, customization-contract, locale, branding, -seed-context and data-safety decisions, then implements the commands, audit wiring -and repeatable tenant-specific seed. The packet table and decision register above -own its exact scope and open gate parts. Public reads, rendering and the browser -demo remain the later packets' work; this merge does not complete those surfaces. diff --git a/docs/roadmap/phase-03-identity-admin.md b/docs/roadmap/phase-03-identity-admin.md index f943ec88..f13aee76 100644 --- a/docs/roadmap/phase-03-identity-admin.md +++ b/docs/roadmap/phase-03-identity-admin.md @@ -33,7 +33,7 @@ and permission-sensitive routes. Bootstrap seed mapper emission remains P02b-6; this phase extends that integration to the live identity/membership lifecycle. **P02b-6 SDK-boundary handoff — 2026-10-21.** The -[accepted package](phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) +[accepted package](phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) uses development Admin REST tooling without a runtime provider SDK. Phase 03 owns the first runtime identity-provider adapter and the [`Provider_SDK_Types_NotImportedOutsideInfrastructure`](../standards/21-architecture-tests-catalogue.md#awaiting-backfill) @@ -134,7 +134,7 @@ answered in the decision pass of the packet that ships it, per command, the decision returns to this phase. **Decision update — 2026-10-02.** The [accepted P02d-2 G17 -answer](phase-02d-walking-skeleton.md#p02d-2-accepted-answers) selects whole-value +answer](phase-02d-delivery-log.md#p02d-2-accepted-answers) selects whole-value `[PiiSensitive]` for generic `TenantSetting.Value` before its first writer; P02d-2 Step 2 implements both the marker and the bounded branding writer. This phase still owns identity-backed access, DSAR and the marketplace purpose/recipient boundary; a public diff --git a/docs/roadmap/phase-04-cms-media-pages.md b/docs/roadmap/phase-04-cms-media-pages.md index 32ab7102..9005d328 100644 --- a/docs/roadmap/phase-04-cms-media-pages.md +++ b/docs/roadmap/phase-04-cms-media-pages.md @@ -38,11 +38,11 @@ consumer: exact `next-intl` 4.14.9, server-first request configuration and app-l foundation and adds CMS/Studio message coverage; it does not reselect the library or own its initial installation. Tenant-authored content localization remains this phase's responsibility. The -[P02d-6 package](phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +[P02d-6 package](phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) records accepted page/status behavior; its -[Step 1 delivery record](phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[Step 1 delivery record](phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns foundation verification. Steps 2–4 deliver actual content pages and product -proofs; the [packet closeout](phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +proofs; the [packet closeout](phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records passing manual accessibility smoke. ## Scope @@ -113,7 +113,7 @@ Also in scope: - Whether a customization change owes an integration event, per [the Customization spec § Integration-event catalogue](../modules/customization/README.md#integration-event-catalogue). -### Content-type quota accounting — accepted (2026-10-19) +### Content-type quota accounting **Accepted — 2026-10-19, @cemil.** The maintainer approved the accounting below before implementation. The existing registration command did not enforce @@ -231,7 +231,7 @@ one thing a per-table constraint cannot do. never resolved by picking a winner at render time. > **Education mapping decided.** Course and Lesson translation rows reserve their -> slugs at insertion. [G11](phase-02d-walking-skeleton.md#p02d-2-accepted-answers) +> slugs at insertion. [G11](phase-02d-delivery-log.md#p02d-2-accepted-answers) > names the reporting commands and error mapping below; this phase names its CMS > writer before implementation. @@ -478,7 +478,7 @@ describes. attempts all three and the database rejects each, connected as `learnstack_app`. The reporting command returns `Result.Fail(business_rule_violation, …)` with the disclosure rules above. For courses, - the accepted [G11 answer](phase-02d-walking-skeleton.md#p02d-2-accepted-answers) + the accepted [G11 answer](phase-02d-delivery-log.md#p02d-2-accepted-answers) selects `AddCourseTranslationCommand` (and `AddLessonTranslationCommand` for lessons), mapping named localized-slug constraints to `business_rule_violation` on insertion. Verify those command-level refusals after P02d-2 implementation; diff --git a/docs/roadmap/phase-05-education-learning-content.md b/docs/roadmap/phase-05-education-learning-content.md index f4c99d1b..45ff4ae2 100644 --- a/docs/roadmap/phase-05-education-learning-content.md +++ b/docs/roadmap/phase-05-education-learning-content.md @@ -66,7 +66,7 @@ browser/Lighthouse proof. The [Phase 02d delivery record](phase-02d-walking-skel owns current implementation, CI enforcement and phase-exit evidence. Phase 05 does not re-create these. Phase 02d's -[delivery status](phase-02d-walking-skeleton.md#delivery-record-p02d-1) distinguishes +[delivery status](phase-02d-delivery-log.md#delivery-record-p02d-1) distinguishes accepted design from shipped implementation. This phase's decision pass designs the move from independent lessons referencing courses to course versions and modules, and from translated inline bodies to lesson items. It must preserve course and @@ -85,7 +85,7 @@ Each change follows [Database Standards § Migrations](../standards/05-database. | `[TenantOwned]` markers, EF query filters, RLS policies | The same layers on every new table, with no exception | **Accepted renderer inheritance — 2026-10-09; implemented by P02d-6.** -The [P02d-6 package](phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +The [P02d-6 package](phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) fixes exact-locale content, both opaque pagination surfaces, inert plain-text presentation and distinct restricted/empty/unavailable states. Its local 307→404 status-route chain changes the browser URL; known content-call failures use diff --git a/docs/roadmap/phase-06-renderer-admin-studio.md b/docs/roadmap/phase-06-renderer-admin-studio.md index b7008ae6..a8c0ed40 100644 --- a/docs/roadmap/phase-06-renderer-admin-studio.md +++ b/docs/roadmap/phase-06-renderer-admin-studio.md @@ -23,9 +23,9 @@ and a non-developer tenant admin can maintain it. ### What Phase 02d supplies Rows identify P02d-6 scope merged through PR #27; its -[merge closeout](phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) +[merge closeout](phase-02d-delivery-log.md#p02d-6-merge-and-closeout-2026-10-10) records final verification. P02d-7's -[delivery record](phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) +[delivery record](phase-02d-delivery-log.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) records the narrow browser/audit proof; the canonical Phase 02d closeout records its CI enforcement and phase-exit state. @@ -44,7 +44,7 @@ app-local `src/i18n/messages/<locale>/<namespace>.json` and complete `en`/`tr` renderer UI. It preserves shared verified request admission, exact content locale, whole-catalogue UI fallback and missing-key failure; the SDK owns no translations. -The [P02d-6 package](phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +The [P02d-6 package](phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) uses plain same-host anchors, opaque signed-target pagination, safe four-color injection and local 307→404 navigation to `/{locale}/status/not-found`. The URL changes; known content-call failures are translated HTTP 200 noindex states. diff --git a/docs/roadmap/phase-07-enrollment-learner-portal.md b/docs/roadmap/phase-07-enrollment-learner-portal.md index 8ee5efe2..2d2c0531 100644 --- a/docs/roadmap/phase-07-enrollment-learner-portal.md +++ b/docs/roadmap/phase-07-enrollment-learner-portal.md @@ -50,7 +50,7 @@ feature UI namespaces through the Phase 06 portal shell, preserving complete supported catalogues and checked ICU/callsite coverage. General UI identifiers remain distinct from backend `lockey_*`; the SDK supplies no translations. -The [P02d-6 package](phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +The [P02d-6 package](phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) selects anonymous page/status composition and shared verified public admission. Its UI fallback changes no content locale or access policy. Its local 307→404 URL change and HTTP 200 noindex content-failure states do not decide authenticated diff --git a/docs/roadmap/phase-08a-assessment-notifications.md b/docs/roadmap/phase-08a-assessment-notifications.md index dbe7d446..c49d07cd 100644 --- a/docs/roadmap/phase-08a-assessment-notifications.md +++ b/docs/roadmap/phase-08a-assessment-notifications.md @@ -182,7 +182,7 @@ Additions to the existing host, not a new one: Typed transactional submission, exact tenant/org restoration, profile/capacity admission and the replacement BackgroundJob_* obligations are accepted by -[P02b-4](phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15). +[P02b-4](phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15). Their implementation/proofs remain pending; this phase depends on that completed foundation and adds no runner. diff --git a/docs/roadmap/phase-11-production-hardening.md b/docs/roadmap/phase-11-production-hardening.md index 301747b4..e362a221 100644 --- a/docs/roadmap/phase-11-production-hardening.md +++ b/docs/roadmap/phase-11-production-hardening.md @@ -360,7 +360,7 @@ not a request to add an unused module, adapter or port. new decision explicitly changes it. - **Subject capacity.** [ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md) is Accepted — 2026-10-20. Implementation and local runtime/exported proofs are - delivered; the [implementation record](phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) + delivered; the [implementation record](phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. Its 4096 retained keys are shared across tenants, so occupied live slots can refuse other valid subjects. Quota/capacity use 429 with diff --git a/docs/standards/03-frontend-coding.md b/docs/standards/03-frontend-coding.md index f8954c5f..4b7f52d7 100644 --- a/docs/standards/03-frontend-coding.md +++ b/docs/standards/03-frontend-coding.md @@ -130,7 +130,7 @@ export function CourseCard({ course, onEnroll }: CourseCardProps) { P02d-2 accepts and implements G16's theme value grammar; P02d-4 delivers its public projection. [Tenant Branding](07-frontend-architecture.md#tenant-branding) owns that contract. P02d-6 Step 1 implements G42's atomic server-rendered color injection; -the [delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +the [delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns verification and the remaining product/manual accessibility proof boundary. ## Server Actions diff --git a/docs/standards/04-api-design.md b/docs/standards/04-api-design.md index 6862fe1b..841ebb44 100644 --- a/docs/standards/04-api-design.md +++ b/docs/standards/04-api-design.md @@ -12,7 +12,7 @@ P02b-5 Step 4 activates the closed HTTP boundary; its delivery record owns proof and review status. Subject-registry capacity, cleanup and refusal semantics derive from [ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md), Accepted — 2026-10-20. Implementation has local runtime/exported proofs; the -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. REST conventions for LearnStack public and admin APIs. @@ -46,7 +46,7 @@ read pairs; Step 4 delivers the contract/SDK controls. Institution reads use `/api/v1/public`, separate from future authoring ID routes: `/site`, `/courses`, `/courses/{slug}` and `/courses/{slug}/lessons/{lessonSlug}`. Each has explicit GET and HEAD; Education routes require query locale. Response/continuation -contracts are the [accepted packet](../roadmap/phase-02d-walking-skeleton.md#public-routes-and-dto-contract) +contracts are the [accepted packet](../roadmap/phase-02d-delivery-log.md#public-routes-and-dto-contract) under [ADR-0052](../decisions/0052-anonymous-public-read-boundary.md). ## Versioning @@ -318,7 +318,7 @@ Rules: and makes no confidentiality, MAC or snapshot promise. Invalid encoding/shape/ scope is `400 validation_failed` naming the sent cursor parameter. Forward-only PageInfo keeps previousCursor null and hasPrevious false. - [The accepted pagination contract](../roadmap/phase-02d-walking-skeleton.md#catalog-and-outline-continuation) + [The accepted pagination contract](../roadmap/phase-02d-delivery-log.md#catalog-and-outline-continuation) owns exact payloads, bounds and seek behavior; P02d-4 Step 3 implements the codec. - Offset pagination is allowed only for admin-bounded lists (≤ 10k total rows). @@ -503,7 +503,7 @@ SDK has no branch for. [Standards 07 § SDK](07-frontend-architecture.md) owns how and when. - Breaking OpenAPI changes fail the always-running `openapi diff` job under ADR-0024. Required-check registration is recorded only after a real run and - API read-back, in [the packet delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci). + API read-back, in [the packet delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci). **G31 delivered by Step 4.** `backend/openapi/v1.json` is the sole v1 snapshot, compared against the production served document. Non-empty eight-operation and @@ -513,7 +513,7 @@ companions implement representable ADR-0024 rules; runtime tests own validator a status meaning absent from the document. Bootstrap builds and serves the verified base composition; only a base without a snapshot and without v1 operations qualifies. Verification/read failures and deleted head snapshots fail closed. -[The accepted contract/CI plan](../roadmap/phase-02d-walking-skeleton.md#openapi-sdk-and-required-check-plan) +[The accepted contract/CI plan](../roadmap/phase-02d-delivery-log.md#openapi-sdk-and-required-check-plan) owns pins, overrides and the six-check rollout; the delivery record owns execution. ## Request and Response Limits diff --git a/docs/standards/05-database.md b/docs/standards/05-database.md index 93402d0c..48b4240d 100644 --- a/docs/standards/05-database.md +++ b/docs/standards/05-database.md @@ -49,7 +49,7 @@ PostgreSQL schema, EF Core, and migration conventions. - One `DbContext` per module (not one global). - Schema migrations live with the owning module. -With [P02d-1 complete](../roadmap/phase-02d-walking-skeleton.md#delivery-record-p02d-1), +With [P02d-1 complete](../roadmap/phase-02d-delivery-log.md#delivery-record-p02d-1), five migration chains exist: Tenancy, Platform, Customization, Audit and Education. P02b-3 Step 1 brings their inventory to twenty-three data tables and five migration-history tables. @@ -1046,7 +1046,7 @@ privileges implicitly. ADR-0046 accepts the two P02b-2 cells above. Step 1 implements their migrations and exact-grant proofs; both independent review rounds are complete in the -[delivery record](../roadmap/phase-02b-events-auth.md#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12). +[delivery record](../roadmap/phase-02b-delivery-log.md#p02b-2-step-1--decision-schema-and-confined-composition-2026-10-12). Outbox status grants land in the Platform chain. The audit INSERT grant lands in a new Audit-chain migration after `audit_log` exists, never in initdb. No audit SELECT/UPDATE/DELETE, business access or role membership is @@ -1447,7 +1447,7 @@ fenced transitions and atomic terminal auditing; both review rounds passed. Step 3 implements hosted execution and metrics; both independent review rounds are complete. Step 4 enforcement and local closeout are complete; all four steps completed both -independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. Existing migrations remain immutable; a new Platform-chain migration replaces free-form legacy `last_error` with `migration:legacy:redacted` before its byte CHECK. @@ -1618,7 +1618,7 @@ and its MUST audit atomically. See **P02b-3 Steps 1–4 deliver the shared schema, durable acceptance, inbox claims, business completion and independent subscriber scheduling.** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) -and the [accepted P02b-3 package](../roadmap/phase-02b-events-auth.md#accepted-storage-and-authority-details) +and the [accepted P02b-3 package](../roadmap/phase-02b-delivery-log.md#accepted-storage-and-authority-details) define transport-owned deduplication and independent subscription delivery. `event_deliveries` retains one immutable envelope copy per `(tenant_id, subscription_id, event_id)`; `inbox_messages` retains that tuple's @@ -4042,9 +4042,9 @@ one-millisecond internal expiration interval must be verified before workers sta Version/guard/ACL failure refuses the explicit storage bootstrap before worker construction. Contract-only registration remains lazy and activates no worker. -The [Step 2 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-2--storage-and-guarded-vendor-bootstrap-2026-10-16) +The [Step 2 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-2--storage-and-guarded-vendor-bootstrap-2026-10-16) owns delivery status: Step 2 implements idle-session settings and source/reset -qualification. The [Step 4 continuation](../roadmap/phase-02b-events-auth.md#source-lifetime-and-facade-continuation-2026-10-16) +qualification. The [Step 4 continuation](../roadmap/phase-02b-delivery-log.md#source-lifetime-and-facade-continuation-2026-10-16) owns current runtime/source qualification and full-step review dispositions. Step 4 is locally complete after both full review rounds and verified corrections. Later SQL lanes require fresh capacity qualification; Step 9 owns full @@ -4140,14 +4140,14 @@ Its app checkpoint follows positive main/auxiliary/callback cleanup on the same invocation source owner, with old bindings permanently closed. One prebound checkpoint slot retains actual work and cancellation cleanup; a failed cleanup cannot start another scope. This sequential phase adds no simultaneous main or -auxiliary checkout. The [Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) +auxiliary checkout. The [Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) owns passing local qualification, both completed full review rounds and verified corrections. These are current acquisition inventories under Accepted ADR-0047, not deployment-wide PostgreSQL capacity guarantees. Independent progress at each supported boundary has source-specific qualification in the -[Step 9 record](../roadmap/phase-02b-events-auth.md#combined-physical-capacity-qualification). +[Step 9 record](../roadmap/phase-02b-delivery-log.md#combined-physical-capacity-qualification). The combined real-owner proof at the default52 configuration complements the complete ledger and existing topology/retention controls; it does not claim52 simultaneously busy connections or a tight empirical minimum. diff --git a/docs/standards/06-testing.md b/docs/standards/06-testing.md index 1992be40..908d2d3b 100644 --- a/docs/standards/06-testing.md +++ b/docs/standards/06-testing.md @@ -11,7 +11,7 @@ The seeded browser/audit proof derives from Native admission, stock-browser fallback and HMR proof controls derive from [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md). UI localization controls derive from [ADR-0027](../decisions/0027-frontend-i18n.md) -and the [Accepted P02d-6 package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09). +and the [Accepted P02d-6 package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09). Test pyramid, conventions, and what every change must cover. @@ -168,7 +168,7 @@ writes only literal `core`; it never restores a pipe. The unchanged child fixtur still qualifies its own preconditions and actual native exits. The required aggregate checks every producer outcome and matching complete artifacts. Offline provisioning/launcher controls run in `meta`. The -[CI acceptance and implementation record](../roadmap/phase-02b-events-auth.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) +[CI acceptance and implementation record](../roadmap/phase-02b-delivery-log.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) owns actual review and hosted qualification; local controls do not establish VM ownership, no-dump proof or either execution's whole-job budget fit. @@ -208,9 +208,13 @@ siblings must belong to the current run attempt. Odd/even attempts select the two deterministic layouts; final qualification requires genuinely distinct co-membership, including SharedSchema methods, on the same source, plan, toolchain and complete case population. Plan, algorithm or fixture-lifetime -changes require both layouts. Normal future pushes execute one complete -assignment. The -[CI follow-up record](../roadmap/phase-02b-events-auth.md#adr-0063-step-3--workflow-and-aggregate-enforcement-2026-10-19) +changes require both layouts. Complete this qualification before merging. +GitHub can omit a merged same-repository PR from a run's REST projection; the +aggregate refuses that missing identity even after a complete rerun. Further +PR qualification uses an open follow-up PR, without weakening identity checks +or combining receipts from different attempts. Normal future pushes execute +one complete assignment. The +[CI follow-up record](../roadmap/phase-02b-delivery-log.md#adr-0063-step-3--workflow-and-aggregate-enforcement-2026-10-19) owns actual hosted fit and the two complete attempts; local controls do not establish either. @@ -239,14 +243,14 @@ and were read as running. generated GET wrappers. Pinned CLI fixtures cover ADR-0024 compatibility, with explicit companions for the tool's open-enum gaps. Snapshot admission controls fail closed on missing/deleted snapshots and failed base verification. - [The packet record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) + [The packet record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) records executed counts, reviews and the live required-check rollout. ### End-to-End Tests P02d-7 Step 3 implements the narrow seeded catalog → course → lesson browser proof over the running production API/native renderer. Its -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) records the passing local nine-page walkthrough and 27 Lighthouse audits; both independent Step 3 reviews are complete. The packet's Step 4 record owns real CI receipts and required-check activation; local proof alone does not establish @@ -319,7 +323,7 @@ Controls must fail for omitted cleanup, early split leaks followed by large outp disabled trust verification, stale listeners and unclosed upgrades. Healthy builds receive nonempty private configuration; a real public-only Client Component and a successfully built leaking mutant make emitted-asset containment falsifiable. -The [remediation record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-3--fixture-reliability-and-containment) +The [remediation record](../roadmap/phase-02d-delivery-log.md#remediation-step-3--fixture-reliability-and-containment) owns execution/review evidence. These are socket/build controls, not P7 browser or Lighthouse delivery. @@ -350,7 +354,7 @@ so its catch-all cannot shadow product routes. Preserve `learnstack_app`, RLS, read-only transactions, native HTTPS, closed hop headers and fixture containment. Step 4 adds deterministic overlapping host/locale lanes, authored RTL content, whole-theme fallback, next-document freshness and one-shot content-failure modes. -The [delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +The [delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) owns execution, review evidence and the completed manual accessibility smoke. Assert visible HTML/DOM separately from Flight: status, `lang`/`dir`, headings, @@ -365,7 +369,7 @@ documents cost two API calls, fixed status/scaffold documents one and followed missing documents three. Metadata/layout/page/UI reuse adds no bootstrap; the next document re-reads. HEAD/RSC/prefetch and Flight fallback need separately proven counts. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) records passing production replacement proofs; both independent Step 3 review rounds are complete. These HTTP/HTML/RSC proofs are not browser E2E evidence. diff --git a/docs/standards/07-frontend-architecture.md b/docs/standards/07-frontend-architecture.md index 3cd5cd05..73032496 100644 --- a/docs/standards/07-frontend-architecture.md +++ b/docs/standards/07-frontend-architecture.md @@ -15,7 +15,7 @@ Public UI localization derives from [ADR-0027](../decisions/0027-frontend-i18n.m single-bootstrap ownership derives from [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md); page composition follows the -[Accepted P02d-6 package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09). +[Accepted P02d-6 package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09). Next.js App Router layout, tenant resolution, SDK shape, and runtime concerns for the tenant-facing `apps/web` application in *this* repository. See @@ -103,7 +103,7 @@ flowchart TD - The approved bootstrap creates no edge tenant registry or resolver endpoint. - ADR-0053 accepts native ingress provenance, Node middleware bootstrap and the server-only configured caller in P02d-5. The - [accepted entry matrix](../roadmap/phase-02d-walking-skeleton.md#public-entry-matrix) + [accepted entry matrix](../roadmap/phase-02d-delivery-log.md#public-entry-matrix) owns membership-first redirects. Anonymous entry neither sets nor uses cookies. P02d-5 Steps 1–3 deliver native ingress, visitor budgets, Node bootstrap/entry and the configured caller; Step 4 implements frontend fences and real-API @@ -115,7 +115,7 @@ flowchart TD **ADR-0054 native/URL controls complete — 2026-10-09; both reviews passed.** Remediation Step 2 implements these controls. Concrete execution and review -evidence belongs to the [delivery record](../roadmap/phase-02d-walking-skeleton.md#remediation-step-2--native-ingress-and-url-boundary). +evidence belongs to the [delivery record](../roadmap/phase-02d-delivery-log.md#remediation-step-2--native-ingress-and-url-boundary). - Admit GET/HEAD on every HTTP path reaching the native listener callback before Next dispatch, including matcher-exempt health/assets and exact scaffolds. @@ -133,7 +133,7 @@ evidence belongs to the [delivery record](../roadmap/phase-02d-walking-skeleton. - Redirects retain inert query values, duplicates and ordering; equivalent percent encoding is allowed. Only the verified live host, accepted HTTPS port and local path select the destination. Membership-first precedence and redirect statuses - remain those of the [entry matrix](../roadmap/phase-02d-walking-skeleton.md#public-entry-matrix). + remain those of the [entry matrix](../roadmap/phase-02d-delivery-log.md#public-entry-matrix). ## Request-Local Bootstrap Admission @@ -159,7 +159,7 @@ one for a completed fixed status/scaffold document and three for a followed missing-detail chain. HEAD/RSC/prefetch and Flight fallback require separately proven counts. Metadata/layout/page/UI reuse adds no bootstrap. Visitor/peer limits remain API-call budgets. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns passing production replacement proof, completed reviews and verified fixes; the five new catalogue rules are Implemented. [Standards 09](09-error-handling.md#public-page-status-and-recovery) owns refusal @@ -230,7 +230,7 @@ explains the import guard. Vitest aliases the marker only in server tests. The P5 production fixture proves a real client import fails with the marker diagnostic before rebuilding a clean server route against the real API. -The [accepted contract/CI plan](../roadmap/phase-02d-walking-skeleton.md#openapi-sdk-and-required-check-plan) +The [accepted contract/CI plan](../roadmap/phase-02d-delivery-log.md#openapi-sdk-and-required-check-plan) owns the source, pin, diff policy, bootstrap exception and required-check rollout. ## Auth @@ -283,7 +283,7 @@ Disable local Server Component HMR caching. P02d-6 Step 1 implements document loaders, chrome, state views and atomic theme injection. Step 2 adds catalog/course views; Step 3 adds ordered lesson views. Step 4 adds concurrent host/locale, theme, freshness and failure-state product proofs. The -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) owns verification, completed reviews and passing manual accessibility evidence. P5 delivers the dynamic layout, transport and source/runtime proofs. Test-owned production routes exercise the real API. P6 product modes copy the actual public diff --git a/docs/standards/08-localization.md b/docs/standards/08-localization.md index f43dbfb2..6863930e 100644 --- a/docs/standards/08-localization.md +++ b/docs/standards/08-localization.md @@ -45,7 +45,7 @@ fallback remains the delivered P02d-3 contract; language attributes are P02d-6. **P02d-6 Step 1 UI foundation implemented — 2026-10-10.** [ADR-0027](../decisions/0027-frontend-i18n.md) supplies next-intl and one app-local catalogue home, with UI-language fallback separate from content admission. The -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns foundation validation. Step 2 adds catalog/course views with actual resolved label languages and exact-locale metadata; Step 3 adds ordered lesson fields and lesson metadata with eligible translated course/lesson slugs. @@ -66,7 +66,7 @@ Rules: - Custom domains resolve tenant first; locale resolves from the path. **Accepted P02d-5 entry policy — 2026-10-08.** -[The entry matrix](../roadmap/phase-02d-walking-skeleton.md#public-entry-matrix) owns +[The entry matrix](../roadmap/phase-02d-delivery-log.md#public-entry-matrix) owns Education path admission: bootstrap first, then bounded LocaleTag canonicalization and enabled membership before any shorthand/scaffold rule. Enabled noncanonical prefixes get `308`; default/locale-root entry gets `307`. Unsupported prefixes get @@ -167,7 +167,7 @@ omitted rather than rendered dead. A slug collision is refused when the translation is inserted; its writing command returns `Result.Fail(business_rule_violation, …)`. The accepted 2026-10-02 -[P02d-2 G11 answer](../roadmap/phase-02d-walking-skeleton.md#p02d-2-accepted-answers) +[P02d-2 G11 answer](../roadmap/phase-02d-delivery-log.md#p02d-2-accepted-answers) selects `AddCourseTranslationCommand` and `AddLessonTranslationCommand` for Education, mapping their named localized-slug uniqueness constraints at insertion. Publication does not reserve or newly collide a slug. P02d-2 Step 3 implements the mapping and @@ -216,7 +216,7 @@ applying the fallback chain. with an explicit two-letter territory and no script, variant or extension to discard. Omit unrepresentable values; never guess a territory. HTML language, URL and hreflang retain BCP-47. The - [approved G40 addendum](../roadmap/phase-02d-walking-skeleton.md#p02d-6-systematic-review-decision-package-2026-10-10) + [approved G40 addendum](../roadmap/phase-02d-delivery-log.md#p02d-6-systematic-review-decision-package-2026-10-10) records this bounded projection and the optional-property tradeoff. ## Formatting @@ -293,7 +293,7 @@ Enabled but untranslated means empty catalog or masked detail `404`, not fallbac none; bootstrap returns `404`. Invalid stored locale/default configuration is `503 dependency_unavailable`, never a synthesized default. URL-segment redirects are delivered by P02d-5 Step 3 under G6(c). ADR-0052 and the -[accepted locale contract](../roadmap/phase-02d-walking-skeleton.md#locale-and-display-applicability) +[accepted locale contract](../roadmap/phase-02d-delivery-log.md#locale-and-display-applicability) record the authority; no platform locale registry is introduced. **G13 reader implemented in P02d-2 Step 1 — 2026-10-02.** The @@ -320,7 +320,7 @@ Step 1 implements direction selection and labelled fallback chrome; Step 2 proves an empty admitted Arabic catalog in production. Step 3 adds per-field label direction. Step 4 adds eligible authored RTL content with concurrent host/locale HTML/Flight proofs. Passing manual accessibility is recorded in -the [delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout). +the [delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout). ## Admin Studio UI diff --git a/docs/standards/09-error-handling.md b/docs/standards/09-error-handling.md index 72365dfa..ad4cafae 100644 --- a/docs/standards/09-error-handling.md +++ b/docs/standards/09-error-handling.md @@ -7,7 +7,7 @@ Public-read additions derive from Tenant API authentication additions derive from [ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md). Public UI message mapping derives from [ADR-0027](../decisions/0027-frontend-i18n.md) -and the [Accepted P02d-6 package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09). +and the [Accepted P02d-6 package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09). Bootstrap response ownership and renderer Retry-After qualification derive from [ADR-0055](../decisions/0055-public-renderer-bootstrap-failures.md). Delivery/recovery additions derive from @@ -17,7 +17,7 @@ Background-job policy derives from [ADR-0061](../decisions/0061-known-external-job-failure-policy.md). Hard-limit refusal follows [ADR-0021](../decisions/0021-feature-based-entitlement.md), [ADR-0045](../decisions/0045-entitlement-and-feature-flag-socket.md) and the -[accepted quota accounting](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting--accepted-2026-10-19). +[accepted quota accounting](../roadmap/phase-04-cms-media-pages.md#content-type-quota-accounting). How LearnStack represents, propagates, surfaces, and recovers from failures. @@ -454,9 +454,9 @@ outcomes mapped to the bounded unavailable state. It does not authorize arbitrar Problem Details keys, titles, field errors or parameters as UI lookup identifiers or visible copy. This public-page mapping is Accepted — 2026-10-09; P02d-6 Steps 1–3 implement it, with evidence in the -[Step 1](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation), -[Step 2](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-2-catalog-and-course-pages) -and [Step 3](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-3-ordered-lesson-presentation) +[Step 1](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation), +[Step 2](../roadmap/phase-02d-delivery-log.md#p02d-6-step-2-catalog-and-course-pages) +and [Step 3](../roadmap/phase-02d-delivery-log.md#p02d-6-step-3-ordered-lesson-presentation) delivery records. ### Public Page Status and Recovery @@ -495,7 +495,7 @@ as integer delta-seconds from zero through sixty inclusive. Preserve eligible values; omit malformed/date/negative/out-of-range values without clamping or inventing a retry. This qualifies renderer forwarding only; the API's selected refusal metadata and accounting remain unchanged. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) records passing exact-wire failure/lifecycle proofs, both independent review rounds and focused fix verification. @@ -576,7 +576,7 @@ exception types (`LiveKit.NET.LiveKitException`, `Stripe.StripeException`, ## Background Jobs [Accepted ADR-0047](../decisions/0047-transactional-background-job-runtime.md#attempts-terminal-audit-and-diagnostics) -owns the job failure policy. The [P02b-4 delivery records](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +owns the job failure policy. The [P02b-4 delivery records](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) own the delivered implementation; the [phase status](../roadmap/phase-02b-events-auth.md) owns remaining hosted qualification. @@ -603,7 +603,7 @@ full enforcement. Acceptance supplies no completed runtime proof. ## Outbox **Accepted ADR-0046; P02b-2 producer runtime and enforcement complete and merged.** -All four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +All four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. P02b-3 Steps 1–4 implement durable acceptance, shared inbox, independent subscriber execution/retries and terminal audit. Step 5 activates both real default diff --git a/docs/standards/10-observability.md b/docs/standards/10-observability.md index 1cecdaa9..9820a434 100644 --- a/docs/standards/10-observability.md +++ b/docs/standards/10-observability.md @@ -9,7 +9,7 @@ Delivery/recovery additions derive from Accepted job-lifecycle observation derives from [ADR-0059](../decisions/0059-owned-hangfire-server-generations.md). P02b-4 is implemented and merged; its -[merge closeout](../roadmap/phase-02b-events-auth.md#p02b-4-merge-and-closeout-2026-10-19) +[merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-4-merge-and-closeout-2026-10-19) owns final qualification. Phase 11 owns production activation. Tenant-authentication diagnostics derive from [ADR-0064](../decisions/0064-tenant-api-authentication-boundary.md); @@ -17,12 +17,12 @@ P02b-5 Steps 1 and 3 implement the components; Step 4 activates the HTTP boundar Bounded assertion diagnostics and process-wide outbound metric projection derive from [ADR-0065](../decisions/0065-bounded-tenant-assertion-diagnostics.md); its audit-budget implementation and local proofs are delivered in the -[remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20). +[remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20). Acceptance was committed before that implementation; production sizing remains open. Subject-admission refusal and cleanup-fault signals derive from [ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md), Accepted — 2026-10-20. Their implementation and local exported proofs are delivered; the -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. Three signals — logs, traces, metrics — bound by a single correlation id. Everything we ship is observable from day one. @@ -276,7 +276,7 @@ The actual singleton-budget suppression path is also exported through the root's `LearnStack.Api` meter subscription. Its test waits for the correlated Warning while the logger owner is alive: a metrics flush is not a log-delivery receipt. The ordinary-destination controls are implemented; the -[P02b-5 merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) +[P02b-5 merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns their current qualification status. Step 3 implements recorder/claimless/quota diagnostics; Steps 4–5 qualify the @@ -438,13 +438,13 @@ backend treat business rejections as system failures. Outbox metrics above are implemented in P02b-2 Step 3 under ADR-0046; both independent review rounds are complete. The subscriber/inbox inventory is -accepted by the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13); +accepted by the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13); Step 4 implements it with real worker, finite-label and memory-only observation proofs. P02b-4 Step 9 implements the five observable and three stage families above under [ADR-0047](../decisions/0047-transactional-background-job-runtime.md#lifecycle-and-observation). Stage, tracing, lease-loss and control-path instrumentation are implemented with source-specific qualification; the -[Step 9 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +[Step 9 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) owns those receipts and full-regression, review, packet-closeout and remaining PR/CI qualification status. `event_type` comes only from the finite declared registry plus fixed @@ -467,7 +467,7 @@ Heartbeat advances after actual bounded loop work, including empty polls. Gauges read immutable memory snapshots and perform no SQL. Refresh follows completed iterations, targets 5 s idle and becomes stale at the approved 45 s health bound. Failure retains the prior snapshot and reports unhealthy. The -[P02b-2 bounds](../roadmap/phase-02b-events-auth.md#runtime-bounds-and-observation) +[P02b-2 bounds](../roadmap/phase-02b-delivery-log.md#runtime-bounds-and-observation) own deadlines and task limits. Dispatcher-owned logs/spans use validated correlation and bounded outcomes, without exception text/stacks, payload, raw stored type or connection data. P02b-3 Steps 3–4 minimize transport-owned @@ -649,7 +649,7 @@ Interception or elapsed caller waiting cannot restore health, and a missing serv row proves neither business completion nor external quiescence. Closed vendor callbacks record fixed memory state only; provider exceptions, SQL and tenant/job/ actor/trace/parameter values stay out. The -[Step 9 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +[Step 9 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) owns delivered instruments and censuses; the [phase status](../roadmap/phase-02b-events-auth.md) owns current qualification. Phase 11 retains readiness routing, alert thresholds and process supervision. diff --git a/docs/standards/11-security.md b/docs/standards/11-security.md index 8931a545..bdefe49c 100644 --- a/docs/standards/11-security.md +++ b/docs/standards/11-security.md @@ -38,13 +38,13 @@ behaviors share that immutable snapshot. The retained-subject bound, retirement ownership and closed refusal/fault signals derive from [ADR-0066](../decisions/0066-bounded-tenant-subject-admission.md), Accepted — 2026-10-20. Implementation and local runtime/exported proofs are delivered; the -[implementation record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +[implementation record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns independent reviews and final-source CI qualification. The bound grants no throughput entitlement. Bounded authenticated assertion recording derives from [ADR-0065](../decisions/0065-bounded-tenant-assertion-diagnostics.md); its implementation and local proofs are delivered in the -[remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20). Its tenant-only audit budget is separate from the +[remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20). Its tenant-only audit budget is separate from the subject request registry and adds no tenant-registry admission cap. Producer announcement and common execution ownership derive from @@ -167,7 +167,7 @@ readable definitions, credentials and unrelated state remain preserved. This is account-preserving reconciliation with named assignment deletion, not general delete authority. All three correction steps complete local implementation and both independent review rounds. The -[qualification record](../roadmap/phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) +[qualification record](../roadmap/phase-02b-delivery-log.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) owns actual historical lifecycle, usable credential/MFA, signed API and stored self-service proof, together with exact hosted assignments and evidence limits. Acceptance or a partial experiment alone does not establish qualification. @@ -176,7 +176,7 @@ Acceptance or a partial experiment alone does not establish qualification. the issuance-lifetime rule decided by [ADR-0067](../decisions/0067-development-tenant-access-token-issuance.md), retaining the earlier approval in the -[P02b-6 package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20): +[P02b-6 package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20): the tenant development realm uses a configured 900-second access-token lifespan. [`learnstack.json`](../../infra/keycloak/realms/learnstack.json) owns the executable value; the development reconciler enforces it with no conflicting override on @@ -184,7 +184,7 @@ either named client. P02b-6 Steps 1–3 supply the fresh-import definition and bounded reconciliation through both seed/demo entries; their delivery records own actual local qualification. Step 4 delivers complete real-token/API proof after both independent reviews; its -[record](../roadmap/phase-02b-events-auth.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) +[record](../roadmap/phase-02b-delivery-log.md#p02b-6-step-4--real-identity-qualification-and-closeout-2026-10-21) owns local proof/review closure and source-bound qualification receipts. The required CI checks qualify their exact source and assignment. ADR-0064's one-hour API acceptance ceiling and 30-second skew remain separate from issuance. @@ -320,7 +320,7 @@ ADR-0046 accepts this P02b-2 boundary. Step 1 implements source/role guards; both review rounds are complete. Step 3 implements mandatory worker startup resolution and connectivity checks; both independent review rounds are complete. Step 4 credential/publication enforcement and local closeout are complete; all -four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +four steps completed both independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. The named keyed, lazy dispatcher source belongs only to the API host. Configuration validates the exact username without connecting or @@ -389,7 +389,7 @@ Begin cleans up the partial transaction and marks rollback-only before rethrowin Mode resets per transaction; poisoning remains sticky for the unit's lifetime. The authenticated-query extension is implemented by -[P02b-5 Step 2](../roadmap/phase-02b-events-auth.md#p02b-5-step-2--real-read-only-application-subject-2026-10-19); +[P02b-5 Step 2](../roadmap/phase-02b-delivery-log.md#p02b-5-step-2--real-read-only-application-subject-2026-10-19); Step 4 owns HTTP activation. Selection is by exact request type, never a query-name suffix, public marker or general authenticated read category. It reuses the existing physical owner and tenant announcement; @@ -617,7 +617,7 @@ and redirect/query rules. These are the ongoing security obligations: dynamic/no-store. The injected SDK owns no host, secret or global fetch default. P02d-5 delivers this boundary and ADR-0054's accounting, native admission and -URL controls. The [remediation record](../roadmap/phase-02d-walking-skeleton.md#p02d-5-external-review-remediation-2026-10-09) +URL controls. The [remediation record](../roadmap/phase-02d-delivery-log.md#p02d-5-external-review-remediation-2026-10-09) owns execution, independent reviews and PR closeout evidence. Every native HTTP path, including matcher exemptions, admits GET/HEAD only; production upgrades close and development retains only validated GET HMR. See diff --git a/docs/standards/12-infrastructure.md b/docs/standards/12-infrastructure.md index 7faf1838..f0838d36 100644 --- a/docs/standards/12-infrastructure.md +++ b/docs/standards/12-infrastructure.md @@ -91,12 +91,12 @@ otel-collector # Phase 11 (Production hardening — observability stack P02d-5 delivers G33's loopback API/native TLS web ingress and paired private local configuration under [ADR-0053](../decisions/0053-trusted-public-server-rendering.md). -Follow the [local setup](../roadmap/phase-02d-walking-skeleton.md#local-setup-and-ingress-details) +Follow the [local setup](../roadmap/phase-02d-delivery-log.md#local-setup-and-ingress-details) for explicit hosts and certificate trust preparation; neither is installed by scripts. P02d-7 delivers G45's `make demo` lifecycle, browser/TLS evidence and G44's Lighthouse harness/assertions under [ADR-0056](../decisions/0056-public-demo-browser-and-lighthouse-enforcement.md). -The [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +The [Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns enforcement and phase-exit verification. APISIX remains Phase 11. ### Healthchecks and the readiness gate @@ -258,7 +258,7 @@ See [10-observability.md](10-observability.md). import/reconciliation source; P02b-7's BFF is its later runtime consumer. Never pass it or Keycloak admin credentials to the API, public renderer or .NET Seeder. Existing confidential secrets are verified, never silently - rotated. The [accepted package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) + rotated. The [accepted package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) owns bounded tooling, selected-target validation and the no-credential-output contract; the [realm guide](../../infra/keycloak/README.md) owns local setup. - **Development-only defaults in `infra/compose/*.yml` are not committed secrets.** A diff --git a/docs/standards/13-documentation.md b/docs/standards/13-documentation.md index c90ebe63..457965c0 100644 --- a/docs/standards/13-documentation.md +++ b/docs/standards/13-documentation.md @@ -1,7 +1,7 @@ # 13 — Documentation Standards **Status:** Active -**Derives from:** [ADR 0007 — Documentation Language and Conventions](../decisions/0007-documentation-language-and-conventions.md). +**Derives from:** [ADR 0007 — Documentation Language and Conventions](../decisions/0007-documentation-language-and-conventions.md), [ADR 0069 — Phase Documents and Delivery Logs](../decisions/0069-phase-documents-and-delivery-logs.md). How LearnStack writes, organizes, and maintains documentation. @@ -19,6 +19,7 @@ docs/ decisions/ NNNN-topic.md ADRs _redirects/ redirect stubs for superseded ADRs roadmap/ phase-NN-topic.md (with phase-NNa / phase-NNb splits for parallel tracks) + phase-NN-delivery-log.md a phase's dated packet records (ADR-0069) standards/ NN-topic.md engineering rules runbooks/ *.md operations procedures (Phase 11+) modules/ <module>/ per-module specs (one directory per module, created with its first spec) @@ -76,7 +77,8 @@ The following are kept current and treated as code: | ADR (`decisions/`) | A one-time decision with status, context, decision, consequences | Immutable after acceptance, except for dated Amendments and the bounded corrections in § Correcting and Amending ADRs | | Standard (`standards/`) | Ongoing engineering rules | Editable as the team learns | | Runbook (`runbooks/`) | Operational procedures | Editable; review quarterly | -| Roadmap (`roadmap/`) | Phased plan | Editable per phase; a shipped packet's delivery record is not rewritten | +| Roadmap (`roadmap/`) | Phased plan: the six sections and a bounded Status block, no records ([Roadmap § Phase Structure](../roadmap/README.md#phase-structure)) | Editable per phase | +| Delivery log (`roadmap/phase-NN-delivery-log.md`) | A phase's dated decision packages, step records, reviews, corrections and closeouts, one section per packet | Append-only; a shipped packet's delivery record is not rewritten; an Accepted decision package is normative; its opening index is generated (`make docs-index`), never edited by hand | A delivery record that cites something false — an amendment withdrawn before merge, a test since renamed — gets a dated correction inline beside the false text, in the shape of an @@ -262,6 +264,7 @@ An Accepted ADR sometimes carries a statement that was **false when it entered t | New feature key or limit key | [21-feature-flags.md](../architecture/21-feature-flags.md) catalog + matching `FeatureKeys` / `LimitKeys` entry | | New Hub endpoint | New ADR (the surface is a cross-repository contract; see [ADR-0034](../decisions/0034-hub-contract-surface-invariant.md)) + [24-learnstack-hub.md](../architecture/24-learnstack-hub.md) | | Standards rule change | The standard itself + an ADR if non-trivial | +| Packet decision pass, step, review, correction or closeout | A dated entry in the phase's delivery log + the packet's row in the phase document's Status block — never a narrative in `CLAUDE.md`, the repository README or the roadmap index ([ADR-0069](../decisions/0069-phase-documents-and-delivery-logs.md)) | ## Documentation Reviews diff --git a/docs/standards/15-performance.md b/docs/standards/15-performance.md index ec90ffa9..d136de91 100644 --- a/docs/standards/15-performance.md +++ b/docs/standards/15-performance.md @@ -22,7 +22,7 @@ not merely a unit clarification. P7 delivers the always-running The hard gzip/CLS/automated-accessibility checks make this standard Active for that delivered scope. Timing medians remain advisory; production baselines, field telemetry and load tests remain Phase 11. The -[Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +[Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns real CI receipts and bounded required-check activation. ## Initial Budgets @@ -81,7 +81,7 @@ consumer query plans and representative local cold/warm measurements without a production p95 claim. P02d-5/G37 accepts dynamic/no-store public rendering under [ADR-0053](../decisions/0053-trusted-public-server-rendering.md); no shared Next representation cache is introduced. Internal definition caches remain independent. -[The accepted package](../roadmap/phase-02d-walking-skeleton.md#branding-entitlement-and-cache-boundary) +[The accepted package](../roadmap/phase-02d-delivery-log.md#branding-entitlement-and-cache-boundary) owns that boundary under ADR-0052. ### Pagination diff --git a/docs/standards/16-accessibility.md b/docs/standards/16-accessibility.md index 38b2e0e6..84d840ef 100644 --- a/docs/standards/16-accessibility.md +++ b/docs/standards/16-accessibility.md @@ -3,7 +3,7 @@ **Status:** Active **Derives from:** WCAG 2.2 AA (external authoritative standard), [00-principles.md](00-principles.md) § 6 (Foundation First). Public-page obligations also follow [ADR-0027](../decisions/0027-frontend-i18n.md) -and the [Accepted P02d-6 package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09). +and the [Accepted P02d-6 package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09). LearnStack targets **WCAG 2.2 AA** across all user-facing surfaces. @@ -101,7 +101,7 @@ LearnStack is an education platform; learners with disabilities are a first-clas - P02d-7 delivers the narrow managed-browser walkthrough and hard Lighthouse automated accessibility score for nine seeded pages under [ADR-0056](../decisions/0056-public-demo-browser-and-lighthouse-enforcement.md). - The [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) + The [Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns CI and required-check receipts; this supplements the scoped P6 human record. - Manual keyboard walkthroughs for new screens in the PR review. @@ -116,7 +116,7 @@ keyboard, focus, 320 CSS px reflow, long-string and contrast observations plus the maintainer's passing VoiceOver smoke complete P6's manual requirement on 2026-10-10. Enforcement and recorded observation promote this standard to **Active** for delivered public-page scope. Step 4's -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) owns automated execution and manual evidence; this is not a full WCAG audit. Catalog → course → lesson is a critical flow requiring manual keyboard, focus, diff --git a/docs/standards/18-audit-coverage.md b/docs/standards/18-audit-coverage.md index 7c63087b..9b03f6f8 100644 --- a/docs/standards/18-audit-coverage.md +++ b/docs/standards/18-audit-coverage.md @@ -15,7 +15,7 @@ Delivery/recovery additions derive from Authenticated assertion admission derives from [ADR-0065](../decisions/0065-bounded-tenant-assertion-diagnostics.md); its implementation and local proofs are delivered in the -[remediation record](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20). +[remediation record](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20). Job additions derive from [ADR-0047](../decisions/0047-transactional-background-job-runtime.md) (accepted 2026-10-15; P02b-4 runtime and enforcement implemented; the diff --git a/docs/standards/20-infrastructure-stack.md b/docs/standards/20-infrastructure-stack.md index cab99930..1be94a10 100644 --- a/docs/standards/20-infrastructure-stack.md +++ b/docs/standards/20-infrastructure-stack.md @@ -302,7 +302,7 @@ boundary in P02d-3, with planted interface/concrete/helper offenders and a clean control. **Settings are uncached in P02d-2/3.** The -[Accepted G23 freshness answer](../roadmap/phase-02d-walking-skeleton.md#p02d-2-accepted-answers) +[Accepted G23 freshness answer](../roadmap/phase-02d-delivery-log.md#p02d-2-accepted-answers) selects no settings cache. The adapter's existing `tenancy:settings` metric spelling is reserved, not an active reader or a TTL promise. P02d-3 owns the typed ambient accessor and explicit tenant/organization scope; it adds no settings generation @@ -457,7 +457,7 @@ it cannot replace the API's own validation and host reconciliation. DDL CHECK. P02b-1 Steps 2/3 implement immediate enqueue, successful-save collection and the completed-provisioning publisher. Step 4 implements the production censuses and catalogue enforcement; the - [delivery record](../roadmap/phase-02b-events-auth.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) + [delivery record](../roadmap/phase-02b-delivery-log.md#p02b-1-step-4--producer-enforcement-and-closeout-2026-10-12) owns final verification and review status. - Only the owner drains successful-save domain events before invariants/MUST audit/commit. Domain handlers only translate to outbox; a total 256-event bound @@ -488,13 +488,13 @@ it cannot replace the API's own validation and host reconciliation. Brokers and retention purge remain demand-gated Phase 11. P02b-2 Step 3 implements hosted producer dispatch, with both independent review rounds complete; Step 4 enforcement and local closeout are complete; all four steps completed - both independent review rounds. The [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) + both independent review rounds. The [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status. P02b-3 Steps 1–4 implement shared storage, durable acceptance, transactional execution and independent scheduling/terminalization/replay. Its real defaults are Active with Step 5 initialization and semantic Seeder handoff. The - [Step 5 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) + [Step 5 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-5--useful-defaults-and-semantic-seed-handoff-2026-10-13) records that step's validation and reviews. The - [Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) + [Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns current enforcement, validation and review/PR status. - Controlled subscriber tasks retain their actual app-role scope through cancellation callbacks and cleanup. Timeout closes the sticky commit gate @@ -726,7 +726,7 @@ causal-envelope or payload read to the bypass scheduler. See Accepted [ADR-0047](../decisions/0047-transactional-background-job-runtime.md) owns H1: stock Hangfire transports opaque wakeups; LearnStack records own business intent, attempts, tenant/organization authority and completion. The -[P02b-4 delivery record](../roadmap/phase-02b-events-auth.md#source-lifetime-and-facade-continuation-2026-10-16) +[P02b-4 delivery record](../roadmap/phase-02b-delivery-log.md#source-lifetime-and-facade-continuation-2026-10-16) owns current implementation/qualification status; Step 4 qualifies API activation. **Accepted lifecycle addition — 2026-10-16.** @@ -744,7 +744,7 @@ are qualified: a draining pool can block unrelated same-pool tenants with a spar slot and below four retained overruns, including after storage recovery, until actual cleanup. Other healthy pools remain independent subject to common dependencies; hard retention bounds, attempts, reservations and quiescence hold. -The [Step 4 adaptation](../roadmap/phase-02b-events-auth.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) +The [Step 4 adaptation](../roadmap/phase-02b-delivery-log.md#maintainer-acceptance-and-step-4-adaptation-2026-10-16) is authorized. Step 4 locally qualifies the shipped lifecycle and API composition; its delivery record owns both full reviews and verified corrections. @@ -769,7 +769,7 @@ is not developer/shared/production host authority or a weaker child precondition The closed owners are `scripts/ci-native-provisioning.py` and `scripts/ci-native-tests.py`; their offline subprocess/partition controls run in `meta`. Exact discovery/result identities and all required execution outcomes gate the -aggregate. The [CI record](../roadmap/phase-02b-events-auth.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) +aggregate. The [CI record](../roadmap/phase-02b-delivery-log.md#adr-0062-acceptance-and-ci-implementation-2026-10-18) owns reviews and actual hosted qualification. Local controls do not qualify the hosted process boundary, complete partitions or their budget fit. @@ -801,7 +801,7 @@ each aggregate to five; actual final-source fit is recorded in the phase. `ExternalWaitTimeout` bounds Execute; `ProbeTimeout` bounds Reconcile, checkpoint history and recovery confirmation. Expiry closes late admission while actual work, private cancellation callbacks and cleanup remain owned. The - [Step 7 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) + [Step 7 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) owns the stage-wait qualification. - A per-pool server-metadata heartbeat fault makes `jobs` unhealthy during retry, before draining. Only confirmed stored heartbeat success clears it. Two fixed @@ -819,7 +819,7 @@ each aggregate to five; actual final-source fit is recorded in the phase. positive original cleanup and distinct recovery authority through the exact app-role checkpoint. Missing local cleanup preserves occupied capacity in paced recoverable parking. - The [Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) + The [Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-6--tenant-capacity-reservations-2026-10-16) owns passing local qualification, both completed full review rounds and verified corrections. - Definition/queue/recurrence keys come from finite code registries. Only the two diff --git a/docs/standards/21-architecture-tests-catalogue.md b/docs/standards/21-architecture-tests-catalogue.md index d71502a8..00a5a668 100644 --- a/docs/standards/21-architecture-tests-catalogue.md +++ b/docs/standards/21-architecture-tests-catalogue.md @@ -16,14 +16,14 @@ [ADR-0046 Durable Event Delivery and Recovery](../decisions/0046-durable-event-delivery-and-recovery.md) (P02b-2 transition, terminal-witness and hosted runtime proofs implemented; all four steps completed both independent review rounds; packet complete and merged; -the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-2-merge-and-closeout-2026-10-13) +the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-2-merge-and-closeout-2026-10-13) owns CI/merge status; P02b-3 Steps 1–6 implement consumer runtime, defaults and production-census enforcement; its -[Step 6 record](../roadmap/phase-02b-events-auth.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) +[Step 6 record](../roadmap/phase-02b-delivery-log.md#p02b-3-step-6--production-enforcement-and-pr-closeout-2026-10-13) owns validation, review and PR closeout status), [ADR-0047 Transactional Background Job Runtime](../decisions/0047-transactional-background-job-runtime.md) (Accepted 2026-10-15; P02b-4 obligations implemented and locally qualified; -the [Step 9 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +the [Step 9 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) owns review, packet and exact PR-head CI/job-budget status), [ADR-0058 Bounded Stock Hangfire Maintenance](../decisions/0058-bounded-stock-hangfire-maintenance.md) (Accepted 2026-10-16; maintenance extensions and runtime proofs implemented), @@ -40,16 +40,16 @@ owns review, packet and exact PR-head CI/job-budget status), final-source hosted qualification), [ADR-0064 Tenant API Authentication Boundary](../decisions/0064-tenant-api-authentication-boundary.md) (Accepted 2026-10-19; P02b-5 obligations implemented and merged through PR #33; -the [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) +the [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns final-source hosted qualification), [ADR-0065 Bounded Tenant Assertion Diagnostics](../decisions/0065-bounded-tenant-assertion-diagnostics.md) (Accepted 2026-10-20; extends existing obligations below; audit-budget and telemetry controls implemented; the -[P02b-5 merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) +[P02b-5 merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns current qualification status), [ADR-0066 Bounded Tenant Subject Admission](../decisions/0066-bounded-tenant-subject-admission.md) (Accepted 2026-10-20; extends the existing subject-admission obligation; -the [delivery record](../roadmap/phase-02b-events-auth.md#adr-0066-acceptance-and-implementation-2026-10-20) +the [delivery record](../roadmap/phase-02b-delivery-log.md#adr-0066-acceptance-and-implementation-2026-10-20) owns source-bound validation, reviews and hosted qualification), [ADR-0067 Development Tenant Access-Token Issuance](../decisions/0067-development-tenant-access-token-issuance.md) (Accepted 2026-10-21; formalizes the existing issuance obligation's authority @@ -155,11 +155,11 @@ P02b-2 Steps 2–4, P02b-3 Steps 3–6 and P02b-4 Steps 1–8, with further source-boundary, observation and production-manifest companions in Step 9. Its nineteen packet obligations are implemented with actual canonical owners and complementary structural, native-runtime and PostgreSQL controls. The -[Step 9 record](../roadmap/phase-02b-events-auth.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) +[Step 9 record](../roadmap/phase-02b-delivery-log.md#p02b-4-step-9--enforcement-and-packet-closeout-2026-10-18) distinguishes local enforcement qualification from pending review/packet/CI closeout. P02b-5 adds the authenticated route/helper census and closed claim/role authority controls; its seven obligations have actual local owners. Its Step 5 and -[review remediation](../roadmap/phase-02b-events-auth.md#p02b-5-external-review-remediation-2026-10-20) +[review remediation](../roadmap/phase-02b-delivery-log.md#p02b-5-external-review-remediation-2026-10-20) records distinguish prior hosted qualification from the current correction head. Methods are not rows: a `[Theory]` is one row and many cases, @@ -706,15 +706,15 @@ otherwise). The guard reads identity literals from the authoritative `SeedData` declaration, not a second hard-coded list. Its source reader must observe the declared values and fail on an incomplete or unreadable declaration rather than report clean. -- **Source:** [Phase 02d G20](../roadmap/phase-02d-walking-skeleton.md#p02d-2-accepted-answers). +- **Source:** [Phase 02d G20](../roadmap/phase-02d-delivery-log.md#p02d-2-accepted-answers). - **Scope:** P02d-2 accepted G20(a)'s source; - [P02d-5](../roadmap/phase-02d-walking-skeleton.md#p02d-5-accepted-answers) + [P02d-5](../roadmap/phase-02d-delivery-log.md#p02d-5-accepted-answers) accepted bounded seed/development/test exemptions, and - [P02d-6](../roadmap/phase-02d-walking-skeleton.md#p02d-6-accepted-answers) + [P02d-6](../roadmap/phase-02d-delivery-log.md#p02d-6-accepted-answers) accepted production frontend TS/JS and JSON subjects, including renderer and message values. Matching/built-in detail, the Seeder-reference fence and behavioral ownership are in the - [P7 package](../roadmap/phase-02d-walking-skeleton.md#p02d-7-genericity-enforcement), + [P7 package](../roadmap/phase-02d-delivery-log.md#p02d-7-genericity-enforcement), approved on 2026-10-11; Step 2 implements the exact-literal/reference fences. ADR-0056's separate browser/Lighthouse measurement decision and its implemented controls complement @@ -1925,7 +1925,7 @@ diagnostic above row security, not the boundary, as its own note says. and concrete cleanup-owner censuses in [BackgroundJobRuntimeCompositionBoundaryTests](../../backend/tests/LearnStack.Tests.Architecture/BackgroundJobRuntimeCompositionBoundaryTests.cs) and [PrivilegedDispatchCleanupBoundaryTests](../../backend/tests/LearnStack.Tests.Architecture/PrivilegedDispatchCleanupBoundaryTests.cs). - The [Step 4 continuation](../roadmap/phase-02b-events-auth.md#source-lifetime-and-facade-continuation-2026-10-16) + The [Step 4 continuation](../roadmap/phase-02b-delivery-log.md#source-lifetime-and-facade-continuation-2026-10-16) owns current qualification/review status. Existing dispatcher enforcement stays Implemented; full Step 4 review gates remain open. @@ -2313,7 +2313,7 @@ because the filters hold, and removing both turns all five red. scan also refuses direct EF mutation/SaveChanges/set-based SQL and ad hoc `NpgsqlCommand` construction; its planted companion distinguishes these from immutable data construction, composition and request dispatch. -- **Source:** [Phase 02d G15](../roadmap/phase-02d-walking-skeleton.md#p02d-2-accepted-answers) +- **Source:** [Phase 02d G15](../roadmap/phase-02d-delivery-log.md#p02d-2-accepted-answers) and [Security Standards § The out-of-band setters](11-security.md#the-out-of-band-setters). - **Type:** xUnit + source/IL scans with companions that plant caller and persistence violations and verify permitted request dispatch/context composition. @@ -3529,7 +3529,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). seventh time. Every transition checks identity, token and database-time expiry. Terminal requests never reenter normal publication, including after audit refusal. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** production architecture census with planted controls where structural; real PostgreSQL/runtime integration proofs where behavioural. **Kind:** structural + behavioural. @@ -3547,7 +3547,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). never publish. Unknown COMMIT reconciles durable state before retry and cannot duplicate the terminal audit. Exact real-role grants allow only the declared writes. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** integration tests (Testcontainers), including physical COMMIT-response loss and real-role grant controls. **Kind:** behavioural. @@ -3570,7 +3570,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). organization, event and transaction against that witness and roll back both writes; matching organization-scoped identity succeeds. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** production architecture census with planted controls where structural; real PostgreSQL/runtime integration proofs where behavioural. **Kind:** structural + behavioural. @@ -3587,7 +3587,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). admission, microsecond timestamp comparison and full row/envelope agreement have positive and negative controls. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** production architecture census with planted controls where structural; real PostgreSQL/runtime integration proofs where behavioural. **Kind:** structural + startup + behavioural. @@ -3606,7 +3606,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). publish/mark path. P02b-3 Step 5 activates both real production subscriptions; Pending-manifest fixtures retain the policy proof. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** integration tests (Testcontainers) and unit tests of production composition and manifest refusal. **Kind:** startup + behavioural. @@ -3636,7 +3636,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). DI health must follow Healthy → Unhealthy → Healthy on its singleton observation, refusing a same-type detached factory. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md); - [P02b-2 proof obligations](../roadmap/phase-02b-events-auth.md#decisive-proof-obligations). + [P02b-2 proof obligations](../roadmap/phase-02b-delivery-log.md#decisive-proof-obligations). - **Type:** production architecture census with planted controls where structural; real PostgreSQL/runtime integration proofs where behavioural. **Kind:** structural + behavioural. @@ -3659,7 +3659,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). Identical duplicates are idempotent, conflicting copies are refused and partial/uncertain acceptance retries safely without spending subscriber budgets. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) - and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). + and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). - **Type:** real PostgreSQL/app-role integration and construction controls. **Kind:** behavioural. - **Status:** **Implemented** (`DurableEventAcceptanceTests`, `InboxGuardTests`, @@ -3676,7 +3676,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). COMMIT recovers from atomic inbox/ledger state. Replay resets one terminal ledger pair only, never its completed inbox or a healthy sibling. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#subscriber-acceptance-and-inbox-ownership) - and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). + and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). - **Type:** real PostgreSQL worker/owner integration, controlled cancellation, lost-COMMIT and state-transition mutants. **Kind:** behavioural. - **Status:** **Implemented** (`DeliveryDispatchStoreTests`, `DeliveryProcessorTests`, @@ -3710,7 +3710,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). diagnostics/finite labels, exact snapshot cadence and prior-snapshot retention preserve truthful registered health; gauge callbacks execute no SQL. - **Source:** [ADR-0046](../decisions/0046-durable-event-delivery-and-recovery.md#diagnostics-and-execution-bounds) - and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). + and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). - **Type:** production registration/observation/call-path census with planted dirty/clean controls, unit probes and real worker integration. **Kind:** structural + behavioural. @@ -3730,7 +3730,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). serialization makes competing registration and initialization converge without overwrite, republish or resurrection; each effect has independent inbox state. - **Source:** [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) - and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). + and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). - **Type:** actual consumer integration, lifecycle/race/atomic-audit controls. **Kind:** behavioural. - **Status:** **Implemented** — `CustomizationDefaultInitializationTests`, @@ -3746,7 +3746,7 @@ Introduced by [Phase 02b](../roadmap/phase-02b-events-auth.md). reruns are neutral, conflicting lifecycle/shape refuses without overwrite, and fresh seeding/delivery races converge in both winning orders. - **Source:** [ADR-0057](../decisions/0057-transactional-event-production-and-completion.md#first-useful-production-flow) - and the [P02b-3 package](../roadmap/phase-02b-events-auth.md#p02b-3-decision-package-2026-10-13). + and the [P02b-3 package](../roadmap/phase-02b-delivery-log.md#p02b-3-decision-package-2026-10-13). - **Type:** actual Seeder/module/worker integration with warm-ID and race controls. **Kind:** behavioural. - **Status:** **Implemented** — `SeederTests`, @@ -3854,7 +3854,7 @@ implements it. | Test | Rule | Kind | Owning phase | Named in | |---|---|---|---|---| -| `Provider_SDK_Types_NotImportedOutsideInfrastructure` | A provider SDK's types — LiveKit, the Keycloak admin client, SeaweedFS, a payment SDK — appear only in the `LearnStack.Infrastructure.*` adapter that wraps it, never in a module. A superset of [`Adapters_Wrap_Provider_Exceptions`](#adapters_wrap_provider_exceptions), which already holds the exception types of the SDKs it lists — the one slice of this rule that runs today | structural | [Phase 03](../roadmap/phase-03-identity-admin.md#goal), at the first runtime identity-provider adapter's actual SDK introduction; re-verify before its first writer. Direct-HTTP tooling does not qualify; it then binds per provider as each SDK adapter lands | [Tenant Isolation](../architecture/09-tenant-isolation.md); [P02b-6 accepted handoff](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) | +| `Provider_SDK_Types_NotImportedOutsideInfrastructure` | A provider SDK's types — LiveKit, the Keycloak admin client, SeaweedFS, a payment SDK — appear only in the `LearnStack.Infrastructure.*` adapter that wraps it, never in a module. A superset of [`Adapters_Wrap_Provider_Exceptions`](#adapters_wrap_provider_exceptions), which already holds the exception types of the SDKs it lists — the one slice of this rule that runs today | structural | [Phase 03](../roadmap/phase-03-identity-admin.md#goal), at the first runtime identity-provider adapter's actual SDK introduction; re-verify before its first writer. Direct-HTTP tooling does not qualify; it then binds per provider as each SDK adapter lands | [Tenant Isolation](../architecture/09-tenant-isolation.md); [P02b-6 accepted handoff](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) | | `LicenseKey_Payload_MatchesSchema` | `entitlement-v1.schema.json` is pinned by a snapshot test run in **both** repositories against the same checked-in schema | structural | [Phase 02c](../roadmap/phase-02c-hub-foundation.md), with the schema | [Hybrid License Model](../architecture/26-hybrid-license-model.md); [ADR-0021](../decisions/0021-feature-based-entitlement.md), as `EntitlementProjection_Shape_IsStable` — see § Canonical names | | `Entitlement_Read_Path_Falls_Through_To_Durable_Row` | With L1 and L2 flushed and the Hub unreachable, the tenant resolves from `platform_entitlement_cache` and no exception escapes the flag read | behavioural | [Phase 02c](../roadmap/phase-02c-hub-foundation.md), with `HubEntitlementProvider` | [Hybrid License Model](../architecture/26-hybrid-license-model.md) | | `CustomDomain_TenantId_NeverReadFrom_RequestBody` | Custom-domain submission derives the tenant from the authenticated session, never from the body or the query | behavioural | [Phase 02c](../roadmap/phase-02c-hub-foundation.md), Hub side, per [ADR-0022](../decisions/0022-custom-domain-tls.md) | ADR-0022; [Custom Domain TLS](../architecture/27-custom-domain-tls.md) | @@ -4527,7 +4527,7 @@ structural test proves — and what it does not. [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) (historical warm qualification); [Security 11](11-security.md#authentication); - [accepted P02b-6 package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20). + [accepted P02b-6 package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20). - **Type:** xUnit Integration with Docker, real Keycloak code exchange, API HTTP and `learnstack_app` database controls. **Kind:** behavioural. - **Test owner:** `TenantRealmIssuanceTests`, `TenantRealmProfileProtectionTests` @@ -4546,7 +4546,7 @@ structural test proves — and what it does not. measures both new scope refusals and the retained offline session/credential; no universal role-loss or immediate-revocation guarantee is inferred. [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) and its - [three-step record](../roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22) + [three-step record](../roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22) own actual receipts, completed correction reviews and source-bound hosted proof. Existing Implemented status and rule counts remain unchanged. - **Phase:** P02b-6 Steps 1/4. @@ -4576,7 +4576,7 @@ structural test proves — and what it does not. - **Source:** ADR-0004; ADR-0064; [ADR-0068](../decisions/0068-development-warm-realm-qualification.md); [Security 11](11-security.md#authentication); - [accepted P02b-6 package](../roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20). + [accepted P02b-6 package](../roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20). - **Type:** xUnit Integration with Docker and actual warm Keycloak Admin REST; offline Node tooling transport/process/CLI controls in meta. **Kind:** behavioural. @@ -4611,7 +4611,7 @@ structural test proves — and what it does not. A hidden fresh-plan conflict may leave preparation metadata, but no ordinary mutation; the earlier zero-write scope remains historical implemented coverage. [ADR-0068](../decisions/0068-development-warm-realm-qualification.md) and its - [three-step record](../roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22) + [three-step record](../roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22) own actual receipts, completed correction reviews and source-bound hosted proof. Existing Implemented status and rule counts remain unchanged. - **Phase:** P02b-6 Steps 2–4. @@ -5079,7 +5079,7 @@ structural test proves — and what it does not. These names are registered against [ADR-0052](../decisions/0052-anonymous-public-read-boundary.md) and the -[accepted P02d-4 package](../roadmap/phase-02d-walking-skeleton.md#p02d-4-accepted-answers). +[accepted P02d-4 package](../roadmap/phase-02d-delivery-log.md#p02d-4-accepted-answers). Every structural mechanism requires a clean control and planted offenders for its claimed paths. Individual Status rows distinguish registration from passing tests. Runtime proofs are independent of structural detection. @@ -5276,7 +5276,7 @@ rules below are commitments before the first implementation; none is a passing test claim at acceptance. Existing P5 source/runtime controls remain mandatory, and P6 product proofs supplement the isolated synthetic transport fixture. P02d-6 implements the five rules below and completes its manual smoke on -2026-10-10; the [packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) +2026-10-10; the [packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) owns execution, review and manual evidence. ### `Ui_Catalogues_Cover_Public_Call_Sites` @@ -5366,7 +5366,7 @@ owns execution, review and manual evidence. replacement proofs and planted controls pass for the five rules below. All three steps completed both independent review rounds and focused fix verification. Existing P5/P6 controls remain mandatory. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns actual execution, completed reviews and verified fixes. Six existing production modes pass with revised call accounting. The additional production Fact is `Native_admission_preserves_wire_failures_request_lifetimes_and_browser_fallback` in @@ -5497,10 +5497,13 @@ mutants, TLS refusals and a real Lighthouse timeout also run in the full proof. `src/test/demo-source.test.ts` uses disposable Git repositories for clean/mutated source checkpoints; `src/test/public-demo-diagnostics.test.ts` covers closed failure attribution with real children and provider canaries. -`src/test/public-demo-ci.test.ts` executes the actual workflow deadline shell; +`src/test/public-demo-ci.test.ts` executes the actual workflow deadline and +browser-installation shells, including effective APT acquire settings and +invocation-owned fragment cleanup on success and failure, plus bounded tail +commands that preserve ordinary and forced-timeout failure statuses; `scripts/ci-public-chromium.test.mjs` tests owned Linux sandbox preparation and cleanup before the job runs the real managed-browser launch smoke. -The [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +The [Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns exact CI and protection receipts. These are Node behavioral rules, not C# architecture-test methods or a full WCAG/production-performance claim. @@ -5561,7 +5564,7 @@ C# architecture-test methods or a full WCAG/production-performance claim. ## P02b-4 background-job obligations Source: [Accepted ADR-0047](../decisions/0047-transactional-background-job-runtime.md#architecture-tests) -and the [nine-step package](../roadmap/phase-02b-events-auth.md#p02b-4-decision-package-2026-10-15). +and the [nine-step package](../roadmap/phase-02b-delivery-log.md#p02b-4-decision-package-2026-10-15). [Accepted ADR-0058](../decisions/0058-bounded-stock-hangfire-maintenance.md#architecture-tests) extends the existing bootstrap and independent-capacity assertions below. [Accepted ADR-0059](../decisions/0059-owned-hangfire-server-generations.md#architecture-tests) @@ -5571,12 +5574,12 @@ qualification to the existing bootstrap, credential and capacity obligations. adds the exceptional fatal-boundary assignments below. [Accepted ADR-0061](../decisions/0061-known-external-job-failure-policy.md#architecture-tests) extends seven existing assertions for completed external-failure policy. -[Step 7 qualification and both full reviews](../roadmap/phase-02b-events-auth.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) +[Step 7 qualification and both full reviews](../roadmap/phase-02b-delivery-log.md#p02b-4-step-7--external-stages-and-recovery-2026-10-17) are complete. Step 9 implements and locally qualifies all nineteen complete assertions below; each Implemented status names its actual canonical owner. Acceptance alone promotes no rule, and a partial foundation does not enforce a complete assertion. The -[Step 9 record](../roadmap/phase-02b-events-auth.md#canonical-enforcement-reconciliation) +[Step 9 record](../roadmap/phase-02b-delivery-log.md#canonical-enforcement-reconciliation) distinguishes executed local qualification from packet/review and exact PR-head CI/job-budget closure. Production business/recurrence registries remain empty; real framework subjects @@ -5898,6 +5901,9 @@ and fixture definitions make the implemented controls non-vacuous. qualify final-source independence and finite execution/meta/aggregate budgets; advisory duration estimates never establish membership or fit. Native and non-Docker authorities remain separated. + Pending-only API acquisition validates each fresh complete snapshot under + one finite deadline; it never combines responses or retries terminal, + malformed, missing, duplicate or identity-invalid evidence. - **Source:** [ADR-0063](../decisions/0063-complete-bounded-ci-test-shards.md). - **Type:** actual Python plan/owner subprocess controls and workflow/API/hosted result proofs. **Kind:** structural + behavioural. diff --git a/docs/standards/README.md b/docs/standards/README.md index e85543b5..2b42db5f 100644 --- a/docs/standards/README.md +++ b/docs/standards/README.md @@ -71,13 +71,13 @@ The table below records delivered enforcement and its owning evidence: [Phase 02a](../roadmap/phase-02a-kernel-tenancy.md) and P02d-1–6 are complete and merged. P02d-5's ingress, configured server caller, dynamic entry and frontend guards are delivered through PR #26; the -[merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-5-merge-and-closeout-2026-10-09) +[merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-5-merge-and-closeout-2026-10-09) owns its final review and CI evidence. -P6's [decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-6-decision-package-2026-10-09) +P6's [decision package](../roadmap/phase-02d-delivery-log.md#p02d-6-decision-package-2026-10-09) and [ADR-0027](../decisions/0027-frontend-i18n.md) are Accepted — 2026-10-09; P6 Step 1 implements the pinned i18n/document foundation, shared request-local loaders, chrome/states and atomic theme injection. Its -[delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-6-step-1-localization-and-document-foundation) +[delivery record](../roadmap/phase-02d-delivery-log.md#p02d-6-step-1-localization-and-document-foundation) owns foundation validation and review evidence. Steps 2–3 implement actual catalog/course/lesson views, pagination/metadata and blocking JSX accessibility controls. Step 4 implements automated product HTML/Flight proofs and completes @@ -85,13 +85,13 @@ manual accessibility, including maintainer-reported VoiceOver. P7 delivers demo/browser/Lighthouse. ADR-0055 remediation delivers single-bootstrap admission and passing production replacement proofs. All three steps completed both independent review rounds. The -[Step 3 record](../roadmap/phase-02d-walking-skeleton.md#adr-0055-step-3--production-admission-proof-and-closeout) +[Step 3 record](../roadmap/phase-02d-delivery-log.md#adr-0055-step-3--production-admission-proof-and-closeout) owns completed Step 3 reviews, verified fixes and delivery evidence; its five rules are Implemented. P6's -[merge closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) +[merge closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-merge-and-closeout-2026-10-10) records PR #27's merge and final verification. P7 delivers the shared demo, G20 fences and seeded browser/Lighthouse enforcement. Its -[Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) +[Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns review, real CI and protection receipts. Acceptance alone promotes no status. **The documents and this table say the same thing, and a test holds them to it.** @@ -114,22 +114,22 @@ included. | 08 | [Localization](08-localization.md) | **Active** | Packet 6 shipped `tenant_locales` and the slug schema. The partial unique default index enforces at most one default, not existence of a default for every enabled set; P02d-2 ships supported-write validation and the default-enabled CHECK constraint; raw deletes can still leave an enabled locale set without a default. `LocalizedText` and `LocalizedMessage` ship with their own cases, and API errors are keyed. P02d-1 shipped Education Pattern A satellites, canonical locales and flat localized-slug uniqueness; P02d-4 Step 3 delivers exact enabled public locale admission and response labels. P02d-5 Step 3 delivers membership-first redirect G36. P02d-6 Step 1 implements Accepted ADR-0027/G39's next-intl 4.14.9 plugin/request runtime, app-local `src/i18n/messages/{en,tr}/public.json` and catalogue controls. Phase 04 inherits the foundation for CMS/Studio. | | 09 | [Error Handling](09-error-handling.md) | **Active** | L1 `IExceptionHandler`, the exception hierarchy, `ProblemDetailsFactory` and `HttpStatusMap` shipped in Packet 3. | | 10 | [Observability](10-observability.md) | **Active** | Serilog → OTLP, OpenTelemetry SDK, `TenantContextSpanProcessor` and the redaction enrichers shipped in Packet 3. | -| 11 | [Security](11-security.md) | **Active** | P02b-5 delivers tenant bearer authentication and the closed AccountSite boundary; its [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-5-merge-and-closeout-2026-10-20) owns final verification. The isolation half is live and mechanical: Row Level Security with the four roles and the isolation suite that runs as `learnstack_app`; the tenancy edge, the trusted-hop predicate and the anonymous rate limiter from Packet 4; and, since Packet 10, § The out-of-band setters — every announcer of a session variable is one the table names and each reader opens its transaction read-only, with `App_Role_Cannot_Enumerate_Tenants`, `App_Role_Cannot_Enumerate_Host_Map` and `Tenant_A_Cannot_Repoint_Tenant_B_Host` proving the role cannot read or repoint what the policies bar. BFF sessions remain P02b-7; application membership and permission enforcement belong to [Phase 03](../roadmap/phase-03-identity-admin.md). Three sections retain the document's enforcement carve-out: § Transport, § HTTP Headers and § CORS — HSTS, `nosniff`, CSP and the production origin policy remain [Phase 11 § Secure headers](../roadmap/phase-11-production-hardening.md) work, at APISIX and in the ASP.NET layer beside it. | +| 11 | [Security](11-security.md) | **Active** | P02b-5 delivers tenant bearer authentication and the closed AccountSite boundary; its [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-5-merge-and-closeout-2026-10-20) owns final verification. The isolation half is live and mechanical: Row Level Security with the four roles and the isolation suite that runs as `learnstack_app`; the tenancy edge, the trusted-hop predicate and the anonymous rate limiter from Packet 4; and, since Packet 10, § The out-of-band setters — every announcer of a session variable is one the table names and each reader opens its transaction read-only, with `App_Role_Cannot_Enumerate_Tenants`, `App_Role_Cannot_Enumerate_Host_Map` and `Tenant_A_Cannot_Repoint_Tenant_B_Host` proving the role cannot read or repoint what the policies bar. BFF sessions remain P02b-7; application membership and permission enforcement belong to [Phase 03](../roadmap/phase-03-identity-admin.md). Three sections retain the document's enforcement carve-out: § Transport, § HTTP Headers and § CORS — HSTS, `nosniff`, CSP and the production origin policy remain [Phase 11 § Secure headers](../roadmap/phase-11-production-hardening.md) work, at APISIX and in the ASP.NET layer beside it. | | 12 | [Infrastructure](12-infrastructure.md) | **Active** | Compose stack, `Makefile`, CI workflow, pre-commit hooks and secret scanning all live since Phase 01. | | 13 | [Documentation](13-documentation.md) | **Active** | Governs this corpus; the CI link audit walks changed Markdown. | -| 14 | [Git Workflow](14-git-workflow.md) | **Active** | Conventional Commits, hooks and required checks are live. Two branch-protection settings — `Require approvals` and `Do not allow bypassing` — are **deferred by maintainer decision (2026-08-10)** while the repository has one active contributor; the trigger and what activating them involves are recorded in [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md). P02d-1 repaired and re-read the live required-check list on 2026-09-14: all five active jobs, including the current meta name and Docker integration, are required with GitHub Actions attribution and strict up-to-date checking. P02d-4 activates the sixth `openapi diff` context after a successful real job and verifies every other setting unchanged. P02d-7 activates the seventh `public demo + lighthouse` context after complete real PR success and verifies all six prior contexts, strict mode and every unrelated setting preserved; its [CI and exit closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) records the receipts. [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) owns the current list; the [P02d-4 delivery record](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-4-contract-sdk-and-ci) records activation verification. | -| 15 | [Performance](15-performance.md) | **Active** | P02d-7 delivers the always-running `public demo + lighthouse` job under ADR-0056: nine seeded pages, 27 audits, actual-page/source/census controls and hard normalized gzip/CLS/automated-accessibility checks. Timing medians are advisory. The [Step 4 record](../roadmap/phase-02d-walking-skeleton.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns real CI and required-check receipts. Production p95/field telemetry/load tests remain [Phase 11](../roadmap/phase-11-production-hardening.md). | -| 16 | [Accessibility](16-accessibility.md) | **Active** | P6 delivers catalog/course/lesson and controlled-state semantics, all 31 active recommended jsx-a11y rules at error severity with per-rule actual-config dirty/clean controls, and real product HTML/Flight proofs. The [packet closeout](../roadmap/phase-02d-walking-skeleton.md#p02d-6-packet-closeout-2026-10-10) records keyboard/focus/reflow/contrast observations and the maintainer's passing VoiceOver smoke. This is enforcement for delivered public-page scope, not a full WCAG audit. P02d-7 adds hard Lighthouse automated accessibility and a narrow library browser walkthrough; full Playwright Test/axe remains [Phase 06](../roadmap/phase-06-renderer-admin-studio.md). | +| 14 | [Git Workflow](14-git-workflow.md) | **Active** | Conventional Commits, hooks and required checks are live. Two branch-protection settings — `Require approvals` and `Do not allow bypassing` — are **deferred by maintainer decision (2026-08-10)** while the repository has one active contributor; the trigger and what activating them involves are recorded in [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md). P02d-1 repaired and re-read the live required-check list on 2026-09-14: all five active jobs, including the current meta name and Docker integration, are required with GitHub Actions attribution and strict up-to-date checking. P02d-4 activates the sixth `openapi diff` context after a successful real job and verifies every other setting unchanged. P02d-7 activates the seventh `public demo + lighthouse` context after complete real PR success and verifies all six prior contexts, strict mode and every unrelated setting preserved; its [CI and exit closeout](../roadmap/phase-02d-delivery-log.md#p02d-7-ci-and-phase-exit-closeout-2026-10-11) records the receipts. [CONTRIBUTING § Branch protection](../../.github/CONTRIBUTING.md#branch-protection-settings-on-main) owns the current list; the [P02d-4 delivery record](../roadmap/phase-02d-delivery-log.md#p02d-4-step-4-contract-sdk-and-ci) records activation verification. | +| 15 | [Performance](15-performance.md) | **Active** | P02d-7 delivers the always-running `public demo + lighthouse` job under ADR-0056: nine seeded pages, 27 audits, actual-page/source/census controls and hard normalized gzip/CLS/automated-accessibility checks. Timing medians are advisory. The [Step 4 record](../roadmap/phase-02d-delivery-log.md#p02d-7-step-4--ci-enforcement-and-phase-exit-2026-10-11) owns real CI and required-check receipts. Production p95/field telemetry/load tests remain [Phase 11](../roadmap/phase-11-production-hardening.md). | +| 16 | [Accessibility](16-accessibility.md) | **Active** | P6 delivers catalog/course/lesson and controlled-state semantics, all 31 active recommended jsx-a11y rules at error severity with per-rule actual-config dirty/clean controls, and real product HTML/Flight proofs. The [packet closeout](../roadmap/phase-02d-delivery-log.md#p02d-6-packet-closeout-2026-10-10) records keyboard/focus/reflow/contrast observations and the maintainer's passing VoiceOver smoke. This is enforcement for delivered public-page scope, not a full WCAG audit. P02d-7 adds hard Lighthouse automated accessibility and a narrow library browser walkthrough; full Playwright Test/axe remains [Phase 06](../roadmap/phase-06-renderer-admin-studio.md). | | 17 | [Code Review](17-code-review.md) | **Active** | Applied to every pull request merged so far; the zero-tolerance blocker list is in live use. | | 18 | [Audit Coverage](18-audit-coverage.md) | **Active** | Packet 9 lit the write path under [ADR-0033](../decisions/0033-audit-durability-model.md) and [ADR-0044](../decisions/0044-audit-write-path.md): classification at step 3, MUST rows on the business transaction before `COMMIT`, `audit_log` / `audit_config` with their append-only layers, and the catalogue ↔ matrix join enforced in both directions and per request/concrete integration-handler identity by `AuditCoverageTests`; actual API/Seeder catalogue parity includes Off coordinators. Retention and partitioning are [Phase 11](../roadmap/phase-11-production-hardening.md)'s. | | 19 | [Permissions](19-permissions.md) | **Adopted** | No application permission key or application role exists. P02b-5's AccountSite admission policy grants neither; the permission registry and enforcement land in [Phase 03](../roadmap/phase-03-identity-admin.md). | -| 20 | [Infrastructure Stack](20-infrastructure-stack.md) | **Active** | `ISecretProvider` shipped in Packet 3, the foundation ports and their defaults in Packet 5, and the entitlement socket in Packet 9; `DeploymentMode` branching happens once, at the composition root. P02b-2 delivers producer dispatch; P02b-3 Steps 1–5 add durable acceptance, shared inbox and independently scheduled default consumers. P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-events-auth.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. Packet 10 made the bans this document states mechanical: no module reaches a cache client, a Hub namespace, `audit_log` or `platform_entitlement_cache`, and every entitlement key a call site names is a registry member. The adapters themselves — Dapr, Kafka, Valkey, Vault, APISIX — arrive on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s triggers, which is the model rather than a gap in it. | +| 20 | [Infrastructure Stack](20-infrastructure-stack.md) | **Active** | `ISecretProvider` shipped in Packet 3, the foundation ports and their defaults in Packet 5, and the entitlement socket in Packet 9; `DeploymentMode` branching happens once, at the composition root. P02b-2 delivers producer dispatch; P02b-3 Steps 1–5 add durable acceptance, shared inbox and independently scheduled default consumers. P02b-3 is complete and merged through PR #31; its [merge closeout](../roadmap/phase-02b-delivery-log.md#p02b-3-merge-and-closeout-2026-10-15) owns final verification. Packet 10 made the bans this document states mechanical: no module reaches a cache client, a Hub namespace, `audit_log` or `platform_entitlement_cache`, and every entitlement key a call site names is a registry member. The adapters themselves — Dapr, Kafka, Valkey, Vault, APISIX — arrive on [ADR-0035](../decisions/0035-demand-gated-infrastructure.md)'s triggers, which is the model rather than a gap in it. | | 21 | [Architecture Tests Catalogue](21-architecture-tests-catalogue.md) | **Active** | The catalogue's own § Implemented today carries the counts, and `The_Catalogue_Counts_Its_Own_Rules` recomputes them, so this row does not keep a third copy. Rules run in the architecture assembly and beside it in the unit, integration and frontend suites — each where it can actually fail, against an applied schema, a real host or a real ESLint configuration. `Every_Implemented_Rule_Names_A_Test_That_Exists` holds each Implemented entry to a method of that name. `No_Architecture_Test_Is_Skippable` governs backend suites; P02d-5 delivers G38(d)'s guarded frontend runner and planted skip/todo, empty-report and omitted-workspace controls. | -P02d-4's [accepted decision package](../roadmap/phase-02d-walking-skeleton.md#p02d-4-accepted-answers) +P02d-4's [accepted decision package](../roadmap/phase-02d-delivery-log.md#p02d-4-accepted-answers) adds bootstrap, exact locale/public response, read-only mode, SDK and OpenAPI proof obligations to the relevant Active standards. -[Step 1](../roadmap/phase-02d-walking-skeleton.md#p02d-4-step-1-authority-and-read-only-foundation) +[Step 1](../roadmap/phase-02d-delivery-log.md#p02d-4-step-1-authority-and-read-only-foundation) delivers host provenance/admission and read-only transaction proofs. Step 2 adds site bootstrap, all-status no-store/HEAD behavior and Off/dispatch/controller guards. Step 3 adds Education eligibility, scoped seek pages and bounded content/label diff --git a/frontend/README.md b/frontend/README.md index bb9263ae..f41e845e 100644 --- a/frontend/README.md +++ b/frontend/README.md @@ -39,7 +39,7 @@ Before starting web, follow the root [HTTPS Quickstart](../README.md#quickstart) remain explicit developer steps. Start `make public-api` in another terminal. The native ingress serves the configured tenant hosts over HTTPS on port 3000. Direct stock `next dev/start` is unsupported. P6 implements localized public -catalog/course/lesson pages; its [closeout](../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +catalog/course/lesson pages; its [closeout](../docs/roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) records completed reviews and passing manual accessibility. P6 is complete and merged through PR #27 on 2026-10-10. P7 delivers the shared demo and narrow Playwright library/Lighthouse proof; Phase 06 owns the broader Playwright Test/axe diff --git a/frontend/apps/web/README.md b/frontend/apps/web/README.md index 1df84221..e317ee0f 100644 --- a/frontend/apps/web/README.md +++ b/frontend/apps/web/README.md @@ -26,14 +26,14 @@ entry under [ADR-0053](../../../docs/decisions/0053-trusted-public-server-render Exact scaffold roots continue only after bootstrap; enabled locale membership takes precedence. P02d-6 implements localized catalog/course/lesson pages, ordered plain-text presentation, safe four-color themes and G40 page states. Its -[product closeout](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-step-4-product-proof-and-accessibility-closeout) +[product closeout](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-step-4-product-proof-and-accessibility-closeout) records completed verification, reviews and scoped browser/VoiceOver observations. P6 is complete and merged through PR #27 on 2026-10-10; its -[merge closeout](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-6-merge-and-closeout-2026-10-10) +[merge closeout](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-6-merge-and-closeout-2026-10-10) owns final verification. P7's shared demo/browser package was approved on 2026-10-11, together with ADR-0056. The shared local/CI lifecycle and narrow Playwright library proof are delivered: nine seeded pages and 27 Lighthouse audits. -The [Step 3 record](../../../docs/roadmap/phase-02d-walking-skeleton.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) +The [Step 3 record](../../../docs/roadmap/phase-02d-delivery-log.md#p02d-7-step-3--browser-and-audit-proof-2026-10-11) owns local execution and reviews; the packet's Step 4 record and CONTRIBUTING own real CI receipts and required-check activation. Phase 06 retains the broader Playwright Test/axe suite. diff --git a/frontend/apps/web/src/test/demo-genericity-sources.ts b/frontend/apps/web/src/test/demo-genericity-sources.ts index aee36c60..fc45d374 100644 --- a/frontend/apps/web/src/test/demo-genericity-sources.ts +++ b/frontend/apps/web/src/test/demo-genericity-sources.ts @@ -66,18 +66,25 @@ const nonRuntimeFiles = new Set([ 'scripts/ci-test-shards-plan.json', 'scripts/ci-test-shard-results.py', 'scripts/connection-string.awk', + 'scripts/delivery-log-index.py', 'scripts/install-leakwatch.py', 'scripts/install-oasdiff.py', + 'scripts/markdown-fragment-audit.py', 'scripts/openapi-ci.py', 'scripts/openapi-policy.py', + 'scripts/roadmap-structure.py', 'scripts/seed.sh', 'scripts/test-adr-status.py', + 'scripts/test-markdown-link-audit.py', + 'scripts/test-markdown-fragment-audit.py', + 'scripts/test-roadmap-structure.py', 'scripts/test-ci-native-environment.py', 'scripts/test-ci-native-provisioning.py', 'scripts/test-ci-native-tests.py', 'scripts/test-ci-test-shards.py', 'scripts/test-ci-test-shard-results.py', 'scripts/test-ci-supply-chain.py', + 'scripts/test-delivery-log-index.py', 'scripts/test-openapi-ci.py', 'scripts/test-realm-node-gate.py', 'scripts/run-realm-node-tests.py', diff --git a/frontend/apps/web/src/test/public-demo-ci.test.ts b/frontend/apps/web/src/test/public-demo-ci.test.ts index 472060be..c46700a9 100644 --- a/frontend/apps/web/src/test/public-demo-ci.test.ts +++ b/frontend/apps/web/src/test/public-demo-ci.test.ts @@ -46,7 +46,59 @@ function proofScript() { return script; } -it('starts the absolute budget before checkout and reserves four minutes of the job ceiling', () => { +function browserSetup(failure = '') { + const files = fixture(); + for (const [name, body] of [ + [ + 'pnpm', + ` + printf 'pnpm %s\\n' "$*" >> "$INVOCATION" + if [ "$*" = 'install --frozen-lockfile' ]; then + [ "$FAILURE" != dependencies ] || exit 19 + elif [ "$*" = 'exec playwright install chromium' ]; then + [ "$FAILURE" != browser ] || exit 23 + else exit 99; fi + `, + ], + // Any privileged or APT call would leave a trace and fail the command. + ...['sudo', 'apt', 'apt-get', 'apt-config'].map( + (tool) => [tool, `printf '${tool} %s\\n' "$*" >> "$INVOCATION"\nexit 99`] as const, + ), + ] as const) { + writeFileSync(join(files.root, name), '#!/bin/sh\nset -eu\n' + body + '\n'); + chmodSync(join(files.root, name), 0o700); + } + const step = job?.match( + / {6}- name: Install pinned browser tools\n {8}timeout-minutes: 5\n {8}working-directory: frontend\n {8}run: \|\n((?: {10}.*\n|\n)+)/, + ); + if (!step?.[1]) throw new Error('Missing bounded browser installation command'); + const result = spawnSync('/bin/bash', ['-euo', 'pipefail', '-c', step[1]], { + env: { ...files.env, FAILURE: failure }, + encoding: 'utf8', + timeout: 10000, + }); + return { ...files, result }; +} + +it('installs only the pinned Chromium build without any APT mirror dependency', () => { + const files = browserSetup(); + expect(files.result.status).toBe(0); + expect(readFileSync(files.invocation, 'utf8').trim().split('\n')).toEqual([ + 'pnpm install --frozen-lockfile', + 'pnpm exec playwright install chromium', + ]); +}); + +it.each([ + ['dependencies', 19, ['pnpm install --frozen-lockfile']], + ['browser', 23, ['pnpm install --frozen-lockfile', 'pnpm exec playwright install chromium']], +] as const)('fails closed on browser setup %s', (failure, code, calls) => { + const files = browserSetup(failure); + expect(files.result.status).toBe(code); + expect(readFileSync(files.invocation, 'utf8').trim().split('\n')).toEqual(calls); +}); + +it('starts the absolute budget before checkout and reserves three minutes of the job ceiling', () => { const files = fixture(); const first = job?.match( /steps:\n(?: {6}#.*\n)* {6}- name: Reserve demo cleanup and artifact time\n {8}run: (.+)\n/, @@ -56,7 +108,58 @@ it('starts the absolute budget before checkout and reserves four minutes of the if (!first?.[1]) throw new Error('Missing first-step budget reservation'); const result = spawnSync('/bin/bash', ['-eu', '-c', first[1]], { env: files.env }); expect(result.status).toBe(0); - expect(readFileSync(files.environment, 'utf8')).toBe('PUBLIC_DEMO_DEADLINE=1960\n'); + expect(readFileSync(files.environment, 'utf8')).toBe('PUBLIC_DEMO_DEADLINE=2020\n'); +}); + +it('restores the existing NuGet cache without adding a cache-save post step', () => { + const cache = job?.match( + / {6}- name: Cache NuGet packages\n([\s\S]*?) {6}- name: Install pinned browser tools\n/, + )?.[1]; + expect(cache).toContain('uses: actions/cache/restore@0057852bfaa89a56745cba8c7296529d2fc39830'); + expect(cache).toContain('path: ~/.nuget/packages'); + expect(cache).toContain("hashFiles('backend/**/*.csproj', 'backend/Directory.Packages.props')"); + expect(cache).toContain('restore-keys:'); + expect(cache).not.toContain('uses: actions/cache@'); +}); + +it.each([ + ['sandbox', 0], + ['sandbox', 1], + ['sandbox', 124], + ['sandbox', 137], + ['receipt', 0], + ['receipt', 1], + ['receipt', 124], + ['receipt', 137], +] as const)('bounds the actual %s tail shell and preserves exit %s', (kind, status) => { + const files = fixture(); + writeFileSync( + join(files.root, 'timeout'), + '#!/bin/sh\nprintf "%s\\n" "$@" > "$INVOCATION"\nexit "$FORCED_EXIT"\n', + ); + const script = + kind === 'sandbox' + ? job?.match( + / {6}- name: Remove only the owned Chromium sandbox profile\n {8}if: always\(\)\n {8}timeout-minutes: 1\n {8}run: (.+)\n/, + )?.[1] + : job?.match( + / {6}- name: Record bounded workflow outcome\n {8}if: always\(\)\n {8}timeout-minutes: 1\n {8}env:\n[\s\S]*? {8}run: \|\n((?: {10}.*\n|\n)+)/, + )?.[1]; + if (!script) throw new Error('Missing actual bounded tail command'); + const result = spawnSync('/bin/bash', ['-eu', '-c', script], { + env: { ...files.env, FORCED_EXIT: String(status) }, + timeout: 10000, + }); + expect(result.status).toBe(status); + expect(readFileSync(files.invocation, 'utf8').split('\n')).toEqual([ + '--signal=TERM', + '--kill-after=5s', + '15s', + ...(kind === 'sandbox' + ? ['node', 'scripts/ci-public-chromium.mjs', 'cleanup'] + : ['python3', '-']), + '', + ]); }); it('bounds the real workflow command by the remaining budget and requests owned SIGINT cleanup', () => { diff --git a/infra/keycloak/README.md b/infra/keycloak/README.md index e75deedc..46bd84b4 100644 --- a/infra/keycloak/README.md +++ b/infra/keycloak/README.md @@ -7,7 +7,7 @@ under [ADR-0004](../../docs/decisions/0004-authentication-strategy.md) and decides development issuance; [Security 11](../../docs/standards/11-security.md#authentication) owns its ongoing rule. The -[P02b-6 accepted package](../../docs/roadmap/phase-02b-events-auth.md#p02b-6-decision-package-2026-10-20) +[P02b-6 accepted package](../../docs/roadmap/phase-02b-delivery-log.md#p02b-6-decision-package-2026-10-20) retains the earlier approval and owns safe warm-realm convergence. Authentication grants no application membership or permission; Phase 03 owns those records. @@ -34,7 +34,7 @@ against it, including the host's default organization where applicable. self-service capability in addition to their existing inert realm roles. This permits owner credential/linked-account management; it grants no LearnStack permission or membership. The - [approved adjustment](../../docs/roadmap/phase-02b-events-auth.md#account-console-self-service-capability--proposal-2026-10-21) + [approved adjustment](../../docs/roadmap/phase-02b-delivery-log.md#account-console-self-service-capability--proposal-2026-10-21) owns this explicit exception to role-assignment preservation. - The operator account remains `demo-operator@learnstack.test`; its separate realm is untouched. Neither realm's token is accepted by the other surface. @@ -201,21 +201,21 @@ P02b-6 Step 1 supplies the executable fresh import; Step 2 supplies the bounded shared Admin REST reconciler. Both completed their local review rounds. Step 3 connects `make seed` and `make demo` to the same awaited operation after application seed convergence. Its actual lifecycle qualification and reviews -are recorded in the [Step 3 delivery record](../../docs/roadmap/phase-02b-events-auth.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21). +are recorded in the [Step 3 delivery record](../../docs/roadmap/phase-02b-delivery-log.md#p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21). The exact pre-P02b-6 export has a stock profile that hides identity values and broader account-console assignments. The qualified correction handles these prerequisites without inferring account ownership from a hidden projection. [ADR-0068](../../docs/decisions/0068-development-warm-realm-qualification.md) is Accepted — 2026-10-22 after verified review corrections under conditional maintainer authority. Its three-step implementation and automatic-path proof -are tracked in the [acceptance record](../../docs/roadmap/phase-02b-events-auth.md#adr-0068-acceptance-and-implementation-2026-10-22). -The [first correction step](../../docs/roadmap/phase-02b-events-auth.md#adr-0068-step-1--qualified-stock-assignment-implementation-2026-10-22) +are tracked in the [acceptance record](../../docs/roadmap/phase-02b-delivery-log.md#adr-0068-acceptance-and-implementation-2026-10-22). +The [first correction step](../../docs/roadmap/phase-02b-delivery-log.md#adr-0068-step-1--qualified-stock-assignment-implementation-2026-10-22) adds fixed historical graph qualification and assignment-only normalization, with both independent review rounds complete. The -[second correction step](../../docs/roadmap/phase-02b-events-auth.md#adr-0068-step-2--owned-visibility-preparation-2026-10-22) +[second correction step](../../docs/roadmap/phase-02b-delivery-log.md#adr-0068-step-2--owned-visibility-preparation-2026-10-22) completes automatic preparation and fresh complete planning after both independent review rounds. The -[third correction step](../../docs/roadmap/phase-02b-events-auth.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) +[third correction step](../../docs/roadmap/phase-02b-delivery-log.md#adr-0068-step-3--complete-historical-path-qualification-2026-10-22) completes local historical seed/demo, usable credential/MFA, signed API and stored self-service proof after both review rounds. That record owns exact source-bound hosted assignments and their evidence limits; merge remains separate. @@ -230,7 +230,7 @@ An older private environment must add `KEYCLOAK_WEB_CLIENT_SECRET` explicitly before either combined entry starts stack or database work. Do not wipe the provider database to upgrade. The tool reports fixed refusal reasons, keeps partial Admin changes durable and requires an explicit verified rerun. The -[accepted account-console adjustment](../../docs/roadmap/phase-02b-events-auth.md#account-console-self-service-capability--proposal-2026-10-21) +[accepted account-console adjustment](../../docs/roadmap/phase-02b-delivery-log.md#account-console-self-service-capability--proposal-2026-10-21) is implemented; its actual stock-parity, warm-preservation, profile/API qualification and both completed independent review rounds are recorded with Step 4. Qualification applies only to the recorded source and scope; subsequent diff --git a/scripts/ci-native-tests.py b/scripts/ci-native-tests.py index 19f8367c..9f380045 100644 --- a/scripts/ci-native-tests.py +++ b/scripts/ci-native-tests.py @@ -81,9 +81,13 @@ STARTUP_FAILURES = {'resource_controllers_unavailable', 'work_cgroup_not_empty', 'cgroup_kill_unavailable', 'startup_io_refused', 'startup_internal_refusal'} FAILURE_SOURCES = { + 'OutboxProcessorTests.cs': 'outbox_processor', 'TenantRealmApiTests.WarmQualification.cs': 'realm_warm_qualification', 'BackgroundJobPositiveSdkTests.CausalRestart.cs': 'positive_sdk_causal_restart', 'BackgroundJobPositiveSdkTests.NativeSettlement.cs': 'positive_sdk_native_settlement', + 'BackgroundJobPositiveSdkTests.NativeWait.cs': 'positive_sdk_native_wait', + 'BackgroundJobPositiveSdkTests.NativeHistory.cs': 'positive_sdk_native_history', + 'BackgroundJobPositiveSdkTests.NativeHandoff.cs': 'positive_sdk_native_handoff', 'BackgroundJobPositiveSdkTests.NativeSettlementScheduling.cs': 'positive_sdk_settlement_scheduling', 'BackgroundJobPositiveSdkTests.NativeSettlementPrepare.cs': 'positive_sdk_settlement_prepare', 'BackgroundJobRecurrenceStoreTests.NativeOwnership.cs': 'recurrence_native_ownership', @@ -381,8 +385,108 @@ def closed_settlement_failure_details(raw): return result +NATIVE_WAIT_FAILURE_CASES = { + 'LearnStack.Tests.Integration.Database.BackgroundJobPositiveSdkTests.' + 'Native_stop_returns_the_wrapper_before_a_held_external_constructor_really_cleans_up(reason: "' + reason + '")' + for reason in ('host_stop', 'lease_loss') +} + + +def closed_native_wait_details(raw): + """First failure and later cleanup are separate, finite observations, never join authority.""" + messages = raw.get('Messages') + if not isinstance(messages, list) or not 1 <= len(messages) <= 32: + return None + if any(not isinstance(item, dict) or set(item) != {'Category', 'Text'} + or not isinstance(item['Category'], str) or not 1 <= len(item['Category']) <= 32 + or not isinstance(item['Text'], str) for item in messages): + return None + if sum(len(item['Text']) for item in messages) > 65536: + return None + stages = {'start', 'handoff', 'constructor', 'capture', 'cancel', 'return', 'wrapper', 'held', + 'cleanup_request', 'cleanup_stop', 'cleanup_completion', 'cleanup_complete'} + tasks = {'not_issued', 'succeeded', 'cancelled', 'faulted', 'pending'} + fields = ('boundary', 'constructor', 'invocation', 'wrapper', 'actual', 'runtime', 'completion', + 'control', 'pools', 'shared', 'bridgeLoop', 'bridgeStop') + result = {'stage': 'native_wait'} + for kind in ('failure', 'cleanup'): + marker = 'Native wait ' + kind + ';' + count = sum(item['Text'].count(marker) for item in messages) + if not count and kind == 'cleanup': + continue + lines = [line for item in messages if item['Category'] == 'StdOutMsgs' + for line in item['Text'].splitlines() if marker in line] + if count != 1 or len(lines) != 1: + return None + unavailable = re.fullmatch(re.escape(marker) + r'boundary=([a-z_]+);snapshot=unavailable\.', lines[0]) + if unavailable is not None: + values = {'boundary': unavailable[1], 'snapshot': 'unavailable'} + else: + match = re.fullmatch(re.escape(marker) + ';'.join(name + r'=([a-z_,]{1,128})' for name in fields) + r'\.', lines[0]) + if match is None: + return None + values = dict(zip(fields, match.groups())) + if values['constructor'] not in ('entered', 'pending') or values['invocation'] not in ('not_issued', 'captured'): + return None + if values['runtime'] not in {'not_started', 'bootstrapping', 'starting', 'running', 'stopping', 'retained', 'stopped', 'unknown'}: + return None + if any(values[name] not in tasks for name in ('wrapper', 'actual', 'completion', 'control', 'shared', 'bridgeLoop', 'bridgeStop')): + return None + pools = values['pools'].split(',') + if not 1 <= len(pools) <= 8 or any(value not in tasks for value in pools) or 'not_issued' in pools and len(pools) != 1: + return None + values['pools'] = pools + if values['invocation'] == 'not_issued' and (values['wrapper'] != 'not_issued' or values['actual'] != 'not_issued'): + return None + if values['boundary'] not in stages or kind == 'cleanup' and not values['boundary'].startswith('cleanup_'): + return None + result[kind] = values + return result + + +OUTBOX_STARTUP_FAILURE_CASES = { + 'LearnStack.Tests.Integration.Database.OutboxProcessorTests.' + 'Actual_host_startup_rejects_invalid_credentials_without_provider_or_secret_text(invalid: "' + value + '")' + for value in ('missing', 'malformed', 'wrong-user', 'unreachable') +} + + +def closed_outbox_startup_details(raw): + messages = raw.get('Messages') + if not isinstance(messages, list) or not 1 <= len(messages) <= 32: + return None + if any(not isinstance(item, dict) or set(item) != {'Category', 'Text'} + or not isinstance(item['Category'], str) or not 1 <= len(item['Category']) <= 32 + or not isinstance(item['Text'], str) for item in messages): + return None + if sum(len(item['Text']) for item in messages) > 65536: + return None + result = {'stage': 'outbox_startup'} + for kind in ('result', 'completion'): + marker = 'Outbox startup ' + kind + ';' + lines = [line for item in messages if item['Category'] == 'StdOutMsgs' + for line in item['Text'].splitlines() if marker in line] + if sum(item['Text'].count(marker) for item in messages) != 1 or len(lines) != 1: + return None + match = re.fullmatch(re.escape(marker) + r'outcome=(succeeded|timeout|cancelled|refused|other);' + r'startup=(succeeded|cancelled|faulted|pending)[.]', lines[0]) + if match is None or kind == 'completion' and match[2] == 'pending': + return None + if (kind == 'completion' and (match[1] == 'succeeded') != (match[2] == 'succeeded') + or kind == 'result' and match[1] == 'succeeded' and match[2] != 'succeeded'): + return None + result[kind] = {'outcome': match[1], 'startup': match[2]} + if result['result']['startup'] != 'pending' and result['result']['startup'] != result['completion']['startup']: + return None + return result + + def closed_failure_details(case, raw): """Decode only existing test-owned finite facts; raw error text never leaves this function.""" + if case['name'] in OUTBOX_STARTUP_FAILURE_CASES: + return closed_outbox_startup_details(raw) if case['assembly'] == 'learnstack.tests.integration' else None + if case['name'] in NATIVE_WAIT_FAILURE_CASES: + return closed_native_wait_details(raw) if case['assembly'] == 'learnstack.tests.integration' else None if case['name'] == RECURRENCE_NATIVE_FAILURE_CASE: return closed_recurrence_native_details(raw) if case['assembly'] == 'learnstack.tests.integration' else None if case['name'] in SETTLEMENT_FAILURE_CASES: diff --git a/scripts/ci-test-shard-results.py b/scripts/ci-test-shard-results.py index 166280d3..c734b3b1 100644 --- a/scripts/ci-test-shard-results.py +++ b/scripts/ci-test-shard-results.py @@ -29,6 +29,9 @@ MAX_EXPANDED = 128 * 1024 * 1024 AGGREGATE_SECONDS = 5 * 60 UPLOAD_SECONDS = 60 +METADATA_SECONDS = 30 +METADATA_OBSERVATIONS = 16 +METADATA_PACING_SECONDS = 2 REQUIRED = { 'backend': 'backend (build + unit + arch + contract)', 'backend-integration': 'backend integration (Testcontainers)', @@ -329,7 +332,17 @@ def verify_run(run, context): or not pulls and fork), 'run_pull_identity_mismatch') -def verify_jobs(jobs, context, plan, scope): +class PendingProducerMetadata(Exception): + def __init__(self, owner, gate): + self.owner, self.gate = owner, gate + + +def pending_state(value): + return (value.get('status') in ('queued', 'in_progress') + and 'conclusion' in value and value['conclusion'] is None) + + +def verify_jobs(jobs, context, plan, scope, *, allow_pending=False): owners = ['base'] + ['architecture-' + str(i) for i in range(plan['counts']['architecture'])] if scope == 'integration': owners = ['base', 'native'] + ['ordinary-' + str(i) for i in range(plan['counts']['ordinary'])] @@ -349,21 +362,84 @@ def verify_jobs(jobs, context, plan, scope): require(job['name'] not in by_name, 'job_api_duplicate_producer') by_name[job['name']] = job require(names <= set(by_name), 'current_attempt_producer_missing') - result = {} + result, pending = {}, None for owner in owners: job = by_name[producer_name(owner)] - require(job.get('status') == 'completed' and job.get('conclusion') == 'success', 'producer_not_successful') - start, end = timestamp(job.get('started_at')), timestamp(job.get('completed_at')) - require(0 < end - start <= 20 * 60, 'producer_ceiling_exceeded') + completed = job.get('status') == 'completed' and job.get('conclusion') == 'success' + waiting = allow_pending and pending_state(job) + if not completed and not waiting: + status, conclusion = job.get('status'), job.get('conclusion') + print(json.dumps({'protocol': 1, 'diagnostic': 'producer_state_refusal', 'owner': owner, + 'status': status if status in ('queued', 'in_progress', 'completed') else 'other', + 'conclusion': conclusion if conclusion in ('success', 'failure', 'neutral', 'cancelled', + 'skipped', 'timed_out', 'action_required', 'startup_failure', 'stale') else 'other'}, + sort_keys=True), file=sys.stderr) + require(completed or waiting, 'producer_not_successful') + created = timestamp(job.get('created_at')) + if completed: + start, end = timestamp(job.get('started_at')), timestamp(job.get('completed_at')) + require(created <= start, 'api_timestamp_invalid') + require(0 < end - start <= 20 * 60, 'producer_ceiling_exceeded') + else: + require('completed_at' in job and job['completed_at'] is None + and 'started_at' in job, 'api_timestamp_invalid') + if job['status'] == 'in_progress': + require(created <= timestamp(job['started_at']), 'api_timestamp_invalid') + else: + require(job['started_at'] is None, 'api_timestamp_invalid') + pending = pending or (owner, 'job') steps = job.get('steps', []) + require(isinstance(steps, list) and all(isinstance(step, dict) for step in steps), + 'producer_gate_not_successful') for name in (BUILD_STEP, EXECUTE_STEP, UPLOAD_STEP): matches = [step for step in steps if step.get('name') == name] - require(len(matches) == 1 and matches[0].get('status') == 'completed' - and matches[0].get('conclusion') == 'success', 'producer_gate_not_successful') + successful = (len(matches) == 1 and matches[0].get('status') == 'completed' + and matches[0].get('conclusion') == 'success') + waiting = allow_pending and len(matches) == 1 and pending_state(matches[0]) + gate = {BUILD_STEP: 'build', EXECUTE_STEP: 'execute', UPLOAD_STEP: 'upload'}[name] + if not successful and not waiting: + # Retain only finite gate/state words, never arbitrary API text. + step = matches[0] if len(matches) == 1 else {} + status, conclusion = step.get('status'), step.get('conclusion') + print(json.dumps({'protocol': 1, 'diagnostic': 'producer_gate_refusal', + 'owner': owner, 'gate': gate, + 'matches': 'one' if len(matches) == 1 else 'missing' if not matches else 'multiple', + 'status': status if status in ('queued', 'in_progress', 'completed') else 'other', + 'conclusion': conclusion if conclusion in ('success', 'failure', 'neutral', 'cancelled', + 'skipped', 'timed_out', 'action_required', 'startup_failure', 'stale') else 'other'}, + sort_keys=True), file=sys.stderr) + require(successful or waiting, 'producer_gate_not_successful') + if waiting: + pending = pending or (owner, gate) result[owner] = job + if pending: + # Scan the complete snapshot before waiting: an earlier pending owner + # must never hide another owner's terminal failure or malformed gate. + raise PendingProducerMetadata(*pending) return result +def acquire_jobs(deadline, context, plan, scope): + # A separate read owner narrows every paginated request to one fixed + # acquisition window. Artifact work retains the original aggregate deadline. + api = Api(min(deadline, time.monotonic() + METADATA_SECONDS)) + for observation in range(1, METADATA_OBSERVATIONS + 1): + require(time.monotonic() < api.deadline, 'producer_metadata_deadline_exhausted') + try: + result = verify_jobs(api.jobs(context), context, plan, scope, allow_pending=True) + except PendingProducerMetadata as pending: + print(json.dumps({'protocol': 1, 'diagnostic': 'producer_metadata_pending', + 'observation': observation, 'owner': pending.owner, 'gate': pending.gate}, + sort_keys=True), file=sys.stderr) + require(observation < METADATA_OBSERVATIONS + and time.monotonic() + METADATA_PACING_SECONDS < api.deadline, + 'producer_metadata_deadline_exhausted') + time.sleep(METADATA_PACING_SECONDS) + else: + require(time.monotonic() < api.deadline, 'producer_metadata_deadline_exhausted') + return result + + def verify_artifact(metadata, context, owner, job): name = artifact_name(context, owner) require(isinstance(metadata, dict) and type(metadata.get('total_count')) is int @@ -562,7 +638,7 @@ def aggregate(scope): api = Api(deadline) run = api.fetch('actions/runs/' + context['runId'] + '/attempts/' + context['runAttempt']) verify_run(run, context) - jobs = verify_jobs(api.jobs(context), context, plan, scope) + jobs = acquire_jobs(deadline, context, plan, scope) output = ROOT / 'artifacts' / ('ci-aggregate-' + scope) output.mkdir(parents=True, exist_ok=False) retained = {} diff --git a/scripts/delivery-log-index.py b/scripts/delivery-log-index.py new file mode 100644 index 00000000..79f86627 --- /dev/null +++ b/scripts/delivery-log-index.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +"""Generate, or check, the index that opens each delivery log (ADR-0069, 2026-10-23). + +A row is a packet section, an entry, or a dated heading deeper than an entry, with +its anchor and its length in lines. Lengths, not line numbers: the index sits above +every heading, so one new row would renumber them all. Rows carry no inferred kind; +the heading text already says what a record is. + + python3 scripts/delivery-log-index.py # fail when an index is stale + python3 scripts/delivery-log-index.py --write # regenerate every index +""" +import importlib.util +import re +import sys +from pathlib import Path + +HERE = Path(__file__).resolve().parent +_SPEC = importlib.util.spec_from_file_location('markdown_fragment_audit', HERE / 'markdown-fragment-audit.py') +_AUDIT = importlib.util.module_from_spec(_SPEC) +_SPEC.loader.exec_module(_AUDIT) + +BEGIN = ('<!-- BEGIN GENERATED INDEX: scripts/delivery-log-index.py — ' + 'run `make docs-index`; do not edit by hand -->') +END = '<!-- END GENERATED INDEX -->' +DATE = re.compile(r'\b\d{4}-\d{2}-\d{2}\b') +LINK_TEXT = re.compile(r'\[([^\]]*)\]\([^)]*\)') + + +def headings(lines): + """(index, level, text, anchor) in file order, with GitHub's duplicate numbering.""" + seen, found, fence = {}, [], False + for index, line in enumerate(lines): + if _AUDIT.FENCE.match(line): + fence = not fence + continue + match = None if fence else _AUDIT.HEADING.match(line) + if match: + base = _AUDIT.slug(match.group(2)) + count = seen.get(base, 0) + seen[base] = count + 1 + found.append((index, len(match.group(1)), match.group(2), base if count == 0 else f'{base}-{count}')) + return found + + +def rows(lines): + """The index list: ## sections, every ###, and each deeper heading that carries a date.""" + found = headings(lines) + result, stack = [], [] + for position, (index, level, text, anchor) in enumerate(found): + if level < 2 or (level > 3 and not DATE.search(text)): + continue + end = next((other for other, depth, _, _ in found[position + 1:] if depth <= level), len(lines)) + while stack and stack[-1] >= level: + stack.pop() + title = LINK_TEXT.sub(r'\1', text) + result.append(f'{" " * len(stack)}- [{title}](#{anchor}) — {end - index:,} lines') + stack.append(level) + return result + + +def block(lines): + return [BEGIN, '', '**Index**', ''] + rows(lines) + ['', END] + + +def locate(lines): + """(start, end) of the generated block, or the reason it cannot be used.""" + starts = [index for index, line in enumerate(lines) if line == BEGIN] + ends = [index for index, line in enumerate(lines) if line == END] + if len(starts) != 1 or len(ends) != 1 or ends[0] < starts[0]: + return None, 'needs exactly one generated index block' + first = next((index for index, level, _, _ in headings(lines) if level == 2), len(lines)) + if ends[0] >= first: + return None, 'its generated index must close before the first ## section' + return (starts[0], ends[0]), None + + +def regenerate(text): + """The log with its index block rebuilt; raises when the block is missing or misplaced.""" + lines = text.split('\n') + span, reason = locate(lines) + if span is None: + raise ValueError(reason) + start, end = span + return '\n'.join(lines[:start] + block(lines) + lines[end + 1:]) + + +def logs(root): + return sorted((Path(root) / 'docs/roadmap').glob('phase-*-delivery-log.md')) + + +def main(argv): + root = HERE.parent + write = argv[1:] == ['--write'] + if argv[1:] not in ([], ['--write']): + print('usage: delivery-log-index.py [--write]', file=sys.stderr) + return 2 + problems = [] + for path in logs(root): + text = path.read_text(encoding='utf-8') + name = path.relative_to(root) + try: + fresh = regenerate(text) + except ValueError as error: + problems.append(f'{name}: {error}') + continue + if fresh == text: + continue + if write: + path.write_text(fresh, encoding='utf-8') + print(f'regenerated {name}') + else: + problems.append(f'{name}: its index is stale; run `make docs-index`') + for problem in problems: + print(f'DELIVERY LOG INDEX: {problem}') + if problems: + print(f'::error::{len(problems)} delivery log index problem(s); see ADR-0069.') + return 1 + if not write: + print(f'Delivery log indexes: {len(logs(root))} current.') + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/scripts/markdown-fragment-audit.py b/scripts/markdown-fragment-audit.py new file mode 100644 index 00000000..822efa64 --- /dev/null +++ b/scripts/markdown-fragment-audit.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Fail on a relative link whose #fragment names no heading or anchor in its target. + +ADR-0069: the Markdown link audit checks that a target file exists and strips the +fragment first, so a moved or renamed heading broke every link into it silently. +This audit reads the whole tree, because a heading edited in one file breaks links +in files the change never touched. +""" +import re +import subprocess +import sys +from pathlib import Path + +SOURCES = {'.md', '.cs', '.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'} +FENCE = re.compile(r'^\s*(```|~~~)') +HEADING = re.compile(r'^ {0,3}(#{1,6})\s+(.*?)(?:\s+#+)?\s*$') +CODE_SPAN = re.compile(r'(`+)(?:(?!\1).)+?\1') +LINK = re.compile(r'\]\(\s*<?([^)\s>]+)>?(?:\s+"[^"]*")?\s*\)|\bhref="([^"]+)"') +EXPLICIT = re.compile(r'<a\s+[^>]*\b(?:id|name)="([^"]+)"') +SCHEME = re.compile(r'^[A-Za-z][A-Za-z0-9+.-]*:') + + +def slug(text): + """GitHub's heading anchor: link text kept, code ticks and punctuation dropped.""" + text = re.sub(r'\[([^\]]*)\]\([^)]*\)', r'\1', text) + text = text.replace('`', '').strip().lower() + return re.sub(r'[^\w\- ]', '', text).replace(' ', '-') + + +def anchors(text): + """Every fragment a GitHub rendering of this Markdown answers, duplicates numbered.""" + seen, found, fence = {}, set(), False + for line in text.splitlines(): + if FENCE.match(line): + fence = not fence + continue + if fence: + continue + heading = HEADING.match(line) + if heading: + base = slug(heading.group(2)) + count = seen.get(base, 0) + found.add(base if count == 0 else f'{base}-{count}') + seen[base] = count + 1 + found.update(EXPLICIT.findall(line)) + return found + + +def links(path, text): + """(line number, target) for each link carrying a fragment; fences and code spans are samples.""" + markdown = path.suffix == '.md' + fence = False + for number, line in enumerate(text.splitlines(), 1): + if markdown and FENCE.match(line): + fence = not fence + continue + if fence: + continue + if markdown: + line = CODE_SPAN.sub('', line) + for match in LINK.finditer(line): + target = match.group(1) or match.group(2) + if '#' in target and not SCHEME.match(target): + yield number, target + + +def resolve(root, source, path): + """The Markdown file a link names, source-relative first, then repository-relative.""" + if not path: + return source + for candidate in (source.parent / path, root / path): + candidate = candidate.resolve() + if candidate.is_relative_to(root) and candidate.is_file(): + return candidate + return None + + +def audit(root, files): + root = root.resolve() + cache, problems, checked = {}, [], 0 + for relative in files: + source = root / relative + if source.suffix not in SOURCES or not source.is_file(): + continue + text = source.read_text(encoding='utf-8', errors='replace') + for number, target in links(source, text): + path, fragment = target.split('#', 1) + destination = resolve(root, source, path.split('?', 1)[0]) + # A missing file is the link audit's finding; a code file's line anchor is GitHub's. + if destination is None or destination.suffix != '.md': + continue + if destination not in cache: + cache[destination] = anchors(destination.read_text(encoding='utf-8', errors='replace')) + checked += 1 + if fragment not in cache[destination]: + problems.append(f'{relative}:{number}: #{fragment} is not an anchor of ' + f'{destination.relative_to(root)}') + return problems, checked + + +def tracked(root): + """Tracked and new unignored files; nested repositories such as worktrees are skipped.""" + listing = subprocess.run(['git', 'ls-files', '--cached', '--others', '--exclude-standard'], + cwd=root, capture_output=True, text=True, check=True).stdout + return sorted({line for line in listing.splitlines() if line and not line.endswith('/')}) + + +def main(): + root = Path(__file__).resolve().parents[1] + problems, checked = audit(root, tracked(root)) + for problem in problems: + print(f'BROKEN FRAGMENT: {problem}') + if problems: + print(f'::error::{len(problems)} link fragment(s) name no heading or anchor (ADR-0069).') + return 1 + print(f'Markdown fragment audit: {checked} fragment links resolve.') + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/roadmap-structure.py b/scripts/roadmap-structure.py new file mode 100644 index 00000000..ed31c751 --- /dev/null +++ b/scripts/roadmap-structure.py @@ -0,0 +1,233 @@ +#!/usr/bin/env python3 +"""Hold phase documents, delivery logs and the status carriers to ADR-0069. + +The phase document is the plan, the delivery log is the record, and packet status +lives once. Every budget except the whole-file one counts non-blank lines. +""" +import re +import sys +from pathlib import Path + +ROADMAP = Path('docs/roadmap') +PLAN = ('Goal', 'Scope', 'Deliverables', 'Completion Criteria', 'Risks', 'Phase Exit Decision') +POINTER = ('Goal', 'Scope on the LearnStack side', 'Trigger', 'Phase Exit Decision') +# Roadmap § Phase Structure's declared shapes; Phase 01 also keeps its long annotation block. +SHAPES = { + 'phase-01-repository-tooling.md': ('Goal', 'Scope', 'Deliverables', 'Completion Criteria', + 'Technical Notes', 'Risks'), + 'phase-09b-hub-billing.md': POINTER, + 'phase-12-hub-marketplace.md': POINTER, +} +UNBOUNDED_STATUS = {'phase-01-repository-tooling.md'} +# Phase 02a closed on 2026-09-12 with its records inside the file; ADR-0069 keeps it frozen. +FROZEN = {'phase-02a-kernel-tenancy.md'} +# Entries whose headings predate the dating rule, moved verbatim on 2026-10-22. +UNDATED_ENTRIES = { + 'phase-02d-delivery-log.md': { + 'Delivery Record (P02d-1)', 'Pending Course Marketplace proposal', + 'Delivery record: P02d-3', 'P02d-4 Step 3: public Education reads', + 'P02d-4 Step 4: contract, SDK and CI', 'P02d-5 delivery record', + 'P02d-6 Step 1: Localization and document foundation', + 'P02d-6 Step 2: Catalog and course pages', + 'P02d-6 Step 3: Ordered lesson presentation', + 'P02d-6 Step 4: Product proof and accessibility closeout', + }, +} +LOG_SECTIONS = ('Phase entry', 'Cross-packet records', 'Status archive') +STATUS_BUDGET, FILE_BUDGET, INDEX_ENTRY_BUDGET = 40, 2000, 6 +CARRIERS = {'CLAUDE.md': ('What state this is in', 'Where to start'), + 'README.md': ('Where it is today',)} + +NAME = re.compile(r'^phase-(\d{2}[a-z]?)-([a-z0-9-]+)\.md$') +FENCE = re.compile(r'^\s*(```|~~~)') +HEADING = re.compile(r'^(#{1,6})\s+(.*?)\s*$') +DATE = re.compile(r'\b\d{4}-\d{2}-\d{2}\b') +RECORD = re.compile(r'\b\d{4}-\d{2}-\d{2}\b|\bP\d{2}[a-z]?-\d+' + r'|\b(?:delivery record|review round|closeout|decision (?:package|pass))', + re.IGNORECASE) +LOG_LINK = re.compile(r'(?:\]\(|href=")[^)"\s]*phase-\d{2}[a-z]?-delivery-log\.md') + + +def headings(lines): + """(index, level, text) outside fenced blocks.""" + fence = False + for index, line in enumerate(lines): + if FENCE.match(line): + fence = not fence + continue + match = None if fence else HEADING.match(line) + if match: + yield index, len(match.group(1)), match.group(2) + + +def nonblank(lines): + return sum(1 for line in lines if line.strip()) + + +def section(lines, title, level=2): + """The lines of one heading's section, or None when the heading is missing.""" + found = [index for index, depth, text in headings(lines) if depth == level and text == title] + if len(found) != 1: + return None + start = found[0] + end = next((index for index, depth, _ in headings(lines) if index > start and depth <= level), + len(lines)) + return lines[start:end] + + +def classify(name): + match = NAME.match(name) + if not match: + return None, None + phase, topic = match.groups() + if topic == 'delivery-log': + return 'log', phase + if topic == 'exit-evidence': + return 'evidence', phase + return 'phase', phase + + +def check_phase(name, lines, has_log): + problems = [] + found = [(index, text) for index, depth, text in headings(lines) if depth == 2] + titles = [text for _, text in found] + required = SHAPES.get(name, PLAN) + position = 0 + for title in titles: + if position < len(required) and title == required[position]: + position += 1 + if position < len(required): + problems.append(f'{name}: missing or out of order: ## {required[position]}') + elif titles and titles[-1] != required[-1]: + last = max(index for index, text in found if text == required[-1]) + after = [text for index, text in found if index > last] + problems.append(f'{name}: nothing may follow ## {required[-1]}; found ## {after[0]}') + for index, _, text in headings(lines): + if index > 0 and RECORD.search(text): + problems.append(f'{name}:{index + 1}: record heading in a phase document ' + f'(move it to the delivery log): {text}') + first = found[0][0] if found else len(lines) + status = lines[1:first] + if name not in UNBOUNDED_STATUS and nonblank(status) > STATUS_BUDGET: + problems.append(f'{name}: Status block has {nonblank(status)} non-blank lines; ' + f'the budget is {STATUS_BUDGET}') + if len(lines) > FILE_BUDGET: + problems.append(f'{name}: {len(lines)} lines; the budget is {FILE_BUDGET} — ' + 'split the phase rather than raise it') + log = name.split('-', 2)[0] + '-' + name.split('-', 2)[1] + '-delivery-log.md' + if has_log and not any(f']({log})' in line or f']({log}#' in line for line in status): + problems.append(f'{name}: its Status block does not link {log}') + return problems + + +def check_log(name, phase, lines, phase_docs): + problems = [] + if len(phase_docs) != 1: + problems.append(f'{name}: needs exactly one phase document phase-{phase}-<topic>.md, ' + f'found {len(phase_docs)}') + elif not any(f']({phase_docs[0]})' in line for line in lines[:next( + (index for index, depth, _ in headings(lines) if depth == 2), len(lines))]): + problems.append(f'{name}: its introduction does not link {phase_docs[0]}') + packet = re.compile(rf'^P{re.escape(phase)}-(\d+)[a-z]? — \S') + numbers, current, seen_packet = [], None, False + sections = [(index, text) for index, depth, text in headings(lines) if depth == 2] + for position, (index, text) in enumerate(sections): + match = packet.match(text) + if match: + numbers.append(int(match.group(1))) + seen_packet = True + elif text not in LOG_SECTIONS: + problems.append(f'{name}:{index + 1}: ## {text} is neither a packet section ' + f'(P{phase}-<n> — <title>) nor one of {", ".join(LOG_SECTIONS)}') + elif text == 'Phase entry' and seen_packet: + problems.append(f'{name}:{index + 1}: ## Phase entry precedes every packet section') + elif text == 'Status archive' and position != len(sections) - 1: + problems.append(f'{name}:{index + 1}: ## Status archive is the last section') + if numbers != sorted(set(numbers)): + problems.append(f'{name}: packet sections are not in packet order: {numbers}') + legacy = UNDATED_ENTRIES.get(name, set()) + for index, depth, text in headings(lines): + if depth == 2: + current = text + elif depth == 3 and current != 'Status archive' and not DATE.search(text) and text not in legacy: + problems.append(f'{name}:{index + 1}: entry heading carries no date: {text}') + return problems + + +def check_index(lines): + problems = [] + phases = section(lines, 'Phases') + if phases is None: + return ['docs/roadmap/README.md: ## Phases is missing'] + entry = None + # An entry is a top-level item and its indented continuation, blank lines included. + for line in phases[1:] + ['<end>']: + if line.startswith('- ') or (line.strip() and not line.startswith(' ')): + if entry and nonblank(entry) > INDEX_ENTRY_BUDGET: + problems.append(f'docs/roadmap/README.md: § Phases entry has {nonblank(entry)} ' + f'non-blank lines; the budget is {INDEX_ENTRY_BUDGET}: {entry[0][:70]}') + entry = [line] if line.startswith('- ') else None + elif entry is not None: + entry.append(line) + if LOG_LINK.search(line): + problems.append('docs/roadmap/README.md: § Phases links a delivery log; ' + 'link the phase document instead') + return problems + + +def check_carrier(name, lines): + problems = [] + for number, line in enumerate(lines, 1): + if LOG_LINK.search(line): + problems.append(f'{name}:{number}: links a delivery log; link the phase document instead') + for title in CARRIERS[name]: + body = section(lines, title) + if body is None: + problems.append(f'{name}: ## {title} is missing') + elif nonblank(body) > STATUS_BUDGET: + problems.append(f'{name}: § {title} has {nonblank(body)} non-blank lines; ' + f'the budget is {STATUS_BUDGET}') + return problems + + +def check(root): + root = Path(root) + roadmap = root / ROADMAP + names = sorted(path.name for path in roadmap.glob('phase-*.md')) + classes = {name: classify(name) for name in names} + problems = [f'{ROADMAP / name}: not phase-<id>-<topic>.md' for name, (kind, _) in classes.items() + if kind is None] + docs = {} + for name, (kind, phase) in classes.items(): + if kind == 'phase': + docs.setdefault(phase, []).append(name) + logs = {phase for kind, phase in classes.values() if kind == 'log'} + for name, (kind, phase) in classes.items(): + lines = (roadmap / name).read_text(encoding='utf-8').splitlines() + if kind == 'phase' and name not in FROZEN: + problems += check_phase(name, lines, phase in logs) + elif kind == 'log': + problems += check_log(name, phase, lines, docs.get(phase, [])) + elif kind == 'evidence' and not docs.get(phase): + problems.append(f'{name}: no phase document for its phase') + problems += check_index((roadmap / 'README.md').read_text(encoding='utf-8').splitlines()) + for name in CARRIERS: + problems += check_carrier(name, (root / name).read_text(encoding='utf-8').splitlines()) + return problems + + +def main(): + root = Path(__file__).resolve().parents[1] + problems = check(root) + for problem in problems: + print(f'ROADMAP STRUCTURE: {problem}') + if problems: + print(f'::error::{len(problems)} roadmap structure violation(s); see ADR-0069.') + return 1 + print('Roadmap structure: phase documents, delivery logs, the roadmap index, ' + 'CLAUDE.md and README.md conform to ADR-0069.') + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/scripts/test-ci-native-tests.py b/scripts/test-ci-native-tests.py index c32caa24..f016b877 100644 --- a/scripts/test-ci-native-tests.py +++ b/scripts/test-ci-native-tests.py @@ -430,8 +430,10 @@ def test_failed_protocol_retains_only_closed_source_codes_and_bounded_line_numbe and row['outcome'] == 'Failed' for row in rows)) expected = {path.name for path in (ROOT / 'backend/tests/LearnStack.Tests.Integration/Database').glob( 'BackgroundJobRuntimeFacadeTests*.cs')} | { - 'BackgroundJobPositiveSdkTests.CausalRestart.cs', + 'OutboxProcessorTests.cs', 'BackgroundJobPositiveSdkTests.CausalRestart.cs', 'BackgroundJobPositiveSdkTests.NativeSettlement.cs', 'PublicAdmissionRenderingTests.cs', + 'BackgroundJobPositiveSdkTests.NativeWait.cs', 'BackgroundJobPositiveSdkTests.NativeHistory.cs', + 'BackgroundJobPositiveSdkTests.NativeHandoff.cs', 'BackgroundJobPositiveSdkTests.NativeSettlementScheduling.cs', 'BackgroundJobPositiveSdkTests.NativeSettlementPrepare.cs', 'BackgroundJobRecurrenceStoreTests.NativeOwnership.cs', @@ -776,6 +778,139 @@ def test_recurrence_native_actual_protocol_keeps_failure_and_sanitizes_private_o self.assertEqual([], ET.parse(trx).findall('.//t:Output', self.owner.NS)) self.refuses('results_incomplete', self.owner.validate_results, output, cases[:1]) + def test_outbox_startup_details_keep_observed_timeout_separate_from_actual_completion(self): + for name in self.owner.OUTBOX_STARTUP_FAILURE_CASES: + case = self.case(1, name) + for outcome, state, actual, complete in ( + ('refused', 'faulted', 'refused', 'faulted'), + ('timeout', 'pending', 'refused', 'faulted'), + ('timeout', 'succeeded', 'succeeded', 'succeeded'), + ('cancelled', 'cancelled', 'cancelled', 'cancelled')): + raw = {'Messages': [{'Category': 'StdOutMsgs', 'Text': + 'Outbox startup result;outcome=' + outcome + ';startup=' + state + '.\n' + 'Outbox startup completion;outcome=' + actual + ';startup=' + complete + '.'}]} + self.assertEqual({'stage': 'outbox_startup', 'result': {'outcome': outcome, 'startup': state}, + 'completion': {'outcome': actual, 'startup': complete}}, + self.owner.closed_failure_details(case, raw)) + + def test_outbox_startup_details_refuse_wrong_cases_private_ambiguous_or_unjoined_facts(self): + name = next(iter(self.owner.OUTBOX_STARTUP_FAILURE_CASES)) + case = self.case(1, name) + sentence = ('Outbox startup result;outcome=timeout;startup=pending.\n' + 'Outbox startup completion;outcome=refused;startup=faulted.') + for text in (sentence + '\n' + sentence, sentence.replace('outcome=timeout', 'outcome=PRIVATE-CANARY'), + sentence.replace('startup=pending', 'startup=PRIVATE-CANARY'), + sentence.replace('startup=faulted', 'startup=pending'), + sentence.replace('outcome=refused', 'outcome=succeeded'), + sentence.replace('startup=pending', 'startup=cancelled'), + sentence.replace('result;outcome=timeout;startup=pending', 'result;outcome=succeeded;startup=pending'), + sentence.replace('result;', 'result;\x00'), sentence + ' PRIVATE-CANARY', + 'x' * 65536 + sentence, sentence.split('\n')[0]): + self.assertIsNone(self.owner.closed_failure_details(case, + {'Messages': [{'Category': 'StdOutMsgs', 'Text': text}]})) + for messages in (None, [], ['PRIVATE-CANARY'], [{'Category': 'Error', 'Text': sentence}], + [{'Category': 'StdOutMsgs', 'Text': sentence, 'Private': 'canary'}]): + self.assertIsNone(self.owner.closed_failure_details(case, {'Messages': messages})) + for changed in ({**case, 'assembly': 'learnstack.tests.unit'}, {**case, 'name': name + 'Other'}): + self.assertIsNone(self.owner.closed_failure_details(changed, + {'Messages': [{'Category': 'StdOutMsgs', 'Text': sentence}]})) + + def test_outbox_startup_protocol_keeps_finite_failure_details_and_sanitized_results(self): + case = self.case(1, next(iter(self.owner.OUTBOX_STARTUP_FAILURE_CASES))) + for outcome in (1, 2): + stream = io.StringIO() + progress = self.progress(self.root / ('outbox-' + str(outcome) + '.diag'), 'LearnStack.Tests.Integration', [case], stream) + item = self.execution_result(case, outcome) + item['ErrorStackTrace'] = '/private/PRIVATE-CANARY/OutboxProcessorTests.cs:line 207' + item['Messages'] = [{'Category': 'StdOutMsgs', 'Text': + 'Outbox startup result;outcome=timeout;startup=pending.\n' + 'Outbox startup completion;outcome=refused;startup=faulted.\nPRIVATE-CANARY'}] + with contextlib.redirect_stdout(io.StringIO()): + progress.results({'NewTestResults': [item]}) + self.assertEqual(bool(progress.failure_locations), outcome == 2) + if outcome == 2: + self.assertEqual([{'source': 'outbox_processor', 'line': 207}], progress.failure_locations[0]['locations']) + self.assertEqual('outbox_startup', progress.failure_locations[0]['details']['stage']) + exported = stream.getvalue() + json.dumps(progress.failure_locations) + self.assertNotIn('PRIVATE-CANARY', exported) + self.assertNotIn('/private/', exported) + self.assertNotIn('Outbox startup result;', exported) + + @staticmethod + def native_wait_sentence(kind='failure', **changes): + values = dict(boundary='constructor', constructor='pending', invocation='not_issued', + wrapper='not_issued', actual='not_issued', runtime='running', completion='pending', + control='succeeded', pools='pending,pending,pending', shared='pending', + bridgeLoop='pending', bridgeStop='not_issued') + values.update(changes) + return 'Native wait ' + kind + ';' + ';'.join(key + '=' + value for key, value in values.items()) + '.' + + def test_native_wait_details_preserve_first_boundary_and_separate_real_cleanup_observations(self): + parse = self.owner.closed_failure_details + for name in self.owner.NATIVE_WAIT_FAILURE_CASES: + case = {**self.case(1), 'name': name} + failure = self.native_wait_sentence() + cleanup = self.native_wait_sentence('cleanup', boundary='cleanup_stop', runtime='stopping', + pools='succeeded,pending,succeeded', control='succeeded') + raw = {'Messages': [{'Category': 'StdOutMsgs', 'Text': 'PRIVATE-CANARY\n' + failure + '\n' + cleanup}]} + result = parse(case, raw) + self.assertEqual('constructor', result['failure']['boundary']) + self.assertEqual('cleanup_stop', result['cleanup']['boundary']) + self.assertEqual(['succeeded', 'pending', 'succeeded'], result['cleanup']['pools']) + self.assertEqual('native_wait', result['stage']) + self.assertNotIn('PRIVATE-CANARY', json.dumps(result)) + self.assertIsNone(parse({**case, 'assembly': 'unregistered'}, raw)) + self.assertIsNone(parse({**case, 'name': 'other'}, raw)) + for boundary in ('start', 'handoff', 'capture', 'cancel', 'return', 'wrapper', 'held', + 'cleanup_request', 'cleanup_stop', 'cleanup_completion'): + self.assertEqual(boundary, parse(case, {'Messages': [{'Category': 'StdOutMsgs', + 'Text': self.native_wait_sentence(boundary=boundary)}]})['failure']['boundary']) + + def test_native_wait_details_accept_unavailable_projection_without_inventing_join_facts(self): + case = {**self.case(1), 'name': sorted(self.owner.NATIVE_WAIT_FAILURE_CASES)[0]} + parse = self.owner.closed_failure_details + raw = {'Messages': [{'Category': 'StdOutMsgs', 'Text': + 'Native wait failure;boundary=cleanup_stop;snapshot=unavailable.\n' + 'Native wait cleanup;boundary=cleanup_stop;snapshot=unavailable.'}]} + result = parse(case, raw) + self.assertEqual({'boundary': 'cleanup_stop', 'snapshot': 'unavailable'}, result['failure']) + self.assertEqual(result['failure'], result['cleanup']) + + def test_native_wait_details_refuse_ambiguous_private_or_inconsistent_observations(self): + case = {**self.case(1), 'name': sorted(self.owner.NATIVE_WAIT_FAILURE_CASES)[0]} + parse = self.owner.closed_failure_details + sentence = self.native_wait_sentence() + stdout = lambda text: {'Category': 'StdOutMsgs', 'Text': text} + for messages in ([stdout(sentence * 2)], [{'Category': 'StdErrMsgs', 'Text': sentence}], + [stdout(sentence + '\n' + self.native_wait_sentence('cleanup', boundary='constructor'))], + [stdout(self.native_wait_sentence('cleanup', boundary='cleanup_stop'))], + [stdout('X' * 65536 + sentence)], [stdout(sentence.replace(';wrapper=', ';unlisted='))]): + self.assertIsNone(parse(case, {'Messages': messages})) + for field, value in (('boundary', 'unlisted'), ('constructor', 'PRIVATE-CANARY'), + ('runtime', 'host.example'), ('wrapper', 'ready'), ('control', 'TRUE'), + ('actual', 'succeeded'), ('pools', ','.join(['pending'] * 9)), + ('pools', 'not_issued,pending')): + self.assertIsNone(parse(case, {'Messages': [stdout(self.native_wait_sentence(**{field: value}))]})) + + def test_native_wait_protocol_exports_only_closed_details_and_truthful_failed_outcome(self): + case = {**self.case(1), 'name': sorted(self.owner.NATIVE_WAIT_FAILURE_CASES)[0]} + stream = io.StringIO() + progress = self.progress(self.root / 'native-wait.diag', 'LearnStack.Tests.Integration', [case], stream) + item = self.execution_result(case); item['Outcome'] = 2 + item['ErrorMessage'] = 'System.OperationCanceledException : PRIVATE-CANARY' + item['ErrorStackTrace'] = '/private/path/BackgroundJobPositiveSdkTests.NativeWait.cs:line 98' + item['Messages'] = [{'Category': 'StdOutMsgs', 'Text': self.native_wait_sentence(boundary='cleanup_stop')}] + with contextlib.redirect_stdout(io.StringIO()): + progress.results({'NewTestResults': [item]}) + result = progress.failure_locations[0] + self.assertEqual([{'source': 'positive_sdk_native_wait', 'line': 98}], result['locations']) + self.assertEqual('cleanup_stop', result['details']['failure']['boundary']) + self.assertEqual('cancellation', result['exceptionKind']) + self.assertEqual('Failed', json.loads(stream.getvalue())['outcome']) + for text in ('PRIVATE-CANARY', '/private/', 'Native wait failure;'): + self.assertNotIn(text, json.dumps(result)) + progress.close() + @staticmethod def settlement_sentence(**changes): values = {'boundary': 'count_assert', 'observedAttempts': '3', 'snapshot': 'available', diff --git a/scripts/test-ci-test-shard-results.py b/scripts/test-ci-test-shard-results.py index 123472e6..eaa56e62 100644 --- a/scripts/test-ci-test-shard-results.py +++ b/scripts/test-ci-test-shard-results.py @@ -1,6 +1,7 @@ #!/usr/bin/env python3 """Planted controls against the real workflow/API/archive/aggregate owner.""" import copy +from contextlib import contextmanager import hashlib import io import json @@ -63,6 +64,173 @@ def jobs(self, scope, context=None): owners = ['base', 'native'] + ['ordinary-' + str(i) for i in range(self.plan['counts']['ordinary'])] return [self.job(owner, n + 1, context) for n, owner in enumerate(owners)] + @contextmanager + def acquisition(self, snapshots, *, scope='backend', deadline=1000, request_seconds=0): + state = {'now': 0, 'reads': 0, 'sleeps': [], 'deadlines': []} + class FixtureApi: + def __init__(self, deadline): + self.deadline = deadline + state['deadlines'].append(deadline) + def jobs(self, context): + state['reads'] += 1 + state['now'] += request_seconds + RESULTS.require(state['now'] < self.deadline, 'aggregate_deadline_exhausted') + value = snapshots[min(state['reads'] - 1, len(snapshots) - 1)] + if isinstance(value, Exception): + raise value + return copy.deepcopy(value) + def sleep(seconds): + state['sleeps'].append(seconds) + state['now'] += seconds + output = io.StringIO() + with mock.patch.object(RESULTS, 'Api', FixtureApi), \ + mock.patch.object(RESULTS.time, 'monotonic', side_effect=lambda: state['now']), \ + mock.patch.object(RESULTS.time, 'sleep', side_effect=sleep), \ + mock.patch('sys.stderr', output): + yield state, output, lambda: RESULTS.acquire_jobs(deadline, self.context(), self.plan, scope) + + def pending_job(self, jobs, index=0, status='in_progress'): + jobs[index].update(status=status, conclusion=None, completed_at=None) + if status == 'queued': + jobs[index]['started_at'] = None + return jobs + + def test_metadata_acquisition_waits_only_for_explicit_pending_producers_or_gates(self): + for scope in ('backend', 'integration'): + clean = self.jobs(scope) + for index in range(len(clean)): + for gate in ('job', 0, 1, 2): + for status in ('queued', 'in_progress'): + with self.subTest(scope=scope, owner=index, gate=gate, status=status): + pending = copy.deepcopy(clean) + if gate == 'job': + self.pending_job(pending, index, status) + else: + pending[index]['steps'][gate].update(status=status, conclusion=None) + with self.acquisition([pending, clean], scope=scope) as (state, output, acquire): + result = acquire() + self.assertEqual(len(clean), len(result)) + self.assertEqual(2, state['reads']) + self.assertEqual([2], state['sleeps']) + self.assertEqual([30], state['deadlines']) + diagnostic = json.loads(output.getvalue()) + self.assertEqual({'protocol', 'diagnostic', 'observation', 'owner', 'gate'}, set(diagnostic)) + self.assertEqual('producer_metadata_pending', diagnostic['diagnostic']) + self.assertEqual(RESULTS.producer_name(diagnostic['owner']), clean[index]['name']) + self.assertEqual(['build', 'execute', 'upload'][gate] if gate != 'job' else 'job', diagnostic['gate']) + self.assertLess(len(output.getvalue()), 256) + with self.acquisition([self.jobs('backend')]) as (state, output, acquire): + self.assertTrue(acquire()) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + self.assertEqual('', output.getvalue()) + + def test_pending_metadata_never_hides_terminal_malformed_or_identity_failures(self): + clean = self.jobs('backend') + for mutation, reason in ( + (lambda rows: rows[-1].update(conclusion='failure'), 'producer_not_successful'), + (lambda rows: rows[-1]['steps'][-1].update(conclusion='failure'), 'producer_gate_not_successful'), + (lambda rows: rows[-1].update(run_attempt=2), 'job_api_identity_mismatch'), + (lambda rows: rows[-1].update(head_sha='c' * 40), 'job_api_identity_mismatch'), + (lambda rows: rows.append(copy.deepcopy(rows[-1])), 'job_api_identity_mismatch'), + (lambda rows: rows.append({**copy.deepcopy(rows[-1]), 'id': 999}), 'job_api_duplicate_producer'), + (lambda rows: rows.pop(), 'current_attempt_producer_missing'), + (lambda rows: rows[-1].update(steps=None), 'producer_gate_not_successful'), + (lambda rows: rows[-1].update(steps=['PRIVATE-CANARY']), 'producer_gate_not_successful'), + (lambda rows: rows[-1]['steps'].pop(), 'producer_gate_not_successful'), + (lambda rows: rows[-1]['steps'].append(copy.deepcopy(rows[-1]['steps'][0])), 'producer_gate_not_successful'), + (lambda rows: rows[-1].update(completed_at='2026-10-19T00:21:02Z'), 'producer_ceiling_exceeded'), + (lambda rows: rows[0]['steps'][-1].update(conclusion='cancelled'), 'producer_gate_not_successful'), + (lambda rows: rows[0]['steps'].pop(), 'producer_gate_not_successful'), + (lambda rows: (rows[-1]['steps'][0].update(status='in_progress', conclusion=None), + rows[-1]['steps'][-1].update(conclusion='failure')), 'producer_gate_not_successful'), + (lambda rows: rows[0].update(completed_at=clean[0]['completed_at']), 'api_timestamp_invalid'), + ): + rows = self.pending_job(copy.deepcopy(clean)) + mutation(rows) + with self.acquisition([rows, clean]) as (state, output, acquire): + self.refuses(reason, acquire) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + self.assertNotIn('PRIVATE-CANARY', output.getvalue()) + for gate in ('job', 0, 1, 2): + for status, conclusion in ( + ('completed', None), ('in_progress', 'success'), ('queued', 'failure'), + ('in_progress', 'PRIVATE-CANARY'), ('in_progress', {}), ('unknown', None), + ): + rows = copy.deepcopy(clean) + value = rows[-1] if gate == 'job' else rows[-1]['steps'][gate] + value.update(status=status, conclusion=conclusion) + with self.acquisition([rows, clean]) as (state, output, acquire): + self.refuses('producer_not_successful' if gate == 'job' else 'producer_gate_not_successful', acquire) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + self.assertNotIn('PRIVATE-CANARY', output.getvalue()) + rows = copy.deepcopy(clean) + value = rows[-1] if gate == 'job' else rows[-1]['steps'][gate] + value.update(status='in_progress'); value.pop('conclusion') + with self.acquisition([rows, clean]) as (state, _, acquire): + self.refuses('producer_not_successful' if gate == 'job' else 'producer_gate_not_successful', acquire) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + + def test_metadata_acquisition_discards_snapshots_and_never_retries_a_terminal_or_api_failure(self): + clean = self.jobs('backend') + first = self.pending_job(copy.deepcopy(clean)) + second = self.pending_job(copy.deepcopy(clean), -1) + with self.acquisition([first, second]) as (state, _, acquire): + self.refuses('producer_metadata_deadline_exhausted', acquire) + self.assertGreater(state['reads'], 2) + self.assertLessEqual(state['reads'], 16) + self.assertLess(state['now'], 30) + failed = copy.deepcopy(clean); failed[-1]['conclusion'] = 'failure' + with self.acquisition([first, failed, clean]) as (state, _, acquire): + self.refuses('producer_not_successful', acquire) + self.assertEqual(2, state['reads']) + self.assertEqual([2], state['sleeps']) + for reason in ('actions_api_unavailable', 'jobs_api_population_changed', 'jobs_api_shape_invalid'): + with self.acquisition([RESULTS.Refusal(reason), clean]) as (state, _, acquire): + self.refuses(reason, acquire) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + + def test_pending_metadata_never_hides_invalid_creation_timestamps(self): + clean = self.jobs('backend') + for status in ('queued', 'in_progress', 'completed'): + for created in (None, 'PRIVATE-CANARY', '2099-01-01T00:00:00Z'): + if status == 'queued' and created == '2099-01-01T00:00:00Z': + continue # No started timestamp exists to compare yet. + rows = self.pending_job(copy.deepcopy(clean)) + if status != 'completed': + self.pending_job(rows, -1, status) + if created is None: + rows[-1].pop('created_at') + else: + rows[-1]['created_at'] = created + with self.subTest(status=status, created=created), \ + self.acquisition([rows, clean]) as (state, output, acquire): + self.refuses('api_timestamp_invalid', acquire) + self.assertEqual(1, state['reads']) + self.assertEqual([], state['sleeps']) + self.assertNotIn('PRIVATE-CANARY', output.getvalue()) + + def test_metadata_acquisition_charges_requests_and_pacing_to_one_bounded_deadline(self): + pending = self.pending_job(self.jobs('backend')) + for deadline, request_seconds in ((1000, 0), (5, 1), (1, 2)): + with self.acquisition([pending], deadline=deadline, request_seconds=request_seconds) as (state, _, acquire): + self.refuses('aggregate_deadline_exhausted' if request_seconds > deadline + else 'producer_metadata_deadline_exhausted', acquire) + self.assertEqual([min(30, deadline)], state['deadlines']) + self.assertLessEqual(state['reads'], 16) + self.assertTrue(all(value == 2 for value in state['sleeps'])) + if request_seconds <= deadline: + self.assertLess(state['now'], min(30, deadline)) + with self.acquisition([pending]) as (state, _, acquire), \ + mock.patch.object(RESULTS.time, 'sleep'): + self.refuses('producer_metadata_deadline_exhausted', acquire) + self.assertEqual(16, state['reads']) + + def metadata(self, owner='base', context=None): context = context or self.context() return {'total_count': 1, 'artifacts': [{'id': 12345, 'name': RESULTS.artifact_name(context, owner), @@ -257,6 +425,66 @@ def test_attempt_api_refuses_stale_missing_skipped_failed_duplicate_or_oversized dirty = copy.deepcopy(clean); other = copy.deepcopy(dirty[0]); other['id'] = 100; dirty.append(other) self.refuses('job_api_duplicate_producer', RESULTS.verify_jobs, dirty, context, self.plan, 'backend') + def test_producer_refusal_retains_only_closed_owner_and_state_diagnostics(self): + context = self.context() + values = [('queued', None), ('in_progress', None), ('completed', None), + ('completed', 'failure'), ('completed', 'skipped'), + ('PRIVATE-STATE-CANARY', {'PRIVATE-CANARY': 'value'})] + for scope in ('backend', 'integration'): + clean = self.jobs(scope, context) + for position in range(len(clean)): + owner = clean[position]['name'].removeprefix('backend ') + owner = {'base tests and gates': 'base', 'native crash proof': 'native'}.get(owner, owner) + for status, conclusion in values: + with self.subTest(scope=scope, owner=owner, status=status, conclusion=conclusion): + jobs = copy.deepcopy(clean) + jobs[position].update(status=status, conclusion=conclusion) + output = io.StringIO() + with mock.patch.object(RESULTS.sys, 'stderr', output): + self.refuses('producer_not_successful', RESULTS.verify_jobs, jobs, context, self.plan, scope) + self.assertEqual({'protocol': 1, 'diagnostic': 'producer_state_refusal', 'owner': owner, + 'status': status if status in ('queued', 'in_progress', 'completed') else 'other', + 'conclusion': conclusion if conclusion in ('failure', 'skipped') else 'other'}, + json.loads(output.getvalue())) + self.assertNotIn('PRIVATE', output.getvalue()) + self.assertLess(len(output.getvalue()), 256) + + def test_gate_refusal_retains_only_closed_owner_gate_and_state_diagnostics(self): + context = self.context() + for index, gate in enumerate(('build', 'execute', 'upload')): + for mutation in ('missing', 'duplicate', 'queued', 'in_progress', 'failed', 'skipped', 'canary'): + with self.subTest(gate=gate, mutation=mutation): + jobs = self.jobs('backend', context) + # The final Architecture producer proves this is the actual failed owner. + owner = 'architecture-' + str(self.plan['counts']['architecture'] - 1) + steps = jobs[-1]['steps'] + if mutation == 'missing': + steps.pop(index) + elif mutation == 'duplicate': + steps.append(copy.deepcopy(steps[index])) + elif mutation in ('queued', 'in_progress'): + steps[index].update(status=mutation, conclusion=None) + elif mutation == 'canary': + steps[index].update(status='PRIVATE-STATUS-CANARY', conclusion={'PRIVATE-CANARY': 'value'}) + else: + steps[index]['conclusion'] = 'failure' if mutation == 'failed' else 'skipped' + output = io.StringIO() + with mock.patch.object(RESULTS.sys, 'stderr', output): + self.refuses('producer_gate_not_successful', RESULTS.verify_jobs, + jobs, context, self.plan, 'backend') + diagnostic = json.loads(output.getvalue()) + self.assertEqual({'protocol': 1, 'diagnostic': 'producer_gate_refusal', 'owner': owner, + 'gate': gate, 'matches': {'missing': 'missing', 'duplicate': 'multiple'}.get(mutation, 'one'), + 'status': mutation if mutation in ('queued', 'in_progress') else + 'completed' if mutation in ('failed', 'skipped') else 'other', + 'conclusion': 'failure' if mutation == 'failed' else 'skipped' if mutation == 'skipped' else 'other'}, + diagnostic) + self.assertNotIn('PRIVATE', output.getvalue()) + output = io.StringIO() + with mock.patch.object(RESULTS.sys, 'stderr', output): + self.assertTrue(RESULTS.verify_jobs(self.jobs('backend', context), context, self.plan, 'backend')) + self.assertEqual('', output.getvalue()) + def test_run_head_and_actual_merge_checkout_are_distinct_and_related(self): context = self.context() run = {'id': 123, 'run_attempt': 1, 'head_sha': context['headSha'], 'path': '.github/workflows/ci.yml', @@ -504,12 +732,20 @@ def test_actual_aggregate_downloads_ids_checks_zip_and_exports_only_complete_cur metadata[RESULTS.artifact_name(context, owner)] = entry source = root / '.github/workflows'; source.mkdir(parents=True) (source / 'ci.yml').write_bytes((ROOT / '.github/workflows/ci.yml').read_bytes()) - jobs = self.jobs('backend'); calls = [] + jobs = self.jobs('backend'); calls, deadlines, job_reads = [], [], [] + pending_job = self.pending_job class FixtureApi(RESULTS.Api): - def __init__(self, deadline): self.deadline = deadline + def __init__(self, deadline): + self.deadline = deadline + deadlines.append(deadline) def fetch(self, suffix, *, binary=False): calls.append(suffix) - if '/jobs?' in suffix: return {'total_count': len(jobs), 'jobs': jobs} + if '/jobs?' in suffix: + job_reads.append(suffix) + rows = copy.deepcopy(jobs) + if len(job_reads) == 1: + pending_job(rows) + return {'total_count': len(rows), 'jobs': rows} if '/artifacts?' in suffix: return metadata[suffix.split('&name=', 1)[1]] if suffix.endswith('/zip'): return archives[int(suffix.split('/')[-2])] return {'id': 123, 'run_attempt': 1, 'head_sha': context['headSha'], @@ -519,8 +755,15 @@ def fetch(self, suffix, *, binary=False): with mock.patch.object(RESULTS, 'ROOT', root), mock.patch.object(RESULTS, 'Api', FixtureApi), \ mock.patch.object(RESULTS.OWNER, 'shard_context', return_value=context), \ mock.patch.dict(os.environ, {'LEARNSTACK_CI_STARTED_AT': str(int(time.time()))}), \ + mock.patch.object(RESULTS.time, 'sleep') as sleep, \ mock.patch('sys.stdout', io.StringIO()): self.assertEqual(0, RESULTS.aggregate('backend')) + sleep.assert_called_once_with(2) + self.assertEqual(2, len(job_reads)) + self.assertEqual(2, len(deadlines)) + self.assertLessEqual(deadlines[1], deadlines[0]) + self.assertLessEqual(deadlines[1] - time.monotonic(), 30) + self.assertLessEqual(deadlines[0] - time.monotonic(), 240) receipt = RESULTS.read_json(root / 'artifacts/ci-aggregate-backend/aggregate.json') self.assertEqual(set(paths), set(receipt['producers'])) self.assertEqual(len(paths), len([call for call in calls if call.endswith('/zip')])) diff --git a/scripts/test-delivery-log-index.py b/scripts/test-delivery-log-index.py new file mode 100644 index 00000000..e1714388 --- /dev/null +++ b/scripts/test-delivery-log-index.py @@ -0,0 +1,127 @@ +#!/usr/bin/env python3 +"""Prove the delivery log index is generated exactly and that a stale one fails.""" +import importlib.util +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[1] +SCRIPT = Path(__file__).with_name('delivery-log-index.py') +SPEC = importlib.util.spec_from_file_location('delivery_log_index', SCRIPT) +index = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(index) + +LOG = '\n'.join([ + '# Phase 07 — delivery log', '', 'Intro.', '', index.BEGIN, index.END, '', + '## P07-1 — Producer', '', + '### P07-1 decision package (2026-10-21)', 'body', '', + '#### Accepted answers', 'body', '', + '##### Maintainer acceptance (2026-10-21)', 'body', '', + '###### Fix review (2026-10-22)', 'body', '', + '### Step 1 review round 1', 'undated legacy entry', '', + '```', '### Not a heading (2026-10-22)', '```', '', + '## P07-2 — Consumer', '', + '### Step 1 review round 1', 'duplicate text', '', + '## Status archive', '', 'Retired prose.', '']) + + +class RowTests(unittest.TestCase): + def test_rows_nest_by_included_ancestors_and_count_whole_sections(self): + self.assertEqual([ + '- [P07-1 — Producer](#p07-1--producer) — 21 lines', + ' - [P07-1 decision package (2026-10-21)](#p07-1-decision-package-2026-10-21) — 12 lines', + ' - [Maintainer acceptance (2026-10-21)](#maintainer-acceptance-2026-10-21) — 6 lines', + ' - [Fix review (2026-10-22)](#fix-review-2026-10-22) — 3 lines', + ' - [Step 1 review round 1](#step-1-review-round-1) — 7 lines', + '- [P07-2 — Consumer](#p07-2--consumer) — 5 lines', + ' - [Step 1 review round 1](#step-1-review-round-1-1) — 3 lines', + '- [Status archive](#status-archive) — 4 lines', + ], index.rows(LOG.split('\n'))) + + def test_link_text_in_a_heading_is_kept_as_plain_text(self): + self.assertEqual(['- [See ADR-0069 (2026-10-23)](#see-adr-0069-2026-10-23) — 1 lines'], + index.rows(['## See [ADR-0069](x.md) (2026-10-23)'])) + + +class BlockTests(unittest.TestCase): + def test_regenerate_is_idempotent_and_touches_only_the_block(self): + once = index.regenerate(LOG) + self.assertEqual(once, index.regenerate(once)) + outside = lambda text: text.split(index.BEGIN)[0] + text.split(index.END)[1] + self.assertEqual(outside(LOG), outside(once)) + self.assertIn('**Index**', once) + + def test_missing_duplicated_or_misplaced_markers_are_refused(self): + for text, reason in ( + (LOG.replace(index.BEGIN + '\n', ''), 'exactly one'), + (LOG.replace(index.END, index.END + '\n' + index.BEGIN + '\n' + index.END), 'exactly one'), + (LOG.replace(index.BEGIN + '\n' + index.END + '\n', '') + .replace('## Status archive', index.BEGIN + '\n' + index.END + '\n## Status archive'), + 'before the first ## section')): + with self.subTest(reason=reason): + with self.assertRaisesRegex(ValueError, reason): + index.regenerate(text) + + +class RepositoryTests(unittest.TestCase): + def run_cli(self, root, *args): + return subprocess.run([sys.executable, str(root / 'scripts/delivery-log-index.py'), *args], + capture_output=True, text=True) + + def fixture(self): + directory = tempfile.TemporaryDirectory(prefix='learnstack-log-index-') + root = Path(directory.name) + (root / 'scripts').mkdir() + for name in ('delivery-log-index.py', 'markdown-fragment-audit.py'): + shutil.copy(ROOT / 'scripts' / name, root / 'scripts' / name) + shutil.copytree(ROOT / 'docs/roadmap', root / 'docs/roadmap') + return directory, root + + def test_every_actual_delivery_log_has_a_current_index(self): + found = index.logs(ROOT) + self.assertGreaterEqual(len(found), 2) + for path in found: + with self.subTest(log=path.name): + text = path.read_text() + self.assertEqual(text, index.regenerate(text)) + + def test_an_entry_appended_to_the_actual_log_fails_until_regenerated(self): + directory, root = self.fixture() + with directory: + self.assertEqual(0, self.run_cli(root).returncode) + log = root / 'docs/roadmap/phase-02b-delivery-log.md' + text = log.read_text() + log.write_text(text.replace('## Status archive', + '### P02b-6 later correction (2026-10-24)\n\nRecord.\n\n## Status archive', 1)) + stale = self.run_cli(root) + self.assertEqual(1, stale.returncode, stale.stdout) + self.assertIn('phase-02b-delivery-log.md: its index is stale', stale.stdout) + self.assertEqual(0, self.run_cli(root, '--write').returncode) + self.assertIn('[P02b-6 later correction (2026-10-24)]', log.read_text()) + self.assertEqual((0, ''), (self.run_cli(root).returncode, self.run_cli(root).stderr)) + + def test_a_hand_edited_row_fails(self): + directory, root = self.fixture() + with directory: + log = root / 'docs/roadmap/phase-02d-delivery-log.md' + text = log.read_text() + log.write_text(text.replace('— 276 lines', '— 275 lines', 1)) + self.assertEqual(1, self.run_cli(root).returncode) + + def test_unknown_arguments_are_refused(self): + self.assertEqual(2, self.run_cli(ROOT, '--check').returncode) + + def test_actual_workflow_and_make_targets_run_the_generator(self): + workflow = (ROOT / '.github/workflows/ci.yml').read_text() + makefile = (ROOT / 'Makefile').read_text() + self.assertIn('python3 scripts/delivery-log-index.py\n', workflow) + self.assertIn('python3 scripts/test-delivery-log-index.py', workflow) + self.assertIn('\tpython3 scripts/delivery-log-index.py\n', makefile) + self.assertIn('\tpython3 scripts/delivery-log-index.py --write\n', makefile) + + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/test-markdown-fragment-audit.py b/scripts/test-markdown-fragment-audit.py new file mode 100644 index 00000000..427e4a93 --- /dev/null +++ b/scripts/test-markdown-fragment-audit.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +"""Prove the fragment audit fails on planted breaks and passes on the real tree.""" +import importlib.util +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[1] +SCRIPT = Path(__file__).with_name('markdown-fragment-audit.py') +SPEC = importlib.util.spec_from_file_location('markdown_fragment_audit', SCRIPT) +audit = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(audit) + + +def tree(files): + directory = tempfile.TemporaryDirectory(prefix='learnstack-fragment-audit-') + root = Path(directory.name) + for name, text in files.items(): + (root / name).parent.mkdir(parents=True, exist_ok=True) + (root / name).write_text(text) + return directory, root + + +class SlugTests(unittest.TestCase): + def test_github_slugs_of_real_heading_shapes(self): + cases = { + 'P02b-6 Step 3 — shared seed/demo lifecycle (2026-10-21)': + 'p02b-6-step-3--shared-seeddemo-lifecycle-2026-10-21', + 'Identity integration — the `learnstack` realm': 'identity-integration--the-learnstack-realm', + 'Accepted G12/G13 answers': 'accepted-g12g13-answers', + 'Delivery Record (Packets 0–3)': 'delivery-record-packets-03', + 'Tenant runtime — host header to tenant_id resolution': + 'tenant-runtime--host-header-to-tenant_id-resolution', + 'Cohort × LiveSession × LiveBooking': 'cohort--livesession--livebooking', + '[Linked](x.md) title': 'linked-title', + } + for text, expected in cases.items(): + with self.subTest(text=text): + self.assertEqual(expected, audit.slug(text)) + + def test_duplicates_are_numbered_in_order_and_fences_are_not_headings(self): + found = audit.anchors('# A\n## Step 1 review round 1\n```\n## Step 1 review round 1\n```\n' + '### Step 1 review round 1\n<a id="kept"></a>\n') + self.assertEqual({'a', 'step-1-review-round-1', 'step-1-review-round-1-1', 'kept'}, found) + + +class AuditTests(unittest.TestCase): + FILES = { + 'docs/a.md': '# Title\n## Moved section\n## Twice\n## Twice\n', + 'docs/b.md': ('[ok](a.md#moved-section) [dup](a.md#twice-1) [self](#local)\n' + '## Local\n[repo](docs/a.md#title) [web](https://x.test/a.md#nope)\n' + '[code](../src/Note.cs#L1) [missing](gone.md#nope) `[sample](a.md#nope)`\n' + '```\n[fenced](a.md#nope)\n```\n'), + 'src/Note.cs': '/// <see href="../docs/a.md#twice">twice</see>\n', + } + + def run_audit(self, extra=None): + directory, root = tree({**self.FILES, **(extra or {})}) + with directory: + return audit.audit(root, sorted(str(p.relative_to(root)) for p in root.rglob('*') if p.is_file())) + + def test_every_resolvable_shape_passes(self): + problems, checked = self.run_audit() + self.assertEqual([], problems) + self.assertEqual(5, checked) + + def test_each_planted_break_is_reported(self): + planted = { + 'docs/c.md': '[gone](a.md#moved-section-2026-10-22)\n', + 'docs/d.md': '[third](a.md#twice-2)\n', + 'docs/e.md': '[self](#nowhere)\n# Here\n', + 'src/Other.cs': '/// <see href="../docs/a.md#renamed">x</see>\n', + 'docs/nested/f.md': '[rel](../a.md#missing)\n', + } + problems, _ = self.run_audit(planted) + reported = sorted(problem.split(':', 1)[0] for problem in problems) + self.assertEqual(sorted(planted), reported) + + def test_actual_repository_has_no_broken_fragment(self): + problems, checked = audit.audit(ROOT, audit.tracked(ROOT)) + self.assertEqual([], problems) + self.assertGreater(checked, 1000) + + def test_renaming_a_real_heading_breaks_its_real_inbound_links(self): + with tempfile.TemporaryDirectory(prefix='learnstack-fragment-real-') as directory: + root = Path(directory) + names = ['docs/roadmap/phase-02b-events-auth.md', 'docs/roadmap/phase-02b-delivery-log.md'] + for name in names: + (root / name).parent.mkdir(parents=True, exist_ok=True) + shutil.copy(ROOT / name, root / name) + self.assertEqual([], audit.audit(root, names)[0]) + log = root / names[1] + log.write_text(log.read_text().replace('### P02b-4 merge and closeout (2026-10-19)\n', + '### P02b-4 merge (2026-10-19)\n', 1)) + problems = audit.audit(root, names)[0] + self.assertTrue(any(p.startswith(names[0]) and 'p02b-4-merge-and-closeout-2026-10-19' in p + for p in problems), problems) + + def test_a_reordered_duplicate_still_resolves_which_only_order_preservation_catches(self): + # The audit proves a fragment exists, not that it names the same section as before: + # renaming the first of two same-named headings hands its anchor to the second. + # ADR-0069's migration verified each heading's anchor individually for this reason. + directory, root = tree({'a.md': '## Twice\n## Twice\n', 'b.md': '[x](a.md#twice)\n'}) + with directory: + (root / 'a.md').write_text('## Once\n## Twice\n') + self.assertEqual([], audit.audit(root, ['a.md', 'b.md'])[0]) + + def test_actual_cli_reports_and_fails_on_a_planted_break(self): + directory, root = tree({'scripts/markdown-fragment-audit.py': SCRIPT.read_text(), + 'a.md': '# A\n', 'b.md': '[x](a.md#b)\n'}) + with directory: + subprocess.run(['git', 'init', '-q'], cwd=root, check=True) + result = subprocess.run([sys.executable, str(root / 'scripts/markdown-fragment-audit.py')], + cwd=root, capture_output=True, text=True) + self.assertEqual(1, result.returncode, result.stdout) + self.assertIn('b.md:1: #b is not an anchor of a.md', result.stdout) + (root / 'b.md').write_text('[x](a.md#a)\n') + result = subprocess.run([sys.executable, str(root / 'scripts/markdown-fragment-audit.py')], + cwd=root, capture_output=True, text=True) + self.assertEqual((0, ''), (result.returncode, result.stderr)) + + def test_actual_workflow_and_make_target_run_the_audit(self): + self.assertIn('python3 scripts/markdown-fragment-audit.py', + (ROOT / '.github/workflows/ci.yml').read_text()) + self.assertIn('python3 scripts/markdown-fragment-audit.py', (ROOT / 'Makefile').read_text()) + + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/test-markdown-link-audit.py b/scripts/test-markdown-link-audit.py new file mode 100644 index 00000000..d5fab0d0 --- /dev/null +++ b/scripts/test-markdown-link-audit.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 +"""Exercise the real workflow link audit across squash merges and missing bases.""" +from contextlib import contextmanager +import os +from pathlib import Path +import subprocess +import tempfile +import textwrap +import unittest + +ROOT = Path(__file__).resolve().parents[1] + + +def audit_script(): + workflow = (ROOT / '.github/workflows/ci.yml').read_text() + block = workflow.split(' - name: Markdown link audit (changed docs)\n', 1)[1].split(' - name:', 1)[0] + return textwrap.dedent(block.split(' run: |\n', 1)[1]) + + +@contextmanager +def squashed_fixture(*, broken_change=False, broken_legacy=False): + with tempfile.TemporaryDirectory(prefix='learnstack-link-audit-') as directory: + root = Path(directory) + env = {key: os.environ[key] for key in ('PATH', 'HOME', 'TMPDIR') if key in os.environ} + env.update(GIT_CONFIG_NOSYSTEM='1', GIT_CONFIG_GLOBAL=os.devnull, GIT_TERMINAL_PROMPT='0', LC_ALL='C') + + def git(where, *args, check=True): + result = subprocess.run(['git', *args], cwd=where, env=env, capture_output=True, text=True, timeout=10) + if check and result.returncode: + raise AssertionError(result.stderr) + return result + + origin = root / 'origin.git' + git(root, 'init', '--bare', '--initial-branch=main', str(origin)) + work = root / 'work' + work.mkdir() + git(work, 'init', '--initial-branch=main') + git(work, 'config', 'user.name', 'Link audit fixture') + git(work, 'config', 'user.email', 'fixture@example.invalid') + git(work, 'config', 'core.hooksPath', os.devnull) + docs = work / 'docs' + docs.mkdir() + (docs / 'target.md').write_text('# Target\n') + (docs / 'changed.md').write_text('# Before\n') + (docs / 'legacy.md').write_text('[legacy](missing-legacy.md)\n' if broken_legacy else '# Legacy\n') + git(work, 'add', '.') + git(work, 'commit', '-qm', 'Fixture base') + base = git(work, 'rev-parse', 'HEAD').stdout.strip() + target = 'missing-changed.md' if broken_change else 'target.md' + (docs / 'changed.md').write_text( + '# After\n[changed](' + target + ')\n[external](https://example.invalid/external)\n' + '[anchor](#section)\n```md\n[example](missing-fenced.md)\n```\n' + 'Sample: `[inline](missing-inline.md)` is code, not a link.\n') + git(work, 'add', '.') + git(work, 'commit', '-qm', 'Fixture topic') + head = git(work, 'rev-parse', 'HEAD').stdout.strip() + tree = git(work, 'rev-parse', 'HEAD^{tree}').stdout.strip() + merge = git(work, 'commit-tree', tree, '-p', base, '-p', head, '-m', 'Fixture PR checkout').stdout.strip() + squash = git(work, 'commit-tree', tree, '-p', base, '-m', 'Fixture squash').stdout.strip() + git(work, 'remote', 'add', 'origin', str(origin)) + git(work, 'push', 'origin', squash + ':refs/heads/main', head + ':refs/heads/development', merge + ':refs/pull/34/merge') + checkout = root / 'checkout' + git(root, 'clone', '--no-local', str(origin), str(checkout)) + git(checkout, 'fetch', '--no-tags', 'origin', 'refs/pull/34/merge') + git(checkout, 'checkout', '--detach', merge) + # Match the failure: a later depth-one fetch truncates the advanced + # squash branch, while the old event base remains locally available. + git(checkout, 'fetch', '--no-tags', '--depth=1', 'origin', 'main') + assert git(checkout, 'rev-parse', '--verify', base + '^{commit}').returncode == 0 + assert git(checkout, 'merge-base', 'origin/main', 'HEAD', check=False).returncode == 1 + + def run(event='pull_request', comparison=base): + values = {**env, 'EVENT_NAME': event, 'PR_BASE_SHA': comparison, + 'PR_BASE_REF': 'main', 'PUSH_BEFORE_SHA': comparison} + return subprocess.run(['bash', '-eo', 'pipefail', '-c', audit_script()], cwd=checkout, + env=values, capture_output=True, text=True, timeout=10) + + yield run, merge, squash, checkout, git + + +class MarkdownLinkAuditTests(unittest.TestCase): + def test_closed_pr_rerun_uses_its_event_snapshot_after_a_squash(self): + with squashed_fixture(broken_legacy=True) as (run, *_): + result = run() + self.assertEqual(0, result.returncode, result.stderr) + self.assertIn('Auditing 1 file(s)', result.stdout) + self.assertNotIn('No changed Markdown', result.stdout) + + def test_closed_pr_rerun_still_refuses_a_broken_changed_link(self): + with squashed_fixture(broken_change=True) as (run, *_): + result = run() + self.assertEqual(1, result.returncode, result.stderr) + self.assertIn('BROKEN: docs/changed.md', result.stdout) + self.assertNotIn('no merge base', result.stderr) + self.assertNotIn('missing-inline.md', result.stdout) + + def test_push_uses_the_before_snapshot_without_ancestry_traversal(self): + with squashed_fixture(broken_change=True) as (run, _, squash, checkout, git): + git(checkout, 'checkout', '--detach', squash) + result = run(event='push') + self.assertEqual(1, result.returncode, result.stderr) + self.assertIn('BROKEN: docs/changed.md', result.stdout) + + def test_missing_or_manual_base_audits_the_complete_tree(self): + with squashed_fixture(broken_legacy=True) as (run, *_): + for event, comparison in (('pull_request', 'f' * 40), ('push', '0' * 40), ('workflow_dispatch', '')): + with self.subTest(event=event): + result = run(event, comparison) + self.assertEqual(1, result.returncode, result.stderr) + self.assertIn('auditing every tracked Markdown file', result.stdout) + self.assertIn('BROKEN: docs/legacy.md', result.stdout) + + def test_an_empty_valid_range_does_not_audit_unchanged_legacy_links(self): + with squashed_fixture(broken_legacy=True) as (run, merge, *_): + result = run(comparison=merge) + self.assertEqual(0, result.returncode, result.stderr) + self.assertIn('No changed Markdown files', result.stdout) + + +if __name__ == '__main__': + unittest.main() diff --git a/scripts/test-openapi-ci.py b/scripts/test-openapi-ci.py index b34d7b39..19133a2f 100644 --- a/scripts/test-openapi-ci.py +++ b/scripts/test-openapi-ci.py @@ -27,6 +27,8 @@ def setUp(self): self.root_patch = patch.object(ci, 'ROOT', self.root) self.root_patch.start() self.git('init', '-q') + # Finish fixture-owned maintenance before TemporaryDirectory removes it. + self.git('config', 'maintenance.autoDetach', 'false') self.git('config', 'user.name', 'Compatibility test') self.git('config', 'user.email', 'test@example.invalid') (self.root / 'fixture.txt').write_text('Synthetic git data, not a project checkout.\n') @@ -122,6 +124,37 @@ def test_deleted_head_snapshot_is_not_a_new_bootstrap(self): self.run_ci(previous, deleted) bootstrap.assert_not_called() + def test_fixture_maintenance_finishes_before_the_commit_returns(self): + with tempfile.TemporaryDirectory(prefix='learnstack-openapi-maintenance-') as temporary: + evidence = Path(temporary) + configuration = evidence / 'gitconfig' + configuration.write_text( + '[maintenance]\n autoDetach = true\n strategy = gc\n' + '[maintenance "commit-graph"]\n enabled = true\n auto = -1\n' + '[maintenance "gc"]\n enabled = false\n' + '[gc]\n autoDetach = true\n' + '[commit]\n gpgSign = false\n') + trace = evidence / 'trace.jsonl' + environment = {key: value for key, value in os.environ.items() if not key.startswith('GIT_')} + environment.update(GIT_CONFIG_GLOBAL=str(configuration), GIT_CONFIG_NOSYSTEM='1', + GIT_TRACE2_EVENT=str(trace)) + with patch.dict(os.environ, environment, clear=True): + self.git('-c', 'core.hooksPath=/dev/null', 'commit', '--allow-empty', '-qm', 'Maintenance control') + events = [json.loads(line) for line in trace.read_text().splitlines()] + starts = [event for event in events if event.get('event') == 'start'] + parent = starts[0]['sid'] + maintenance = next(event for event in starts if 'maintenance' in event['argv']) + graphs = {event['sid'] for event in starts if 'commit-graph' in event['argv']} + self.assertEqual(1, len(graphs), 'Force real maintenance, not an idle no-op') + parent_exit = next(index for index, event in enumerate(events) + if event.get('event') == 'exit' and event['sid'] == parent) + graph_exit = next(index for index, event in enumerate(events) + if event.get('event') == 'exit' and event['sid'] in graphs) + self.assertLess(graph_exit, parent_exit, 'Actual maintenance must finish before commit returns') + self.assertEqual(0, events[graph_exit]['code'], 'The forced graph write must succeed') + self.assertIn('--no-detach', maintenance['argv']) + self.assertTrue((self.root / '.git/objects/info/commit-graphs/commit-graph-chain').is_file()) + def test_missing_verified_ref_is_not_bootstrap(self): head = self.save(CURRENT) with patch.object(ci, 'bootstrap') as bootstrap, self.assertRaises(subprocess.CalledProcessError): diff --git a/scripts/test-roadmap-structure.py b/scripts/test-roadmap-structure.py new file mode 100644 index 00000000..926a0fe1 --- /dev/null +++ b/scripts/test-roadmap-structure.py @@ -0,0 +1,165 @@ +#!/usr/bin/env python3 +"""Prove the roadmap structure guard fails on each planted violation and passes the real tree.""" +import importlib.util +from pathlib import Path +import shutil +import subprocess +import sys +import tempfile +import unittest + +ROOT = Path(__file__).resolve().parents[1] +SCRIPT = Path(__file__).with_name('roadmap-structure.py') +SPEC = importlib.util.spec_from_file_location('roadmap_structure', SCRIPT) +guard = importlib.util.module_from_spec(SPEC) +SPEC.loader.exec_module(guard) + +PLAN = ('# Phase 07: Fixture\n\n> **Status (2026-10-22).** In progress; records live in the\n' + '> [delivery log](phase-07-delivery-log.md).\n\n## Goal\n\n## Scope\n\n### Plan detail\n\n' + '## Deliverables\n\n## Completion Criteria\n\n## Risks\n\n## Phase Exit Decision\n\nGate.\n') +LOG = ('# Phase 07 — delivery log\n\nThe record of [Phase 07](phase-07-fixture.md).\n\n' + '## P07-0 — Entry\n\n### P07-0 entry verification (2026-10-20)\n\n#### Undated detail\n\n' + '## P07-1 — Producer\n\n### P07-1 decision package (2026-10-21)\n\n' + '## Status archive\n\nRetired prose.\n') +INDEX = ('# Roadmap\n\n## Phases\n\n- [Phase 07](phase-07-fixture.md) — **in progress**;\n' + ' its Status block owns packet state.\n\n## Decision Timing\n\n' + '[accepted answer](phase-07-delivery-log.md#p07-1-decision-package-2026-10-21)\n') +CLAUDE = '# Guide\n\n## What state this is in\n\nPointer.\n\n## Where to start\n\nRead.\n' +README = '# LearnStack\n\n## Where it is today\n\nPointer.\n\n## Quickstart\n' + + +class Fixture: + def __init__(self, **overrides): + self.directory = tempfile.TemporaryDirectory(prefix='learnstack-roadmap-guard-') + self.root = Path(self.directory.name) + files = {'docs/roadmap/phase-07-fixture.md': PLAN, 'docs/roadmap/phase-07-delivery-log.md': LOG, + 'docs/roadmap/README.md': INDEX, 'CLAUDE.md': CLAUDE, 'README.md': README} + files.update(overrides) + for name, text in files.items(): + if text is None: + continue + (self.root / name).parent.mkdir(parents=True, exist_ok=True) + (self.root / name).write_text(text) + + def __enter__(self): + return guard.check(self.root) + + def __exit__(self, *_): + self.directory.cleanup() + + +def status_lines(count): + return ''.join(f'> line {n}\n' for n in range(count)) + + +class GuardTests(unittest.TestCase): + def assertFlags(self, fragment, **overrides): + with Fixture(**overrides) as problems: + self.assertTrue(any(fragment in problem for problem in problems), problems) + + def test_conforming_fixture_and_actual_repository_pass(self): + with Fixture() as problems: + self.assertEqual([], problems) + self.assertEqual([], guard.check(ROOT)) + + def test_phase_document_record_headings_fail(self): + for heading in ('### P07-1 Step 2 — writers', '### Writers (2026-10-22)', + '#### Step 2 review round 1', '### Merge and closeout', + '### Decision package', '### Delivery record'): + with self.subTest(heading=heading): + self.assertFlags('record heading in a phase document', + **{'docs/roadmap/phase-07-fixture.md': PLAN.replace( + '### Plan detail', heading)}) + + def test_phase_document_shape_fails(self): + self.assertFlags('nothing may follow ## Phase Exit Decision', + **{'docs/roadmap/phase-07-fixture.md': PLAN + '\n## Delivery Record (P07-1)\n'}) + self.assertFlags('missing or out of order: ## Risks', + **{'docs/roadmap/phase-07-fixture.md': PLAN.replace('## Risks\n', '')}) + + def test_status_and_file_budgets_fail_one_past_the_limit(self): + def plan(extra): + return PLAN.replace('## Goal', status_lines(extra) + '\n## Goal') + with Fixture(**{'docs/roadmap/phase-07-fixture.md': plan(38)}) as problems: + self.assertEqual([], problems) + self.assertFlags('Status block has 41 non-blank lines', + **{'docs/roadmap/phase-07-fixture.md': plan(39)}) + long_plan = PLAN.replace('### Plan detail', '### Plan detail\n' + 'text\n' * 1990) + self.assertFlags('the budget is 2000', **{'docs/roadmap/phase-07-fixture.md': long_plan}) + + def test_phase_document_must_link_its_log_and_log_its_phase_document(self): + self.assertFlags('does not link phase-07-delivery-log.md', + **{'docs/roadmap/phase-07-fixture.md': PLAN.replace('phase-07-delivery-log.md', 'x.md')}) + self.assertFlags('needs exactly one phase document', + **{'docs/roadmap/phase-07-fixture.md': None}) + self.assertFlags('introduction does not link', + **{'docs/roadmap/phase-07-delivery-log.md': LOG.replace('(phase-07-fixture.md)', '(x.md)')}) + + def test_delivery_log_sections_and_entries_fail(self): + log = 'docs/roadmap/phase-07-delivery-log.md' + self.assertFlags('neither a packet section', **{log: LOG.replace('## P07-1 — Producer', '## Notes')}) + self.assertFlags('not in packet order', **{log: LOG.replace('## P07-0 — Entry', '## P07-2 — Entry')}) + self.assertFlags('entry heading carries no date', + **{log: LOG.replace('### P07-1 decision package (2026-10-21)', '### P07-1 decision package')}) + self.assertFlags('Status archive is the last section', **{log: LOG + '\n## Cross-packet records\n'}) + self.assertFlags('Phase entry precedes every packet section', + **{log: LOG.replace('## Status archive', '## Phase entry\n\n## Status archive')}) + + def test_carriers_fail_on_log_links_budgets_and_missing_sections(self): + link = '[record](docs/roadmap/phase-07-delivery-log.md#x)\n' + self.assertFlags('CLAUDE.md:10: links a delivery log', **{'CLAUDE.md': CLAUDE + link}) + self.assertFlags('README.md:8: links a delivery log', **{'README.md': README + link}) + self.assertFlags('What state this is in has 41 non-blank lines', + **{'CLAUDE.md': CLAUDE.replace('Pointer.\n', 'line\n' * 40)}) + self.assertFlags('## Where it is today is missing', **{'README.md': '# LearnStack\n'}) + + def test_index_bounds_phase_entries_but_not_decision_citations(self): + long_entry = '- [Phase 07](phase-07-fixture.md)\n' + ' more\n\n' * 6 + self.assertFlags('§ Phases entry has 7 non-blank lines', + **{'docs/roadmap/README.md': INDEX.replace( + '- [Phase 07](phase-07-fixture.md) — **in progress**;\n' + ' its Status block owns packet state.\n', long_entry)}) + self.assertFlags('§ Phases links a delivery log', + **{'docs/roadmap/README.md': INDEX.replace('(phase-07-fixture.md)', '(phase-07-delivery-log.md#x)')}) + + def test_declared_shapes_pass_and_frozen_phase_02a_is_exempt(self): + pointer = '# Phase 12\n\n## Goal\n\n## Standing\n\n## Scope on the LearnStack side\n\n## Trigger\n\n## Phase Exit Decision\n' + frozen = PLAN + '\n## Delivery Record (Packet 9)\n\n### The fifth review (2026-09-11)\n' + with Fixture(**{'docs/roadmap/phase-12-hub-marketplace.md': pointer, + 'docs/roadmap/phase-02a-kernel-tenancy.md': frozen}) as problems: + self.assertEqual([], problems) + + def test_a_record_appended_to_the_actual_phase_02b_document_fails(self): + with tempfile.TemporaryDirectory(prefix='learnstack-roadmap-real-') as directory: + root = Path(directory) + shutil.copytree(ROOT / 'docs/roadmap', root / 'docs/roadmap') + for name in ('CLAUDE.md', 'README.md'): + shutil.copy(ROOT / name, root / name) + self.assertEqual([], guard.check(root)) + phase = root / 'docs/roadmap/phase-02b-events-auth.md' + text = phase.read_text() + phase.write_text(text.replace('## Deliverables\n', + '### P02b-7 decision package (2026-10-23)\n\nRecord.\n\n## Deliverables\n', 1)) + self.assertTrue(any('record heading in a phase document' in p for p in guard.check(root))) + + def test_actual_cli_exit_codes(self): + result = subprocess.run([sys.executable, str(SCRIPT)], capture_output=True, text=True) + self.assertEqual((0, ''), (result.returncode, result.stderr), result.stdout) + fixture = Fixture(**{'CLAUDE.md': CLAUDE + '[x](docs/roadmap/phase-07-delivery-log.md)\n'}) + try: + (fixture.root / 'scripts').mkdir() + shutil.copy(SCRIPT, fixture.root / 'scripts/roadmap-structure.py') + result = subprocess.run([sys.executable, str(fixture.root / 'scripts/roadmap-structure.py')], + capture_output=True, text=True) + self.assertEqual(1, result.returncode, result.stdout) + self.assertIn('CLAUDE.md:10: links a delivery log', result.stdout) + finally: + fixture.directory.cleanup() + + def test_actual_workflow_and_make_target_run_the_guard(self): + self.assertIn('python3 scripts/roadmap-structure.py', (ROOT / '.github/workflows/ci.yml').read_text()) + self.assertIn('python3 scripts/roadmap-structure.py', (ROOT / 'Makefile').read_text()) + + +if __name__ == '__main__': + unittest.main() diff --git a/third-party/hangfire/qualification/README.md b/third-party/hangfire/qualification/README.md index ed0325ce..e5f67d7e 100644 --- a/third-party/hangfire/qualification/README.md +++ b/third-party/hangfire/qualification/README.md @@ -32,5 +32,5 @@ its process/container also provide a finite experiment teardown boundary. These experiments do not claim forced cancellation of managed production work. Measurements and findings belong to the -[Step 2 reassessment](../../../docs/roadmap/phase-02b-events-auth.md#step-2-maintenance-reassessment). +[Step 2 reassessment](../../../docs/roadmap/phase-02b-delivery-log.md#step-2-maintenance-reassessment). Mandatory production-path controls remain in the ADR and canonical test catalogue.