Microservice → database ownership matrix
Status: evidence inventory (current state verified 2026-07-22) + Accepted target (ADR-039 rev-4, owner-approved 2026-07-22). Sources: devops/compose/docker-compose.stella-services.yml, live stellaops-postgres catalog (read-only), AddStartupMigrations sweep over src/, docs/agent-playbooks/data-and-stores.md. src/ wins over this document; rows marked (verify) lack a confirmed code anchor.
1. Current physical reality (measured 2026-07-22)
- One shared instance
stellaops-postgres(postgres:18.1), one volume (99.25 GB), three databases:stellaops_platform91 GB,stellaops_authority252 MB,postgres7.7 MB. - Every service except Authority connects with the same
STELLAOPS_POSTGRES_CONNECTION(→stellaops_platform). ~46 service schemas share that database. - Vulnerability data plane inside
stellaops_platform:vuln71 GB,vex9,625 MB,vexhub5,908 MB,concelier2,322 MB ≈ 89 GB = 97.8%. Everything else totals < 3 GB (largest:scanner2,110 MB,advisoryai271 MB,timeline199 MB;platformitself 2,024 kB).
2. Deployable → schema matrix
Replica sets (web/worker/init of one service) are one row — they legitimately share the owner database. Wave = adoption wave from ADR-039 (1 = vulnerability plane now, 2 = large/high-churn next, 3 = small batch moves). Risk = migration risk of the move itself.
| Deployable(s) (compose) | Schemas written today | Migration assembly (AddStartupMigrations) | Category | Proposed database / role (stellaops_*) | Cluster | Wave | Risk |
|---|---|---|---|---|---|---|---|
| platform | platform, shared | Platform.Database | control plane | platform — DB name stays stellaops_platform(owner correction 2026-07-22; keeps shared.tenants while the resolver contract stands) | control | — (stays) | low |
| authority | authority (own DB already) | Authority.Persistence | control plane | authority (done — the precedent) | control | done | — |
concelier (+ concelier-jobs-init) → merges into StellaOps.Vulnerabilities | concelier (sources/DTOs/jobs), vuln canonical advisory tables + issue_observations/_evidence_refs/_linksets (global consensus) | Concelier.Storage → Vulnerabilities.Persistence | data plane (hub) | vuln(single hub DB stellaops_vuln, ADR-039 D2; fresh build, no data moved — D7) | vulndata | 1 | rename + rebuild, no data migration |
concelier (today’s serving role) — vuln.issue_gate_decisions + rebuild queue | per-tenant gate projection | Concelier.Storage (today) | control plane (tenant decisions) | moves to policy— Policy-owned projection fed by hub events (ADR-039 D3) | control | 1 | rebuilt by Policy projector |
excititor-web + excititor-worker → merges into StellaOps.Vulnerabilities | vex (claims, raw blobs/documents, product dedup, checkpoints, quarantine) | Excititor.Persistence → Vulnerabilities.Persistence | data plane (hub) | vuln | vulndata | 1 | rename + rebuild |
vexhub-web → merges into StellaOps.Vulnerabilities | vexhub (statements, sources, provenance, conflicts) — rows currently written by Excititor’s sink, not by VexHub | VexHub.Persistence → Vulnerabilities.Persistence (dist schema) | data plane (distribution view, rebuildable) | vuln | vulndata | 1 | rename + rebuild |
| scanner-web + scanner-worker (+ cache-init) | scanner (106 tables, 2.1 GB) | Scanner.Storage | data plane | scanner | control | 2 | medium |
| advisory-ai-web + advisory-ai-worker (+ data-init) | advisoryai | AdvisoryAI hosting | data plane | advisoryai | control | 2 | low |
| opsmemory-web | opsmemory | OpsMemory | control plane | opsmemory | control | 3 | low |
| timeline-web | timeline (+ timeline_app) | Timeline persistence | evidence/read-model | timeline | control | 2 | low |
| notify-web | notify (+ notify_app) | Notify.Persistence | control plane | notify | control | 2 | low |
| notifier-worker | notifier (verify: compose points notifier__storage__postgres at shared DB; live schema is empty) | — (verify) | control plane | notifier (or fold into notify if same service — decide in Wave 2) | control | 2 | low |
| policy-engine | policy (+ policy_app); plus foreign writes: scheduler (via its scheduler connection), release.security_finding_projection (verify writer path); foreign read: vuln.issue_gate_decisions | Policy.Persistence | control plane | policy | control | 2 | medium (contracts, not size) |
| scheduler-web | scheduler (+ scheduler_app) | Scheduler.Persistence (JobEngine) | control plane | scheduler | control | 2 | low |
| release-orchestrator (+ agent-ca-init) | release (83 tables), release_orchestrator, release_orchestrator_agent, scripts | ReleaseOrchestrator(+.Environment) | control plane | release_orchestrator (all four schemas) | control | 3 | medium (Platform/Policy seams) |
| agent-core | (verify — likely none / registry cache volumes) | — | control plane | — | — | 3 | low |
| attestor (+ tileproxy, tsa) | attestor, proofchain | Attestor.Persistence | evidence | attestor | control | 3 | low |
| signer | signer, crypto (CredentialStore shared lib) | Signer.KeyManagement + CredentialStore | control plane | signer (crypto schema instantiates per host DB per ADR-039 P4) | control | 3 | low |
| evidence-locker-web + worker | evidence_locker (+ _app) | EvidenceLocker persistence | evidence | evidence_locker | control | 3 | low |
| findings-ledger-web | findings | Findings ledger persistence | data plane | findings | control | 3 | low |
| riskengine-web + worker | riskengine | RiskEngine | data plane | riskengine | control | 3 | low |
| findings-security-web | findings_security | Findings.Security.Persistence | read-model | findings_security | control | 3 | low |
| findings-vulncorrelation | analytics | Findings.VulnCorrelation.Persistence | read-model | vulncorrelation | control | 3 | low |
| signals | signals | Signals.Persistence | data plane | signals | control | 3 | low |
| sbomservice | sbom | SbomService.Persistence | data plane | sbomservice | control | 3 | low |
| graph-api | graph | Graph.Indexer.Persistence | data plane | graph | control | 3 | low |
| reachgraph-web | reachgraph | ReachGraph.Persistence | data plane | reachgraph | control | 3 | low |
| binaryindex-web | binaries, binary_index, golden_sets(runtime — BinaryIndex.WebService/Program.cs:48 auto-migrates it via AddStartupMigrations; previously mislabeled bench, round-20 correction) | BinaryIndex persistence | data plane | binaryindex | control | 3 | low |
| symbols | symbols | Symbols runtime persistence | data plane | symbols | control | 3 | low |
| export-web + export-worker | export_center (+ _app) | ExportCenter persistence | control plane | export_center | control | 3 | low |
| replay-web | replay | Replay.WebService | evidence | replay | control | 3 | low |
| integrations-web | integrations | Integrations.Persistence | control plane | integrations | control | 3 | low |
| packsregistry-web + worker | packs | PacksRegistry.Persistence | control plane | packsregistry | control | 3 | low |
| doctor-web (+ evidence-init) | doctor | Doctor persistence | ops | doctor | control | 3 | low |
| issuer-directory | issuer | IssuerDirectory persistence | control plane | issuer_directory | control | 3 | low |
| vexlens-web | vexlens | VexLens persistence | read-model | vexlens | control | 3 | low |
| airgap-controller | airgap | AirGap persistence | control plane | airgap | control | 3 | low |
| registry-token | registry_token | Registry token persistence | control plane | registry_token | control | 3 | low |
| unknowns-web | unknowns (schema not yet present live) | Unknowns.Persistence | data plane | unknowns | control | 3 | low |
replay/tester, workflow host (verify — workflow schema, 10 tables, host unconfirmed) | workflow | Workflow.DataStore.PostgreSQL | control plane | with its host service | control | 3 | low |
| bench/tools (non-runtime) | groundtruth, public | — | fixtures/bench | out of runtime scope; must not block waves (golden_sets moved to the binaryindex-web row — it is runtime; round-20 correction) | — | 3 | low |
Notes:
- “One microservice, several replicas” (scanner-web/worker, excititor-web/worker, export web/worker, evidence-locker web/worker, riskengine web/worker, packsregistry web/worker, advisory-ai web/worker) share one owner database by design. Concelier vs. Excititor vs. VexHub are independent deployables and get independent databases — this matrix does not reinterpret database-per-service as schema-per-service.
- The
vulnschema today mixes two ownership categories (Concelier canonical advisory source vs. rebuildable serving projection); in the target both live inside the single hub databasestellaops_vulnas internal schemas (ingest/factsvsconsensus/dist) per the v2 design — the rev-1 two-database split (stellaops_concelier+stellaops_vuln) was superseded by D2.
3. Cross-service SQL inventory (violations to burn down)
| # | Consumer → target | Kind | Evidence | Disposition (target, ADR-039 rev-2) |
|---|---|---|---|---|
| X1 | Excititor worker → vuln.issue_observations/_evidence_refs/_linksets | DELETE (destructive, cross-owner) | src/Concelier/StellaOps.Excititor.Worker/Scheduling/VexRetentionSweepService.cs:111-130 | Freeze now (D6); disappears entirely with consolidation — v2 has no retention sweep at all |
| X2 | Excititor (web+worker) → vexhub.statements | write (cross-owner) | src/Concelier/__Libraries/StellaOps.Excititor.Persistence/Postgres/VexHub/PostgresVexHubProjectionSink.cs:461-487 | Becomes internal to StellaOps.Vulnerabilities (D2): a rebuildable dist projection driven by the hub outbox |
| X3 | Policy engine → vuln.issue_gate_decisions + vuln.advisory_affected(matcher rows via VulnMatch.Core/IAdvisoryRowSource) | read | src/Policy/StellaOps.Policy.Engine/Services/PostgresFindingsLookup.cs:1083,1135 (+ advisory_affected reads; src/__Libraries/StellaOps.VulnMatch.Core/IAdvisoryRowSource.cs) | Killed by D3 + DC-30 v2: gates → Policy-owned projection fed by hub events; matcher rows → the generation-stamped compact corpus artifact consumed via VulnDb.Compact (one artifact for every matcher host, online = offline); no cross-DB read remains (P15); no advisory-row tables outside the hub |
| X4 | CLI compact vuln-db export → vuln.issue_gate_decisions ⋈ vuln.issue_linksets | read (cross-DB JOIN) | src/Cli/StellaOps.Cli/Commands/VulnDb/PostgresCompactVulnDbCorpusSource.cs:126-164 | Killed by D3: CLI reads the hub’s global corpus-export API (the export is global data; reading tenant gates was a category error) |
| X5 | CLI mirror-seed / archive rebuild → concelier/vuln | write (ops tool as owner) | src/Cli/StellaOps.Cli/Commands/MirrorSeedCommandGroup.cs:472,547; src/Concelier/__Libraries/StellaOps.Concelier.Persistence/Postgres/MirrorSeed/* | Becomes the hub’s mirror import/export plugins (D2); the CLI drives the hub API, never SQL |
| X6 | Authority → shared.tenants (platform DB) | write | src/Authority/StellaOps.Authority/StellaOps.Authority/Tenants/SharedTenantsPropagation.cs:397 (falls back to STELLAOPS_POSTGRES_CONNECTION) | Killed by D10: Authority is sole tenancy owner in stellaops_authority; shared.tenants becomes an event-carried replica or is retired; Authority never touches the platform DB |
| X7 | Authority → platform DB (IdP provider import) | read | compose docker-compose.stella-services.yml:507 | Killed by D10: IdP configuration is Authority-owned (completes the SPRINT_20260718_006 direction) |
| X8 | Policy engine → scheduler schema | write via Scheduler.Persistence client | compose docker-compose.stella-services.yml:1751-1752 | Wave 2 decision: JobEngine API/queue, or the scheduler client persists into Policy’s own DB (P4) (verify current semantics first) |
| X9 | corrected (dig 2026-07-22): all projection code lives in StellaOps.Findings.Security.* (owns findings_security.security_finding_projection); the release.-schema copy (574 rows) has no code writer found — suspected legacy duplicate | — | grep sweep 2026-07-22; live row counts | Findings copy → owned by 010; release. copy → confirm + retire in SPRINT_20260722_018 RO-1 |
| X10 | Doctor DB checks → many schemas | read-only monitoring | src/__Libraries/StellaOps.Doctor.Plugins.Database/Checks/DatabaseCheckBase.cs:17 | Killed by D11/P11: doctor checks become plugins hosted inside each service; Doctor aggregates via APIs and holds no cross-DB connections. Doctor also reads shared.tenants directly (SharedTenantsDoctorTenantCatalog) — dies with the 009 retirement |
| X11 | Findings.Security → scanner.* | read (SQL joins) | src/Findings/__Libraries/StellaOps.Findings.Security.Persistence/Stores/SecurityFindingProjectionStore.cs (FROM scanner.) | Disposition in SPRINT_20260722_010 (owner API / event-carried projection) before Scanner’s grant revocation (017) |
| X12 | Integrations → scanner.* | read | src/Integrations/StellaOps.Integrations.WebService/PostgresRegistryImageSeverityCountProvider.cs | Disposition in SPRINT_20260722_024 before 017’s revocation |
| X13 | Policy → scanner.* | read | src/Policy/StellaOps.Policy.Engine/Services/PostgresFindingsLookup.cs | Disposition with the 007 lookup replacement (same file as X3) |
| X14 | Every tenant-resolving service → shared.tenants | read via shared library | src/Authority/StellaOps.Authority/StellaOps.Auth.ServerIntegration/Tenancy/StellaOpsTenantResolver.cs (ADR-010); direct readers: IssuerDirectory, Doctor | The library mechanism is built once in SPRINT_20260722_027 (replica tables per host DB, dual-mode rollout; covers shared.actor_identity too); 016 lands the tenants producer |
| X15 | platform-web migrates ~23 foreign schemas (central migrator) | cross-service DDL/migrations | src/Platform/__Libraries/StellaOps.Platform.Database/MigrationModulePlugins.cs — 24 IMigrationModulePlugin entries (airgap, authority, binaries, evidence, evidence_locker, export_center, graph, integrations, issuer, notify, packs, policy, proofchain, reachgraph, release_orchestrator, remediation, sbom, scheduler, signer, timeline×2, unknowns, workflow, + platform’s own). Explains the 0-byte shell schemas and X9’s origin (archived mig061/Release/050_SecurityDispositionProjection.sql). Runtime faces: PlatformMigrationAdminService + /api/v1/admin/* (incl. seed-demo), CLI MigrationCommandService manual applier | DC-26: each program deletes its plugin in the same change as its DB move (recipe S3/M1); the mechanism + runtime faces retire early in SPRINT_20260722_026; 021 PLT-4 final sweep |
| X16 | ReleaseOrchestrator ⇄ platform-schema plugin-registry tables | read/write via shared library | src/Plugin/StellaOps.Plugin.Registry/PostgresPluginRegistry.cs; consumers: ReleaseOrchestrator.WebApi/Program.cs, ReleaseOrchestrator.Plugin/Registry/ConnectorRegistry.cs; migrated by Platform’s PluginRegistryMigrationModulePlugin | P4 pattern (019 SGN-2): Plugin.Registry instantiates its tables in the host’s own DB (RO’s registry → stellaops_release_orchestrator, in 018); Platform keeps its own instance; the central plugin entry dies with DC-26 |
| X17 | Eventing producers → timeline.outbox/timeline.events | write via shared library | src/__Libraries/StellaOps.Eventing (EventingDbContext.cs:35,69 — ToTable("events"/"outbox", schemaName)); hosts: VexLens, Findings-Ledger, Concelier (Feedser.Core), Timeline; schema centrally migrated (X15 EventingMigrationModulePlugin) | DC-29: P6 is delivered by evolving StellaOps.Eventing — per-host outbox tables (P4), DC-06 envelope, new inbox/lease/fencing; Timeline becomes a stream consumer via the existing ITimelineStreamBridge; shared-DB tables retire with the producers’ moves |
| X18 | Findings.Security → vuln.* (heavy) | read (SQL joins) | SecurityFindingProjectionStore.cs + AggregatedRiskStatusService.cs join vuln.sbom_canonical_match, vuln.sbom_registry, vuln.advisory_canonical, vuln.advisories, vuln.advisory_cvss, vuln.kev_flags(the exploited-flag reader) | Disposition (010 + DC-30): advisory/CVSS/exploited data → corpus artifact + hub events; sbom_registry + sbom_canonical_match are artifact-scoped match RESULTS, not global knowledge — they move to the Findings family’s ownership (control plane), never into the tenant-free hub |
| X19 | SbomService → vuln.sbom_canonical_match | write (BYOS upload “produces real vuln.sbom_canonical_match rows”, SbomUploadService.cs:179) | src/SbomService/StellaOps.SbomService/Services/SbomUploadService.cs | Dies with the X18 re-homing: SbomService publishes an sbom.uploaded event; match computation runs on the corpus artifact in the Findings family (010); Scanner’s historical involvement (Scanner.WebService/Program.cs:1279 comment “Scanner no longer…”) confirmed in 017 S0 |
| X20 | Scanner.Worker → ReachGraph | write (HTTP publisher) | Scanner.Worker/Processing/Reachability/Publishers/HttpReachGraphPublisher.cs posts ReachGraphMinimal to POST /v1/reachgraphs when ScannerWorkerOptions.PublishToReachGraph is true (base URL option, e.g. http://reachgraph:8080); stage: ReachabilityPublishStageExecutor | 023 merge preserves the POST /v1/reachgraphs contract + keeps the reachgraph network alias during transition; Scanner repoints its base-URL option at its next deploy (coordinate with 017); contract test pins the writer alongside the two pinned readers |
Approved read-contract register (ADR-039 P5): transitional only — X6/X7 until D10 lands, X10 until D11 lands, X8/X9 until their Wave-2 dispositions. The target register is empty. New entries require an ADR-039 amendment.
4. Shared-fallback burn-down
Code that resolves STELLAOPS_POSTGRES_CONNECTION outside Platform (must fail closed instead — ADR-039 P3): Authority SharedTenantsPropagation.cs:397; CLI MigrationCommandService.cs:408 and MirrorSeedCommandGroup.cs:547; every compose service env described in §1. The conformance test in ADR-039 P10 pins this list and fails on additions.
5. Full rename map — every container: current → target
Legend: unchanged = same name/src path. (verify) = project name not yet confirmed against a code anchor — the owning program’s S0 task confirms it. D12 DAL renames (…Storage/…Database → StellaOps.<Service>.Persistence) land with each service’s own wave, never out-of-band. “shared DB” = stellaops_platform (name kept — owner correction 2026-07-22; the bare stellaops name applies at the container/instance level, aligned at endgame per SPRINT_20260722_021 PLT-2).
5.1 Vulnerabilities program (sprints 003–008)
| Current microservice | Src path | DB project(s) used | DB used | New microservice | New src path | New DB project | New DB |
|---|---|---|---|---|---|---|---|
| concelier (+ concelier-jobs-init) | src/Concelier/StellaOps.Concelier.WebService | StellaOps.Concelier.Persistence | shared DB (concelier, vuln) | StellaOps.Vulnerabilities (vulnerabilities-web/-worker) | src/Vulnerabilities/ | StellaOps.Vulnerabilities.Persistence | stellaops_vuln |
| excititor-web + excititor-worker | src/Concelier/StellaOps.Excititor.WebService / .Worker | StellaOps.Excititor.Persistence | shared DB (vex) | merged ↑ | src/Vulnerabilities/ | merged ↑ | stellaops_vuln |
| vexhub-web | src/VexHub/ | StellaOps.VexHub.Persistence | shared DB (vexhub) | merged ↑ (dist schema) | src/Vulnerabilities/ | merged ↑ | stellaops_vuln |
| vexlens-web | src/VexLens/ | VexLens persistence (verify) | shared DB (vexlens) | folds into Vulnerabilities (hub close-out evaluation) | src/Vulnerabilities/ | merged ↑ | stellaops_vuln |
| — (EPSS data only) | src/Scanner/ EPSS connector tables | StellaOps.Scanner.Storage | shared DB (scanner.epss_*, ~2.05 GB) | data relocates to the hub (P14); Scanner keeps no EPSS tables | — | StellaOps.Vulnerabilities.Persistence | stellaops_vuln |
5.2 Family merge programs (sprints 010–016)
| Current microservice | Src path | DB project(s) used | DB used | New microservice | New src path | New DB project | New DB |
|---|---|---|---|---|---|---|---|
| findings-ledger-web | src/Findings/StellaOps.Findings.Ledger.WebService | StellaOps.Findings.Ledger (library w/ migrations) | shared DB (findings) | StellaOps.Findings (findings-web/-worker) | src/Findings/StellaOps.Findings.WebService/.Worker | StellaOps.Findings.Persistence | stellaops_findings |
| riskengine-web + riskengine-worker | src/Findings/StellaOps.RiskEngine.WebService/.Worker | StellaOps.RiskEngine.Core (store wired in WebService) | shared DB (riskengine) | merged ↑ (scoring = worker role) | ↑ | merged ↑ | stellaops_findings |
| findings-security-web | src/Findings/StellaOps.Findings.Security.WebService | StellaOps.Findings.Security.Persistence | shared DB (findings_security) | merged ↑ | ↑ | merged ↑ | stellaops_findings |
| findings-vulncorrelation | src/Findings/StellaOps.Findings.VulnCorrelation.WebService | StellaOps.Findings.VulnCorrelation.Persistence | shared DB (analytics) | merged ↑ | ↑ | merged ↑ | stellaops_findings |
| attestor | src/Attestor/StellaOps.Attestor.WebService | Attestor.Persistence (ProofChainDbContext) | shared DB (attestor, proofchain) | StellaOps.Evidence (owner-widened, 011) | src/Evidence/ | StellaOps.Evidence.Persistence | stellaops_evidence |
| attestor-tileproxy | src/Attestor/StellaOps.Attestor.TileProxy | — | — | role of StellaOps.Evidence | ↑ | — | — |
| tsa | infra container from devops/docker/tsa/ (openssl RFC3161 — no .NET host) | — | tsa-data volume | infra role of StellaOps.Evidence | devops/docker/tsa/ | — | — |
| evidence-locker-web + worker | src/EvidenceLocker/StellaOps.EvidenceLocker (one project; web+worker = role containers) | migrations embedded in StellaOps.EvidenceLocker(.Infrastructure) | shared DB (evidence_locker) | merged into StellaOps.Evidence (011) | src/Evidence/ | merged ↑ | stellaops_evidence |
| scheduler-web | src/JobEngine/StellaOps.Scheduler.WebService (+ Worker.Host) | StellaOps.Scheduler.Persistence | shared DB (scheduler) | StellaOps.JobEngine (jobengine-web/-worker) | src/JobEngine/StellaOps.JobEngine.WebService/.Worker | StellaOps.JobEngine.Persistence | stellaops_jobengine |
| packsregistry-web + packsregistry-worker | src/JobEngine/StellaOps.PacksRegistry | StellaOps.PacksRegistry.Persistence | shared DB (packs) | merged ↑ | ↑ | merged ↑ | stellaops_jobengine |
| advisory-ai-web + advisory-ai-worker | src/AdvisoryAI/StellaOps.AdvisoryAI.WebService/.Worker | AdvisoryAI hosting migrations (verify) | shared DB (advisoryai) | StellaOps.AdvisoryAI (advisoryai-web/-worker) | same module, consolidated hosts | StellaOps.AdvisoryAI.Persistence | stellaops_advisoryai |
| opsmemory-web | src/AdvisoryAI/StellaOps.OpsMemory.WebService | StellaOps.OpsMemory | shared DB (opsmemory) | merged ↑ (module) | ↑ | merged ↑ | stellaops_advisoryai |
| binaryindex-web | src/BinaryIndex/StellaOps.BinaryIndex.WebService (+ .Worker) | StellaOps.BinaryIndex.Persistence | shared DB (binaries, binary_index) | dissolves into the hub (DC-33): connector family + binary fact class + artifact content + internal VEX deriver; deployable retires | src/Vulnerabilities/ | hub persistence | stellaops_vuln |
| symbols | src/BinaryIndex/StellaOps.Symbols.Server | symbols runtime persistence | shared DB (symbols) | hub-adjacent global CAS (catalog in hub; blobs → object store, P16); deployable retires | src/Vulnerabilities/ | hub persistence | stellaops_vuln |
| notify-web | src/Notify/StellaOps.Notify.WebService | StellaOps.Notify.Persistence | shared DB (notify) | StellaOps.Notify (notify-web/-worker) | src/Notify/ | StellaOps.Notify.Persistence (kept) | stellaops_notify |
| notifier-worker | src/Notifier/StellaOps.Notifier/StellaOps.Notifier.WebService + .Worker (only worker deployed) | own schema live-empty; hosts a crypto CredentialStore instance | shared DB (notifier, empty) | merged ↑ (worker role); src/Notifier/ deleted | src/Notify/ | merged ↑ | stellaops_notify |
| issuer-directory | src/Authority/StellaOps.IssuerDirectory/StellaOps.IssuerDirectory.WebService | IssuerDirectory.Infrastructure | shared DB (issuer) | role of StellaOps.Authority (S0 decision on container shape) | src/Authority/ | StellaOps.Authority.Persistence | stellaops_authority |
| authority | src/Authority/StellaOps.Authority | StellaOps.Authority.Persistence | stellaops_authority (already own DB) | unchanged + D10 (tenants/IdP sole owner; zero platform-DB access) | unchanged | unchanged | stellaops_authority |
5.3 Same service, new database (Waves 2–3; D12 DAL rename where deviating)
Owning programs: Scanner → SPRINT_20260722_017; ReleaseOrchestrator → 018; Signer → 019; Platform → 021 (endgame); Graph+ReachGraph → 023; Integrations+registry-token → 024; EvidenceLocker → 011; doctor-web → retirement via 009; remediation → archived; ExportCenter + AirGap (+ Mirror.Creator) → 025 (OfflineKit, owner-approved); every other row → SPRINT_20260722_020 (batch).
| Current microservice | Src path | DB project(s) used | DB used | New microservice | New src path | New DB project | New DB |
|---|---|---|---|---|---|---|---|
| platform | src/Platform/ | StellaOps.Platform.Database | shared DB (platform, shared) | unchanged | unchanged | StellaOps.Platform.Persistence (D12) | stellaops_platform(name kept — owner correction; container/instance naming aligned at PLT-2) |
| policy-engine | src/Policy/StellaOps.Policy.Engine | StellaOps.Policy.Persistence | shared DB (policy) | unchanged + gains vuln gate projection (D3, sprint 007) | unchanged | unchanged | stellaops_policy |
| scanner-web + scanner-worker (+ cache-init) | src/Scanner/ | StellaOps.Scanner.Storage | shared DB (scanner, minus EPSS) | unchanged | unchanged | StellaOps.Scanner.Persistence (D12) | stellaops_scanner |
| release-orchestrator (+ agent-ca-init) | src/ReleaseOrchestrator/ | StellaOps.ReleaseOrchestrator.Persistence (+ Environment data source in WebApi) | shared DB (release, release_orchestrator, release_orchestrator_agent, scripts) | unchanged | unchanged | consolidated StellaOps.ReleaseOrchestrator.Persistence | stellaops_release_orchestrator |
| signer | src/Attestor/StellaOps.Signer | Signer.KeyManagement + CredentialStore libs (crypto) | shared DB (signer, crypto) | unchanged — stays separate (key custody, D14) | unchanged | StellaOps.Signer.Persistence (D12; crypto schema instantiates per host, P4) | stellaops_signer |
| evidence-locker-web + worker | — row moved to §5.2 (Evidence merge, 011) — | ||||||
| timeline-web | src/Timeline/ | Timeline persistence (verify) | shared DB (timeline) | unchanged (+ audit-event partitioning, review §3) | unchanged | per D12 | stellaops_timeline |
| export-web + export-worker | src/ExportCenter/StellaOps.ExportCenter/* (WebService/Worker/Infrastructure + Cra/Nis2/StandardsMapping/RiskBundles adapters) | ExportCenter.Infrastructure | shared DB (export_center, 16 tables) | StellaOps.OfflineKit (owner-approved EVL-3, 025) | src/OfflineKit/ | StellaOps.OfflineKit.Persistence | stellaops_offlinekit |
| replay-web | src/Replay/ | in-WebService store (PostgresFeedSnapshotIndexStore) | shared DB (replay) | unchanged | unchanged | StellaOps.Replay.Persistence (D12: extract from WebService) | stellaops_replay |
| integrations-web | src/Integrations/ | Integrations.Persistence (IntegrationDbContext) | shared DB (integrations) | StellaOps.Integrations + registry-token role (owner-approved, 024) | src/Integrations/ | StellaOps.Integrations.Persistence | stellaops_integrations |
| signals | src/Signals/ | StellaOps.Signals.Persistence | shared DB (signals) | unchanged | unchanged | unchanged | stellaops_signals |
| sbomservice | src/SbomService/ | StellaOps.SbomService.Persistence | shared DB (sbom) | SBOM system of record (DC-34): absorbs vuln.sbom_registry + Scanner’s SBOM registry; blobs → object store; producers publish, consumers subscribe | unchanged | unchanged | stellaops_sbomservice |
| graph-api | src/Graph/ | StellaOps.Graph.Indexer.Persistence | shared DB (graph) | StellaOps.Graph (owner-approved merge, 023) | src/Graph/ | StellaOps.Graph.Persistence | stellaops_graph |
| reachgraph-web | src/ReachGraph/ | ReachGraph.Persistence | shared DB (reachgraph) | merged into StellaOps.Graph (023; CAS role) | src/Graph/ | merged ↑ | stellaops_graph |
| doctor-web (+ evidence-init) | src/Doctor/ | Doctor persistence (verify) | shared DB (doctor) | retired (owner-approved, 009 DOC-5) — module survives as plugin SDK + CLI; registry lives in Platform | — | — | — (schema dispositioned at retirement) |
| airgap-controller (+ airgap-time) | src/AirGap/ | StellaOps.AirGap.Persistence (one 32 kB state table) | shared DB (airgap) | split decided (owner EVL-3, 025): posture → Platform (seal/status/time-anchor; both deployables retire); Importer/Bundle/Sync + Mirror.Creator → OfflineKit | posture src/Platform/; exchange src/OfflineKit/ | Platform.Persistence / OfflineKit.Persistence | posture → platform DB; exchange → stellaops_offlinekit |
| registry-token | src/Registry/StellaOps.Registry.TokenService | in-service (RegistryTokenPersistenceExtensions.cs:52) | shared DB (registry_token) | role of StellaOps.Integrations (owner-approved, 024) | src/Integrations/ | merged | stellaops_integrations |
| unknowns-web | src/Unknowns/ | StellaOps.Unknowns.Persistence | shared DB (unknowns, not yet live) | unchanged | unchanged | unchanged | stellaops_unknowns |
| remediation | src/Remediation/ | RemediationDataSource assembly | none (dormant: no compose service/route/UI) | archived (owner-approved; AdvisoryAI autofix is in-module) | — | — | — |
| workflow host (verify which service hosts it) | src/Workflow/ | StellaOps.Workflow.DataStore.PostgreSQL | shared DB (workflow) | with its host service (P4) | unchanged | unchanged | host’s DB |
Evaluation families (VexLens fold, Reachability, Offline/exchange): SPRINT_20260722_022.
5.4 No database / infrastructure (unchanged unless noted)
| Container | Src path | DB | Change |
|---|---|---|---|
| router-gateway | src/Router/StellaOps.Gateway.WebService | — (Valkey) | route table updates only (sprints 006 + per-program S5) |
| stellaops (console) + frontdoor + console-builder | src/Web/StellaOps.Web | — | API base-map repoints only (S6 stages) |
stellaops-cli (stella) | src/Cli/ | — (was direct SQL) | X4/X5 die: corpus/mirror via hub APIs |
| agent-core | RO agent host (verify) | — (verify) | unchanged |
| airgap-time | AirGap module | — | unchanged |
| init jobs (scanner-cache-init, doctor-evidence-init, advisory-ai-data-init, release-orchestrator-agent-ca-init, concelier-jobs-init) | with their services | — | follow their owning service’s program (concelier-jobs-init → Vulnerabilities) |
| stellaops-postgres (postgres:18.1) | — | hosts control-plane DBs | stays; gains per-service DBs (platform DB name unchanged) |
| stellaops-postgres-vulndata | — | hosts stellaops_vuln | new (own volume, P8) |
| valkey / rustfs (seaweedfs) / registry (zot) | — | — | unchanged |
Bench/tools schemas (groundtruth, public; analytics is VulnCorrelation) are non-runtime; dispositioned in Wave 3 (must not block any program). golden_sets is not bench — binaryindex-web live-migrates and serves it (round-20 correction); its destination rides the 014 dissolution.
