Closes the bootstrap gap two parallel QA agents surfaced on 2026-04-22:
fresh Authority DBs lacked the `default` tenant row so setup-wizard admin
creation failed with users_tenant_id_fkey and /connect/token returned
invalid_grant. Fix is on the migration path per AGENTS.md §2.7; the init
script stays seeds-only as established in SPRINT_20260422_003.
- New embedded migration 003_seed_default_tenants.sql performs
`INSERT ... ON CONFLICT (tenant_id) DO NOTHING` for `default` and
`installation`. Numeric prefix (not S-prefix) so the migration runner's
Startup category auto-applies it; S-prefix files route to Seed category
which is intentionally manual-only per
StartupMigrationHost.cs:158.
- `default` is strictly required (Authority's
StandardPluginBootstrapper.DefaultTenantId; /internal/users bootstrap
inserts under this FK). `installation` is not Authority-FK-referenced
today but matches the empirical workaround both QA agents converged on
and serves as defense for cross-service inserts that join
authority.tenants.tenant_id.
Fresh-volume verification (docs/qa/authority-default-tenant-20260422/):
1. docker compose down -v (20 volumes removed incl. compose_postgres-data)
2. docker compose up -d — 62 containers, Authority healthy in ~15s.
3. Startup log: applying 001 (144ms) → 002 (13ms) → 003 (7ms).
authority.tenants contains default + installation.
4. POST /api/v1/setup/sessions → 201; database/valkey/migrations prereqs
ran; admin/execute with admin/Admin@Stella2026! → 200 "Bootstrap
administrator 'admin' ensured successfully."
5. POST /connect/token (password, stellaops-cli, ui.admin openid) → 200
+ JWT carrying role=admin, stellaops:tenant=default.
6. docker compose restart authority → "Database is up to date for
Authority." Clean no-op.
Docs: docs/modules/authority/architecture.md §1.1 "Seeded bootstrap
tenants (migration-owned)". Cross-link added to the archived prior
sprint's Decisions & Risks so the lineage is traceable.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes SPRINT_20260421_007 — all 4 tasks DONE. Full Tier 2c behavioral
verification per docs/qa/feature-checks/FLOW.md. 34 assertions, 0 fail,
0 deferred.
FE-QA-EVID-001 — Evidence: 7/7 PASS
/evidence/{overview, audit-log, verify-replay, exports, capsules, proofs,
bundles}. Alias chains to /ops/operations/audit confirmed intentional per
evidence.routes.ts.
FE-QA-OPS-002 — Ops: 8/8 PASS
/ops/operations/{jobengine, feeds-airgap, doctor, audit, notifications,
health-slo, watchlist} + /ops/scripts. Doctor full diagnostics grid
rendered with real data.
FE-QA-SETUP-003 — Setup + Admin: 12 + 7 PASS
Setup: /setup{, /integrations, /trust-signing (+ issuers/keys/certificates
/audit sub-tabs aliased correctly), /identity-providers, /tenant-branding,
/workflows, /ai-preferences, /topology}.
Admin: all /console-admin/{tenants, users, roles, clients, audit, branding,
assistant} preserved console origin under "Console Administration" heading.
FE-QA-EVIDOPS-004 — Retention coverage:
New e2e/routes/sprint-007-evidence-ops-setup-admin.e2e.spec.ts with 27
Playwright assertions covering origin, canonical-or-alias URL, and
identity-matching body text. Uses the existing auth.fixture.ts pattern.
Evidence: docs/qa/feature-checks/runs/web/sprint-007-evidence-ops-setup-admin/
run-001/ (EVIDENCE.md + tier2-ui-check.json + 36 screenshots + verify.mjs).
Authority default-tenant gap (same as FE-QA-REL-001 discovery):
stellaops_authority had zero tenants and zero users; setup wizard admin
bootstrap failed with users_tenant_id_fkey FK violation. Worked around
in-session by inserting `installation` + `default` tenants and calling
POST /api/v1/setup/sessions/{id}/steps/admin/execute. This is the same
bug two parallel agents independently hit — needs a real Authority sprint
to seed `default` through migrations or StandardPluginRegistrar init.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes SPRINT_20260421_006 — all 4 tasks DONE. Full Tier 2c behavioral
verification per docs/qa/feature-checks/FLOW.md. Evidence directories
include per-route screenshots + tier2-ui-check JSON with PASS/FAIL/DEFERRED
assertions.
FE-QA-REL-001 — Release Control: 9/9 PASS
/environments/overview, /releases, /releases/deployments, /releases/bundles,
/releases/promotions, /releases/approvals, /releases/hotfixes,
/releases/investigation/timeline, /releases/workflows
FE-QA-REL-002 — Release Policy: 7/9 PASS, 2 DEFERRED
/ops/policy/{packs, governance, vex, simulation, governance/budget,
governance/profiles, vex/exceptions} — all PASS.
DEFERRED: /ops/policy/governance/audit (redirects to sprint-007-owned
/ops/operations/audit — scope lock), /ops/policy/governance/trust-weights
(tab URL doesn't persist — flagged as follow-up).
FE-QA-SEC-003 — Security: 10/10 effective PASS
Direct PASS: /security{,/images,/risk,/advisory-sources,/findings,
/vulnerabilities,/reachability}
Redirect PASS matching SEC-005/006/007 consolidation contracts:
/security/vex → /ops/policy/vex, /security/artifacts → /triage/artifacts,
/security/exceptions → /ops/policy/vex/exceptions.
FE-QA-RELSEC-004 — Retention coverage:
New e2e/routes/release-security-identity.e2e.spec.ts with 24 route-identity
assertions + 1 Release interaction guard. Uses auth.fixture.ts test-session
so CI does not require live Authority credentials.
Environmental gap surfaced (worked around in-session, NOT a code fix here):
stellaops_authority was missing the `default` tenant row, breaking setup-
wizard Admin bootstrap with FK users_tenant_id_fkey=(default) and causing
admin login to return invalid_grant. Manually seeded `default` into
authority.tenants and finalized the setup session via Platform Setup API.
Should be addressed in a follow-up Authority sprint — the default tenant
seed needs to land in startup migrations or StandardPluginRegistrar init.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes the last open task in SPRINT_20260422_003. Persisted operator
enablement is now separated from runtime readiness so credential-gated
sources can show an explicit blocked state instead of collapsing into a
generic failed/disabled shape.
Readiness model:
- new SourceReadiness constants class: Disabled | Unsupported | Blocked | Ready
- ConfiguredAdvisorySourceStatus gains Readiness + BlockedReason alongside
existing SyncState (kept as backward-compatible alias)
- enabled = persisted operator intent (untouched)
- readiness = blocked when persisted-enabled and credentials/URIs missing
- blockedReason = free-form list of missing fields
- blockingReason.errorCode = SOURCE_CONFIG_REQUIRED for structured drill-down
Endpoint propagation:
- /status: persisted enabled=true kept; readiness=blocked; readyForSync=false
- /{id}/enable: 200 with readiness=blocked; sourceRegistry left disabled
until credentials land (pre-existing behaviour retained)
- /{id}/sync: 422 readiness=blocked + SOURCE_CONFIG_REQUIRED;
**connector never invoked**, no job run created
- /sync (batch): per-result outcome=blocked with readiness/errorCode/
blockedReason; excluded from totalTriggered; other sources proceed
- Transition: PUT /{id}/configuration with missing credential →
runtimeOptionsInvalidator.Invalidate → next /status flips to ready.
No disable/re-enable cycle needed.
Tests: 8 targeted xUnit methods via scripts/test-targeted-xunit.ps1,
8/8 pass. Includes: blocked status exposure, blocked-to-ready transition
on persisted credential, connector-not-invoked-when-blocked, plus 4
pre-existing SRC-CREDS-002 regression tests.
Docs:
- docs/modules/concelier/connectors.md — new "Blocked / sleeping
readiness state" section with field contract, per-endpoint behaviour
table, UI/CLI rendering guidance, resolution flow
- docs/modules/cli/guides/commands/db.md — short note under
`db connectors configure` cross-linking the connectors.md contract
Sprint SPRINT_20260422_003 archived — all 5 tasks DONE.
New fields are additive; existing UI types in
source-management.api.ts ignore unknown fields so no UI breakage. A
future FE pass can wire explicit readiness/blockedReason rendering.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SPRINT_20260422_001 (Notify compat surface restoration) — closes
NOTIFY-COMPAT-003 final criterion. notify-web rebuilt, 7/7 gateway probes
green post-rebuild (8th returns contracted 501 notify_overrides_not_supported).
Browser replay via direct Node+Playwright driver (MCP bridge rejected the
self-signed cert) confirmed Dashboard/Channels/Quiet Hours/Overrides/
Escalation/Throttle tabs render without runtime-unavailable banners. All 3
tasks DONE.
SPRINT_20260421_003 (Concelier advisory connector runtime alignment) —
all 7 tasks were already DONE before this session; archival is purely
administrative.
Evidence bundle at docs/qa/notify-compat-20260422/ includes EVIDENCE.md,
verify.mjs + verify_with_token.mjs, verify-results.json, and screenshots
for each verified tab.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Brings Authority into §2.7 compliance. Previously AutoMigrate=true was set
in Program.cs but no runner was wired; 001_initial_schema.sql was
non-idempotent so wiring AddStartupMigrations against a pre-bootstrapped
DB crash-looped. Discovered during DEPRECATE-003 when the new drop
migration couldn't apply via Authority's own startup path.
Idempotency fixes in 001_initial_schema.sql:
- CREATE INDEX → CREATE INDEX IF NOT EXISTS (27 indexes)
- CREATE TRIGGER → DROP TRIGGER IF EXISTS + CREATE TRIGGER (3 triggers)
- CREATE POLICY → DROP POLICY IF EXISTS + CREATE POLICY (12 policies)
- CREATE TABLE / FUNCTION (OR REPLACE) / RLS ENABLE / role DO blocks were
already idempotent — left unchanged
Wiring:
- AddStartupMigrations("authority", "Authority", typeof(AuthorityDataSource)
.Assembly) called inside RegisterAuthorityServices (canonical
Signals/Scanner pattern).
- Stale options.AutoMigrate = true + options.MigrationsPath removed from
Program.cs.
- Migrations\_archived\** excluded from the EmbeddedResource glob.
Init script cleanup (migrations own schema authority now):
- 04-authority-schema.sql: 569 lines → 60 lines (schema shells + guarded
default-tenant seed fallback only; all DDL removed)
- 04b-authority-dedicated-schema.sql: same reduction for dedicated DB
Verification sequence — all PASS:
1. Green-field replay: 001 runs twice with zero semantic drift (pg_dump
diff shows only session restrict nonce).
2. Wire against pre-migrated volume: runner applies 001+002 in 209ms, no
crash-loop.
3. Wire + fresh schema: migrates 20 tables from empty in 395ms.
4. Idempotent restart: "Database is up to date", pure no-op.
Sprint SPRINT_20260422_003_Authority_auto_migration_compliance created
and archived in the same pass.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
test-targeted-xunit.ps1 verified end-to-end against
SchedulerStorageConfigurationTests (3/3 pass via direct DLL exec).
QA flow + testing-practices docs updated.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
SchedulerStorageConfiguration ResolveConnectionString supports flat,
compose-nested, and legacy keys; web host fails fast with a clear
message listing all three. Targeted xUnit run of
SchedulerStorageConfigurationTests passes 3/3.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
All three tasks are now DONE per the 2026-04-19 execution log:
- ADV-SETUP-006 setup source probe/apply reflects real connectivity
- ADV-SETUP-007 enabled-but-broken advisory warning + auth helper
- ADV-SETUP-008 targeted Platform + Concelier xUnit verification
passed via the direct xUnit runner workflow.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Archived sprint files inherit the rename without the post-move status edits
since git recorded the rename against pre-edit content. Applies the
OBSOLETE/DONE annotations directly on the archived copies so the record is
internally consistent.
Integration-detail component + spec: small polish pass. integration-hub-ui
spec: trivial assertion tweak. Playwright: refreshed live-frontdoor-auth
snapshot.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds SPRINT_20260415_001_DOCS_real_service_cutover_plan tracking the doc
work needed to finalize the no-mocks / real-service migration.
Archives SPRINT_20260415_002_FE_integration_hub_truthful_status_and_button_styling
— both tasks complete (truthful integration status + button styling fix
landed in the earlier Web UI commit).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Closes SPRINT_20260408_002_Findings_vulnexplorer_ledger_merge via Option B:
- Phase 1 (VXPM-001..005) marked OBSOLETE. The separate vulnexplorer
schema was superseded by commit 6b15d9827 (direct merger into Findings
Ledger); there is no separate Postgres schema to build.
- Phase 2 corrections: VXLM-003/004/005 flipped to DONE. The adapter
ConcurrentDictionary pattern is accepted as the VXLM-003 closure — these
are read-side projections over Ledger events; durability comes from the
append-only event log, not from the adapter. Two follow-ups logged in
Decisions & Risks (FOLLOW-A: write-through Ledger event emission;
FOLLOW-B: /api/v1/vulnerabilities gateway route alignment).
- Deletes stale VulnExplorer project trees:
- src/Findings/StellaOps.VulnExplorer.Api/ (entire service)
- src/Findings/StellaOps.VulnExplorer.WebService/ (shell + migrated contracts)
- src/Findings/__Tests/StellaOps.VulnExplorer.Api.Tests/ (tests targeted
SampleData IDs that no longer exist under Ledger)
- src/Findings/StellaOps.Findings.Ledger.WebService/Services/
VulnExplorerRepositories.cs (33-line placeholder with a misleading
header comment; the actual Postgres path was never wired)
- Updates StellaOps.sln and Findings.sln to drop the removed project GUIDs
and their 24 configuration entries. dotnet build
src/Findings/StellaOps.Findings.sln passes 0 warnings / 0 errors.
Also archives the 4 previously-closed sprints:
- SPRINT_20260408_002 Findings VulnExplorer merger (above)
- SPRINT_20260410_001 Web runtime no-mocks (21/21 tasks done via earlier
Postgres persistence commits)
- SPRINT_20260413_002 Integrations GitLab bootstrap automation
- SPRINT_20260413_003 Web UI-driven local setup rerun
- SPRINT_20260413_004 Platform UI-only setup bootstrap closure
Active sprints reduced to 2: SPRINT_20260408_004 Timeline unified audit
sink (15-25hr breadth work) and SPRINT_20260408_005 Audit endpoint filters
deprecation (mandatory 30/90-day verification windows).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
TASK-013: SchedulerPersistenceExtensions now calls AddStartupMigrations so
the embedded SQL files (including 007 job_kind + 008 doctor_trends) run on
every cold start. Deletes duplicate migrations 007_add_job_kind_plugin_config
(kept 007_add_schedule_job_kind.sql with tenant-scoped index) and
008_doctor_trends_table (kept 008_add_doctor_trends.sql with RLS + BRIN
time-series index).
TASK-010: Doctor UI trend service now calls
/api/v1/scheduler/doctor/trends/categories/{category} (was
/api/v1/doctor/scheduler/...) so it routes through the scheduler plugin
endpoints rather than the deprecated standalone doctor-scheduler path.
TASK-009: New DoctorJobPluginTests exercises plugin lifecycle: identity,
config validation for full/quick/categories/plugins modes, plan creation,
JSON schema shape, and PluginConfig round-trip (including alerts). 10 tests
added, all pass (26/26 in Plugin.Tests project).
Archives the sprint — all 13 tasks now DONE — and archives the platform
retest sprint (SPRINT_20260409_002) whose RETEST-008 completed via the
earlier feed-mirror cleanup.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Adds MigrationSqlTransactionClassifier to recognize migration SQL that opens
its own transactions (BEGIN/COMMIT/ROLLBACK) so MigrationRunner can skip
wrapping those files in an outer transaction. StartupMigrationHost now surfaces
a MigrationCategory indicator for runtime-aligned bootstrap. Test harness
extended with an explicit-transaction fixture and execution scenario coverage.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Completes Sprint 323 TASK-001 using Option C (direct URL rewrite):
- release-management.client.ts: readBaseUrl and legacyBaseUrl now use
/api/v1/release-orchestrator/releases, eliminating the v2 proxy dependency
- All 15+ component files updated: activity, approvals, runs, versions,
bundle-organizer, sidebar queries, topology pages
- Spec files updated to match new URL patterns
- Added /releases/activity and /releases/versions backend route aliases
in ReleaseEndpoints.cs with ListActivity and ListVersions handlers
- Fixed orphaned audit-log-dashboard.component import → audit-log-table
- Both Angular build and JobEngine build pass clean
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All sprint tasks marked DONE verified via Playwright canonical route sweep
(111/111 routes passing). Remaining active: Sprint 025 (BLOCKED on Node
heap exhaustion in full test suite).
New sprint: SPRINT_20260316_001 — First-Time User Experience Fixes (7 tasks).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
All 6 tasks DONE: consumer API endpoints, 4-step setup wizard UI,
dashboard and catalog integration, air-gap import API, E2E tests,
and documentation.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Backend: ExtractParameters() now discovers query params from [AsParameters]
records and [FromQuery] attributes via handler method reflection. Gateway
OpenApiDocumentGenerator emits parameters arrays in the aggregated spec.
QueryParameterInfo added to EndpointSchemaInfo for HELLO payload transport.
Frontend: Remaining spec files and straggler services updated to canonical
X-Stella-Ops-* header names. Sprint 026 archived (tasks 01-06 DONE,
07-09 TODO for backend service rename pass).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>