Authority consolidation — S0 target design (SPRINT_20260722_016 AUTH-1)

Status: S0 DRAFT for review (2026-08-03). This S0 is unusual: substantial pieces of the program already LANDED out of stage order because they unblocked other programs — the draft consolidates them into the recipe frame rather than pretending the stages ran in sequence. Verification base: the sprint’s dig notes (2026-07-22/23/30), the live baselines, the 2026-08-03 boundary register, and ledger rounds 45–63. ⚠ marks remaining verification.

1. Current → target shape

CurrentTarget
Deployablesauthority (own DB stellaops_authority — done), issuer-directory (schema issuer in the shared platform DB; the “352 kB” is index and catalogue overhead — measured read-only 2026-08-11, all four domain tables hold 0 rows, so AUTH-9’s copy is a no-op and its parity gate is 0 = 0. Re-measure per estate.)authority absorbing issuer-directory (role vs scoped container = the S0 bootstrap-surface decision, §5.1)
DALAuthority.Persistence (25 authority.* table declarations in the source lineage; 22 extant on a fresh chain because 001 drops three deprecated local-audit tables; LIVE-APPLIED chain — no re-baseline, round-21 deviation stands: issuer tables arrive as forward migrations appended to the existing chain) + IssuerDirectory.Persistence (5 domain tablesissuers, issuer_keys, trust_overrides, operator_provider_change_receipts, audit — plus the per-schema schema_migrations ledger, which does NOT carry)issuer tables → new forward migrations in Authority.Persistence. LANDED 2026-08-04 (AUTH-3): one migration, 024_authority_issuer_directory_tables.sql

2. Already landed out of stage order (consolidated into the frame)

PieceStage it belongs toEvidence
IIssuerDirectoryClient widened to the full issuer surface (8 ops + update), closed graphAUTH-5 (client half)2026-08-02; VexLens repointed same day — 003’s defect-3 closed; the client is the seam consumers keep through the fold
Tenants producer: Authority’s FIRST domain outbox (AddEventingReliabilityeventing schema in stellaops_authority), migration 023 row_version, same-transaction tenants catalog emission, startup backfill, /catalog-changes/tenants under catalog:replicateAUTH-4 (X6 re-author, event half)round 58; producer tests 3/3, e2e 5/5
SCR-4 lifecycle events (tenant.suspended transition-only, tenant.deleted + tombstone same-transaction) on tenant_lifecycleAUTH-4 adjacentround 62
Dual-mode consumer seam (AddStellaOpsTenantResolverDualMode) in Auth.ServerIntegrationthe X14 exit’s library half (027 SCR-1)round 59
Host-side mapping of the folded endpoint groups (IssuerDirectoryFold composition root in StellaOps.IssuerDirectory.Api; AddFoldedIssuerDirectory / AddFoldedIssuerDirectoryPolicies / MapFoldedIssuerDirectory in the Authority host, behind default-off IssuerDirectory:Fold:Enabled)AUTH-5 (S5) — the D-AUTH7-5 ruling2026-08-11, 7758aa221b; AuthorityIssuerFoldHostingTests 6/6, two guards red-proven

The fold is composed, not ported (2026-08-11). Four things the legacy host’s Program.cs does are deliberately absent from the composition root, and each one would have been a defect on the auth root rather than a carry — sprint findings D-AUTH5B-14…17:

  1. the folded persistence gets its own PostgresOptions instance, because both it and AddAuthorityPostgresStorage configure the container’s UNNAMED one and the later registration wins — so the naive wiring would have silently moved AuthorityDataSource and the tenants outbox onto the issuer schema;
  2. no AddStartupMigrations— Authority keeps ONE ledger (AUTH-3) and 024 owns those tables;
  3. no CSAF publisher seed — it defaults to true in the legacy host and would write rows into the destination AUTH-9’s parity gate measures;
  4. tenants resolve from authority.tenants, not shared.tenants. Authority’s own database carries a legacy, unmaintained shared.tenants (3 rows against authority.tenants’s 5, measured 2026-08-11), so the carried resolver would have been silently wrong rather than loudly broken.

Consequence: AUTH-4’s X6 re-author was half done (events existed; the legacy cross-DB path did not), and AUTH-9’s forcing function (“tenant create propagates via the new contract to a consumer replica”) is now executable on a scratch stack whenever a consumer flips.

Closed 2026-08-05 (AUTH-4, 0b472b375a). The other half of X6 is the legacy cross-database READ, and it is deleted: GET /console/tenants no longer reads shared.tenants out of the Platform database to build a global admin’s switcher. It had the replica taking PRECEDENCE over authority.tenants, so a stale display name or status in the replica outranked the owner’s own row; and a row present only there is by construction not an Authority tenant, so listing it was a phantom. The catalogue is now owner-truth first (authority.tenants, then the configured catalogue, then home/selected). What remains of the X6 legacy path is the WRITE (SharedTenantsPropagator) plus the narrow ReadSlugsAsync its reconciliation check needs; both stay until the SCR-3 consumer flips complete and are deleted whole at AUTH-10.

3. Table inventory + dispositions

4. Boundary state (2026-08-03)

4a. What issuer-directory IS (owner-requested explainer, review item A8)

What it does. The trust-administration surface for advisory/VEX ISSUERS: registers issuers and their signing keys (issuers, issuer_keys), holds per-tenant TRUST OVERRIDES (how much weight a tenant grants an issuer), and custodies the operator decision-signing key with dual-control approval and a database-enforced append-only guard (§3). Every mutation lands in its audit tables with provider-change receipts.

Who consumes it. The VEX consensus plane (issuer trust weights feed the DC-38 evaluator’s tier/trust inputs), the Console trust-admin pages (trust.client.ts), Excititor/VexLens via IssuerDirectory.Client (the closed SDK). Operator use cases: curate which advisory sources are trusted and how much; rotate signing keys under two-person control; tenant-scoped trust tuning.

Why fold it into Authority as a ROLE (the lean recommendation). It is identity/trust administration — Authority’s domain family; its whole dataset is ~352 kB; a dedicated container buys no blast-radius win while adding a deployable, a boot-order edge, and a route surface. As an Authority role it inherits the hardened host and bootstrap path. The alternative (scoped container) is justified only if trust-admin someday needs independent rollout/availability — nothing in the evidence demands it. OWNER RULING (2026-08-03, A8 closed): fold as an Authority ROLE — approved as recommended.

5. S0 decisions to settle

  1. Bootstrap-surface / container shape (§1): issuer-directory as an authority ROLE (lean recommendation — the 352 kB domain does not justify a second deployable; Authority is the bootstrap root and the fold removes one boot-order edge) vs scoped container. Write the bootstrap-order argument either way.
  2. AUTH-11 break-glass design (constraints recorded in the sprint) — design together with the bootstrap surface.
  3. The pipeline signing gap for the standard IdP plugin (recorded 2026-08-02: publish signs nothing; scratch ran enforcement off) — enforcement stays ON everywhere durable; the fix belongs to the plugin packaging pipeline, tracked here because the fold touches the same surface.
  4. P13-header audit scope for the live chain (§3) — source disposition closed by 026 + S050; exact-current image application remains inside AUTH-9.

Remaining verification CLOSED (updated 2026-08-24) — the P13 audit now distinguishes the 25-declaration lineage from the 22 tables extant on a fresh chain and is forward-only in 026 + S050; applying it to the standing database remains part of the exact-current AUTH-9 image/window. Everything else is verified: