Concelier Unified Issue Projection

The unified issue projection is the Stella Ops Mirror skeleton used by Scanner, Findings, Policy, VEX, and advisory views to discuss the same vulnerability without collapsing the underlying source evidence.

Contract

Tables

Migration 026_add_unified_issue_projection.sql creates these tables and is embedded in StellaOps.Concelier.Persistence, so fresh databases converge on service startup.

API

Read endpoints require Concelier.Advisories.Read. Backfill requires Concelier.Advisories.Ingest and must be run in chunks so mirror aggregation continues to make progress.

The consensus-metrics owner validates that the store result belongs to the authenticated tenant and that 0 <= multiSourceCveCount <= totalCveCount. Projection timeouts/database failures return a sanitized 503 error envelope with error.code: "ISSUE_CONSENSUS_METRICS_UNAVAILABLE" and metadata state: "degraded", retryable: true. An impossible or cross-tenant store result returns ISSUE_CONSENSUS_METRICS_INVALID with state: "invalid", retryable: false; the foreign tenant or underlying exception detail is never returned.

For local/recovery runs where the automation client cannot mint the ingest scope, the repository tool exposes the same production store backfill path:

dotnet run --project src\Concelier\StellaOps.Concelier.MirrorSeedTool\StellaOps.Concelier.MirrorSeedTool.csproj -- `
  backfill-issues `
  --connection-string "<postgres dsn>" `
  --tenant-id default `
  --source advisory,vex-claims `
  --limit 50000 `
  --max-iterations 5

Use --after <lastCursor> when continuing one source across batches. Large vex.claims stores are disk-sensitive because every claim can materialize an observation/evidence row. On the 2026-05-11 workstation, roughly 0.9M issue observations were enough to add several GB to PostgreSQL, so the live backfill was stopped before host disk exhaustion and the clean replay proof was moved to a bounded E2E fixture.

Operational replay contract

Each bounded source batch and its affected-linkset refresh commit in one PostgreSQL transaction. The store applies a transaction-local 300-second server statement_timeout and the same Npgsql client timeout; the longer maintenance budget therefore cannot leak back into the connection pool. Any cancellation or refresh failure rolls back the batch, and the background service persists a new last_cursor only after the complete operation succeeds. A repeated 57014 is a retryable failed batch, not evidence that replay has completed.

The source schema owner must also provide an index matching each keyset cursor. For vex.claims, Excititor startup migration 009_issue_projection_claims_cursor_index.sql owns idx_claims_issue_projection_cursor (tenant, created_at, claim_hash). On a large existing mirror, operators can create that exact index CONCURRENTLY before the Excititor restart; the idempotent startup migration then records convergence without rebuilding it. Do not reset projection cursors to work around a missing index or timeout failure.

Stella Ops Mirror Seed

stellaops-mirror-seed-v1 exports the projection tables together with the public/no-credential connector stores. Import should run before Concelier and Excititor schedulers start, then schedulers resume from imported cursors instead of refetching the whole bootstrap dataset.

The WebService seed endpoints are:

The archive stores manifest.json plus Zstandard-compressed PostgreSQL COPY chunks under data/*.copy.zst. The manifest records format version, tenant, checkpoint mode, build version/source revision where available, active work for checkpointed exports, source/provider summaries, per-table columns, row counts, byte counts, and SHA-256 hashes. Import validation verifies the manifest and target schema before any row copy, and normal import rejects non-empty target tables unless the caller explicitly requests replacement.

Fresh setup uses the Mirror:SeedImport startup gate. When enabled, Concelier imports or validates the seed before mirror export and source scheduler hosted services start. The default restart behavior skips the import when target tables already contain mirror rows, while real validation/import failures stop startup before schedulers can redownload from upstream.

The seed remains secret-free:

If a live database has not yet applied the issue-projection migration, the seed manifest records the projection tables as skipped. That archive can still seed source stores and VEX claims, but it is not the final issue-skeleton seed until the migration and projection backfill have run.

The repeatable setup proof is devops/mirror/test-concelier-seed-import-e2e.ps1. It applies real Concelier and Excititor startup migrations to isolated source and target PostgreSQL containers, exports a bounded seed containing advisory and VEX issue evidence, imports it through Mirror:SeedImport before Concelier schedulers start, and verifies the imported target counts plus credential stripping.