Operations - rsys-bshankar/ai-ran-smo GitHub Wiki
- Take a backup first:
scripts/db_backup.sh(one checkedpg_dumpfile, mode 0600) andscripts/db_restore.sh. - Docker Compose:
docker compose up -d --buildruns the migrations (docker compose logs migrate). Outside compose runpython scripts/migrate.py. On Kubernetes see Helm on Kubernetes: the migration runs as a Job before any pod of the new version. -
From 0.2.0 to 0.3.0: the schema moves to revision 0021, all additive (KPI schedules, KPI guard, the audit chain), and the 0.2.0 code runs on it. Three things to know:
-
R1 Termination now needs the database, for the audit chain and the kill switch. Compose does this already; a deployment of your own must give it the same
SMO_DATABASE_URLand password as a module. -
An rApp may now change only what it uses. A third-party rApp that calls a route outside the allow-list gets
403 ROLE_NOT_PERMITTED. SetSMO_ROLE_ENFORCEMENT=auditon SME and R1 Termination to log instead while you move it. -
A new service,
ran-nf-oam-worker, does the periodic work (staged job advance, KPI schedules and guards). Those run only while it does.
-
R1 Termination now needs the database, for the audit chain and the kill switch. Compose does this already; a deployment of your own must give it the same
-
From 0.1.0 to 0.2.0: run
scripts/init_secrets.shonce on the host first (it createssecrets/enrollment_secretand leavesdb_passwordalone). During a mixed-version rolling upgrade setSMO_ROLE_ENFORCEMENT=auditon SME and R1 Termination. - CI upgrades a real previous-release database with data on every change to the migrations, so an upgrade that works only on an empty schema fails there.
Every authenticated change through the gateway is recorded in a hash chain. Check it and export it from any module's image:
docker compose exec r1-termination python -m smo_shared.audit verify
docker compose exec r1-termination python -m smo_shared.audit export --format jsonl > audit.jsonl
verify exits 1 and names the first broken row if a row was edited, removed or inserted. export ends with a head line: keep it somewhere the database's writers cannot reach, because someone who can write the database and recompute every hash is not caught by the chain alone. R1_AUDIT=off turns recording off.
Inventory, *_FILE convention and a rotation runbook for each secret: smo/docs/SECRETS.md.
Structured logs and Prometheus-style metrics per module, readiness vs liveness endpoints, and a slow-query log: Postgres logs statements slower than POSTGRES_SLOW_QUERY_MS (default 500, -1 off): docker compose logs postgres | grep duration. The gateway counts refusals (smo_role_refusals_total) and audit writes (smo_audit_writes_total).
Tag smo-vX.Y.Z on a merged release PR (smo/docs/RELEASES.md). The tag starts release-images.yml: it builds every image, pushes ghcr.io/rsys-bshankar/ai-ran-ref/smo-<module>:<version>, signs each by digest with cosign (keyless), attaches provenance and an SBOM, and writes the release notes.
Verify an image before running it:
cosign verify ghcr.io/rsys-bshankar/ai-ran-ref/smo-ran-nf-oam:0.3.0 \
--certificate-identity-regexp '^https://github.com/rsys-bshankar/ai-ran-ref/\.github/workflows/release-images\.yml@refs/' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com
docker buildx imagetools inspect ghcr.io/rsys-bshankar/ai-ran-ref/smo-ran-nf-oam:0.3.0 --format '{{ json .Provenance }}'
Before opening a PR run the verification battery in smo/CLAUDE.md (lint, every module's unit suite, the integration suite, the migration check against a real Postgres, GUI typecheck/tests/build). CI runs the same on every PR, plus a Helm install and upgrade on kind.