sbom-nexus/docs/operator-guide.md
tegwick 280da08455
All checks were successful
Build and Publish Container Image / build-and-push (push) Successful in 1m9s
feat: add repository projection synchronization
Assistant: codex
Assistant-Model: gpt-5.6-sol
Assistant-Session: 01a028f0-a42f-7582-89a8-ebaad7343834
2026-08-22 16:52:47 +02:00

95 lines
2.9 KiB
Markdown

# Operator guide
## Run locally
```bash
make install
make run
```
The API defaults to `127.0.0.1:8010` and `./sbom-nexus.db`. SQLite schema is
created automatically for local development.
For PostgreSQL, migrate before starting the API:
```bash
export SBOM_NEXUS_DATABASE_URL='postgresql+psycopg://user:password@host/sbom_nexus'
make migrate
make run
```
Production deployments should mount a Secret and set
`SBOM_NEXUS_DATABASE_URL_FILE` to its `url` file rather than exposing the DSN
in a manifest or command argument. The same file setting is consumed by both
Alembic and the API process.
PostgreSQL never auto-creates tables unless `SBOM_NEXUS_AUTO_CREATE=1` is set
explicitly. Normal production operation must use Alembic.
## Register and ingest a repository
```bash
curl -X PUT http://127.0.0.1:8010/repositories/example \
-H 'Content-Type: application/json' \
-d '{"checkout_path":"/srv/repos/example","active":true}'
curl -X POST http://127.0.0.1:8010/sbom/example/ingest
```
The ingest response is terminal: `ingested`, or `skipped` with one of
`no-checkout`, `no-manifest`, or `ingest-error`. A skip advances queue fairness
but does not advance `last_success_at`.
## Inspect catch-up
```bash
curl -s 'http://127.0.0.1:8010/sbom/catch-up?limit=3' | python3 -m json.tool
```
The default stale threshold is 30 days. Override it globally with
`SBOM_NEXUS_STALE_DAYS` or per query with `stale_days` during controlled
operation.
## Import State Hub history
Synchronize the minimum repository identity/path projection first. This command
does not call an ingest endpoint or create an SBOM snapshot:
```bash
uv run python scripts/sync_repository_projections.py \
--source-url http://127.0.0.1:8000 \
--target-url http://127.0.0.1:8010 \
--host-id bnt-lap001 \
--dry-run
```
Remove `--dry-run` only after the target is deployed. The apply path upserts all
active and inactive records, then reads them back and fails on a missing or
mismatched active/path projection. Extra target rows are reported but retained.
Run a read-only preview first:
```bash
uv run python scripts/import_state_hub.py --dry-run
```
Then run against a backed-up Nexus database:
```bash
uv run python scripts/import_state_hub.py \
--source-url http://127.0.0.1:8000 \
--target-url http://127.0.0.1:8010
```
Imports are idempotent on the State Hub snapshot UUID. Before cutover, compare
the source/target repository, snapshot, and entry counts described in the
extraction review. The command fails unless every legacy snapshot id, repository,
timestamp, entry count, licence group, and direct-production copyleft count
reconciles.
## Current production limitations
- Authentication and authorization are not yet integrated.
- Structured operational metrics, backup/restore proof, and retention policy are
required before authority cutover.
- State Hub and Repo Manager callers have not yet been retargeted.