# SBOM Service Architecture > Scope: canonical SBOM projections, ledger history, lineage, registry-source state, and durable SBOM event backlogs consumed by Console, Policy, Concelier, Graph, and Findings. ## 1) Mission and boundaries - Serve deterministic, tenant-scoped SBOM projections and ledger history. - Accept scanner-produced SBOMs or operator-supplied SPDX/CycloneDX uploads. - Own append-only SBOM versioning, lineage edges, retention, and related audit state. - Do not perform scanning itself and do not author policy verdicts. ## 2) Runtime layout - Host: `src/SbomService/StellaOps.SbomService` - Persistence: `src/SbomService/__Libraries/StellaOps.SbomService.Persistence` - Tests: `src/SbomService/__Tests/StellaOps.SbomService.Persistence.Tests` ### 2.1 Durable state - Canonical PostgreSQL tables now include: - `sbom.projections`, `sbom.catalog`, `sbom.component_neighbors` - `sbom.entrypoints`, `sbom.orchestrator_sources`, `sbom.orchestrator_control` - `sbom.ledger_versions`, `sbom.ledger_audit`, `sbom.analysis_jobs`, `sbom.watermarks` - `sbom.lineage_edges` - `sbom.version_events`, `sbom.asset_events`, `sbom.inventory_events`, `sbom.resolver_candidates` - `sbom.registry_sources`, `sbom.registry_source_runs` - Startup migrations are embedded in the persistence assembly and run automatically on host startup. ### 2.2 Truthful unsupported surface - The live durable runtime no longer fabricates dependency-path data from in-memory seeds. - Until a durable dependency-path backend exists: - `GET /sbom/paths` returns `501 sbom_paths_unsupported` - dependency-path portions of `GET /sbom/context` return `501 sbom_paths_unsupported` - `POST /internal/sbom/inventory/backfill` returns `501 sbom_inventory_backfill_unsupported` - `POST /internal/sbom/resolver-feed/backfill` returns `501 sbom_resolver_feed_backfill_unsupported` ## 3) Primary APIs - `POST /sbom/upload` validates and normalizes SPDX 2.3/3.0 or CycloneDX 1.4-1.7 and appends a new ledger version. - `GET /sbom/versions?artifact=...` returns the durable timeline for an artifact. - `GET /sbom/ledger/history`, `/point`, `/range`, `/diff`, `/lineage` expose ledger and lineage state. - `GET /console/sboms` reads the durable catalog view. - `GET /components/lookup?purl=...` reads the durable component-neighbor view. - `POST /entrypoints` and `GET /entrypoints` manage tenant-scoped entrypoint overrides. - `GET /sboms/{snapshotId}/projection` returns the stored Link-Not-Merge projection. ## 4) Internal APIs - `GET /internal/sbom/events` returns durable `sbom.version.created` backlog state. - `POST /internal/sbom/events/backfill` replays stored projections into the durable event backlog. - `GET /internal/sbom/asset-events` returns durable `sbom.asset.updated` backlog state. - `GET /internal/jobengine/sources` and `POST /internal/jobengine/sources` manage ingest sources. - `GET /internal/jobengine/control` and `POST /internal/jobengine/control` manage pause/throttle/backpressure state. - `GET /internal/jobengine/watermarks` and `POST /internal/jobengine/watermarks` manage durable watermarks. - `GET /internal/sbom/resolver-feed` and `GET /internal/sbom/resolver-feed/export` expose the persisted resolver candidate store. - `GET /internal/sbom/ledger/audit` and `GET /internal/sbom/analysis/jobs` expose durable ledger audit and analysis job history. - `POST /internal/sbom/retention/prune` applies durable retention policy. ## 5) Ingestion and ledger behavior - Uploads are normalized into deterministic component lists before persistence. - Each artifact keeps an append-only chain of `SbomLedgerVersion` records. - Audit entries are written for ledger mutations. - Analysis jobs are persisted immediately when upload-triggered work is queued. - Lineage edges are persisted for parent, base-image, and shared-build relationships. - Retention pruning removes old versions while preserving auditability. ## 6) Events and derived state - Durable event backlogs are stored in: - `sbom.version_events` - `sbom.asset_events` - `sbom.inventory_events` - `sbom.resolver_candidates` - `sbom.version.created` and `sbom.asset.updated` are canonical durable outputs today. - Inventory and resolver feeds remain durable stores, but automatic rebuild of those feeds is blocked on the missing durable dependency-path backend. ## 7) Registry source management - Registry source definitions and run history are durable PostgreSQL state. - `RegistrySource` stores URL, filters, trigger mode, auth references, and tenant ownership. - `RegistrySourceRun` stores discovery/scan counts, trigger metadata, and completion state. ## 8) Determinism and offline posture - Stable ordering, UTC timestamps, and canonical hashing are required for all read models and ledger state. - The service remains offline-friendly: no external calls are required for persistence or replay. - `Testing` is the only supported environment for fixture-backed or in-memory fallback runtime composition when PostgreSQL is intentionally absent. - Development, staging, and production runtimes now fail startup if `SbomService:PostgreSQL` is not configured. ## 9) Configuration - `SbomService:PostgreSQL:ConnectionString` enables the live durable runtime. - `SbomService:PostgreSQL:Schema` optionally overrides the default schema `sbom`. - `SbomService:Ledger:*` controls retention: - `MaxVersionsPerArtifact` - `MaxAgeDays` - `MinVersionsToKeep` - `SbomService:RegistryHttp`, `SbomService:ScannerHttp`, and `SbomService:RegistrySourceQuery` configure registry discovery and scan emission behavior. ## 10) Proof status - Durable host build: `StellaOps.SbomService` builds cleanly with PostgreSQL-backed canonical stores. - Durable persistence proof: `StellaOps.SbomService.Persistence.Tests` covers ledger, event store, registry-source persistence, and repository-backed timeline rebuild across service instances. ## 11) Open gaps - Add a durable dependency-path backend so `/sbom/paths`, dependency-path context assembly, and inventory/resolver feed backfill can leave truthful `501` mode. - Normalize the shared contract surface further if the persistence assembly keeps absorbing host-owned types. ## 12) Related docs - `docs/modules/sbomservice/ledger-lineage.md` - `docs/modules/sbomservice/byos-ingestion.md` - `docs/modules/sbomservice/retention-policy.md` - `docs/modules/sbomservice/api/projection-read.md`