diff --git a/docs/implplan/SPRINT_20260422_005_Authority_default_tenant_bootstrap.md b/docs/implplan/SPRINT_20260422_005_Authority_default_tenant_bootstrap.md new file mode 100644 index 000000000..520eeec0a --- /dev/null +++ b/docs/implplan/SPRINT_20260422_005_Authority_default_tenant_bootstrap.md @@ -0,0 +1,75 @@ +# Sprint 20260422-005 — Authority default-tenant bootstrap + +## Topic & Scope +- Close the bootstrap gap that forces setup-wizard Admin creation to fail with `users_tenant_id_fkey (tenant_id)=(default)` on any fresh Authority DB. +- The previous Authority §2.7 compliance sprint (`SPRINT_20260422_003_Authority_auto_migration_compliance`, archived) trimmed `devops/compose/postgres-init/04-authority-schema.sql` to "seeds only". In doing so, the guarded `default` tenant seed now runs only when the schema exists at init-script time — which, for migration-owned schemas, it doesn't. Result: freshly-migrated Authority DBs have zero tenants, the setup wizard fails, admin login returns `invalid_grant`. +- Two parallel QA agents (`fe-qa-006-relsec` and `fe-qa-007-evidops` in SPRINT_20260421_006/007 closeouts on 2026-04-22) independently hit this bug and worked around it by manually inserting the `default` + `installation` tenant rows and calling `POST /api/v1/setup/sessions/{id}/steps/admin/execute`. +- Working directory: `src/Authority/` (primary); `devops/compose/postgres-init/04-authority-schema.sql` + `04b-authority-dedicated-schema.sql` only if the seed fallback needs tightening. +- Expected evidence: fresh-volume bring-up (`docker compose down -v && docker compose up -d`) produces a working Authority with `default` tenant present and setup-wizard Admin bootstrap succeeding without manual intervention. + +## Dependencies & Concurrency +- Follow-up to `SPRINT_20260422_003_Authority_auto_migration_compliance` (archived). Migration wiring and schema ownership contract established there are the baseline. +- No cross-module dependencies; safe to run alongside any non-Authority sprint. + +## Documentation Prerequisites +- `CLAUDE.md` §2.7 — auto-migration + init script contract. +- `docs-archived/implplan/SPRINT_20260422_003_Authority_auto_migration_compliance.md` — the Decisions & Risks from the prior sprint explain why the init script was trimmed. +- `src/Authority/__Libraries/StellaOps.Authority.Persistence/Migrations/001_initial_schema.sql` — where a seed migration could live. +- `src/Authority/__Libraries/StellaOps.Authority.Persistence/Migrations/S001_demo_seed.sql` (if present) — pattern reference for seed-category migrations. + +## Delivery Tracker + +### AUTH-SEED-001 — Seed `default` tenant through the migration path +Status: TODO +Dependency: none +Owners: Developer (backend) +Task description: +- Add the `default` (and `installation`, if the setup wizard expects both) tenant rows as an embedded seed migration under `src/Authority/__Libraries/StellaOps.Authority.Persistence/Migrations/`. Seed-category filename so it runs after the DDL migrations and is idempotent (`INSERT ... ON CONFLICT (id) DO NOTHING` or equivalent). +- The migration runner established in AUTH-MIGRATE-002 applies all embedded SQL resources on startup; placing the seed here means both fresh-volume and already-provisioned environments converge to the same state. +- Do NOT add the seed to `04-authority-schema.sql` — that script stays pure-fallback per the prior sprint's Decision. + +Completion criteria: +- [ ] Seed migration is an embedded resource in the persistence assembly. +- [ ] `default` tenant row exists after Authority startup on any fresh DB. +- [ ] Migration is idempotent — re-running against an already-seeded DB is a no-op. +- [ ] Migration applies cleanly after `001_initial_schema.sql` + `002_drop_deprecated_audit_tables.sql`. + +### AUTH-SEED-002 — Verify setup-wizard admin bootstrap succeeds without manual intervention +Status: TODO +Dependency: AUTH-SEED-001 +Owners: Developer (backend), QA +Task description: +- On a fresh volume (`docker compose down -v && docker compose up -d`), drive the setup-wizard admin-creation flow end-to-end using the documented credentials (`admin / Admin@Stella2026!`). Capture the happy path: first-run wizard → admin execute step → `POST /connect/token` succeeds. +- Regression test: `docker compose stop authority && docker compose rm -f authority && docker compose up -d authority` (recreate against existing volume) — must remain healthy with no tenant FK violations. + +Completion criteria: +- [ ] Fresh-volume `docker compose up -d` produces a working admin login with zero manual SQL inserts. +- [ ] Authority startup logs show the seed migration applied once; restart shows "up to date". +- [ ] Integration or targeted test captures this path (or at minimum a run evidence document in `docs/qa/`). + +### AUTH-SEED-003 — Document the bootstrap contract +Status: TODO +Dependency: AUTH-SEED-002 +Owners: Documentation author +Task description: +- Update Authority's module dossier or operations guide to document that the `default` tenant is a migration-owned seed, not a user-modifiable row; note the relationship between `authority.tenants` and the setup-wizard admin flow. +- If the `installation` tenant was previously a migration-owned seed, explain its meaning too. + +Completion criteria: +- [ ] Dossier or operations guide describes the seeded tenants and their purpose. +- [ ] Cross-link from `docs-archived/implplan/SPRINT_20260422_003` Decisions & Risks so the follow-up lineage is obvious. + +## Execution Log +| Date (UTC) | Update | Owner | +| --- | --- | --- | +| 2026-04-22 | Sprint created to unpark the bootstrap gap surfaced independently by two FE QA agents during SPRINT_20260421_006/007 closeouts. The `default` tenant seed disappeared when §2.7 compliance trimmed the init scripts; it needs to come back as a migration-owned seed. | Claude | + +## Decisions & Risks +- **Decision**: the seed belongs in the migration path, not the init scripts. This matches the §2.7 contract established in SPRINT_20260422_003 (migrations own schema + canonical seeds; init scripts are pure fallbacks). +- **Risk**: if an operator had already customized the `default` tenant row, an idempotent INSERT-on-conflict is safe; but if they've renamed or deleted it, the wizard will still fail on a different constraint. Mitigation: the seed is additive and conservative; it does not reconcile existing operator modifications. +- **Risk**: the setup wizard may expect additional bootstrap rows (e.g., default roles, default OIDC client) that are similarly missing after the init-script trim. If AUTH-SEED-002 surfaces more FK violations, extend the seed migration rather than reverting to init-script DDL. + +## Next Checkpoints +- AUTH-SEED-001 DONE: fresh-DB `\dt authority.tenants` + `SELECT * FROM authority.tenants` shows the seeded rows. +- AUTH-SEED-002 DONE: fresh-volume stack brings up and `admin / Admin@Stella2026!` logs in without manual SQL. +- AUTH-SEED-003 DONE: dossier updated, sprint archivable.