# SBOM Nexus client contract v1 Repo Manager consumes SBOM Nexus; it does not implement a second scanner, snapshot store, freshness model, licence classifier, or catch-up scheduler. This contract pins the boundary used by `RMGR-WP-0011`. ## Authority modes | Mode | Surface | Authoritative | Persisted | Advances Nexus state | | --- | --- | --- | --- | --- | | Local preview | `rmgr sbom scan|licence-report` → `sbom-nexus scan` | no | no | no | | Service operation | configured SBOM Nexus HTTP client | yes | Nexus decides | yes, according to the route outcome | Every compatibility-command result carries: ```json { "repo_manager_context": { "mode": "local-preview", "authoritative": false, "persisted": false, "advances_last_attempt_at": false, "advances_last_success_at": false, "creates_snapshot_history": false } } ``` Writing preview JSON to a file creates optional local evidence only. It does not turn the result into an authoritative snapshot or ingest receipt. ## Pinned snapshot envelope Repo Manager accepts `schema: sbom-nexus.snapshot.v1`. Additive fields are compatible. An unknown schema or omission of any of these fields is a contract error: `schema`, `ok`, `repo_slug`, `source_revision`, `generated_at`, `entry_count`, `entries`, `sources`, `licence_report`, and `errors`. Repo Manager may project the existing licence-report compatibility shape from that envelope. It must not recalculate licence groups or copyleft signals. ## Authoritative service routes The production client may consume these Nexus-owned routes without depending on Nexus tables or migrations: | Purpose | Route | | --- | --- | | Upsert repository projection | `PUT /repositories/{repo_slug}` | | Read repository projections | `GET /repositories/` | | Persist scan outcome | `POST /sbom/{repo_slug}/ingest` | | Persist terminal skip outcome | `POST /sbom/{repo_slug}/skip` | | Read latest repository SBOM | `GET /sbom/{repo_slug}` | | Read immutable snapshot detail | `GET /sbom/snapshots/{snapshot_id}` | | Read licence report | `GET /sbom/report/licences/` | Calls use a bounded timeout and surface deterministic transport, HTTP, and contract errors. Credentials enter only through the platform runtime path and must never appear in files, command output, or logs. ## Authoritative client usage The Python client requires `SBOM_NEXUS_URL`. `SBOM_NEXUS_TIMEOUT_SECONDS` defaults to 30 seconds and is bounded to 0.1–300 seconds. An optional `SBOM_NEXUS_TOKEN` may be injected at runtime; its value is excluded from configuration representations and all structured errors. ```python from repo_manager.sbom_client import SBOMNexusClient, SBOMNexusConfig client = SBOMNexusClient(SBOMNexusConfig.from_environment()) client.upsert_repository( "example", nexus_checkout_path="/srv/controlled/example/abc123", active=True, ) receipt = client.ingest_repository( "example", expected_source_revision="abc123", operation_id="stable-operation-id", ) latest = client.latest_snapshot("example") report = client.licence_report() ``` The client URL-escapes repository slugs, accepts only object responses with the pinned route-specific fields, and adds an `authoritative-service` context. It does not retry mutations automatically: a timeout or server failure can occur after Nexus commits. Structured errors therefore expose `mutation_may_have_committed`; callers must resolve the stable operation id or read the resulting snapshot before deciding whether to retry. When an expected source revision is supplied, an `ingested` receipt for any other revision fails closed as `source_revision_mismatch` and explicitly notes that the mutation may already have committed. The checkout path sent to Nexus is Nexus-local controlled-source identity, never authorization to mount a workstation path into the cluster. ## Forgejo archive source-reference projection The `CUST-WP-0064` v1 source mechanism is available through a read-only resolution command: ```bash rmgr sbom source-ref --path /path/to/checkout --slug example ``` Repo Manager reads the selected Git remote only to normalize identity. It then uses the anonymous Forgejo API—not local `HEAD`, the working tree, or a cached remote-tracking ref—to read repository visibility, default branch, and its full 40-character commit SHA. The result contains `kind: forgejo-archive-v1`, exact `coulomb/` identity, `revision`, `observed_ref`, and a canonical UTC `observed_at`. V1 returns `supported: false` and no `source_ref` for a missing remote, non-Coulomb identity, slug mismatch, private repository, unavailable Forgejo record, invalid branch response, or unresolved full SHA. It never falls back to a workstation path or local revision. Projection is an explicit mutation and requires both service configuration and confirmation: ```bash export SBOM_NEXUS_URL=https://sbom-nexus.example rmgr sbom source-ref --path /path/to/checkout --slug example \ --project --confirm-authoritative ``` The projection sends `checkout_path: null` plus the structured source reference. It succeeds only when Nexus returns the exact same `source_ref`; an older server that silently ignores the additive field fails closed. This makes the command a direct readiness probe for the SBOM Nexus side of `CUST-WP-0064`. ## Repository source identity and provenance Repo Manager remains authoritative for repository slug, active state, checkout/source identity, and Git revision. An authoritative scan request must refer to a controlled source artifact or checkout pinned to that revision. It must not infer identity from a path string or repository name, and it must not mount a workstation filesystem into the cluster. `CUST-WP-0064` owns the coordinated source-input topology. Until that topology is live, local checkout scans remain previews even when their Git revision is known. SBOM Nexus alone records the resulting authoritative snapshot and attempt/success history.