Core concepts
This page walks the data model and the lifecycle of a single artifact end-to-end. It's the document you read once and then re-skim when you're trying to remember what a "repo" is in OrbitalReg's vocabulary.
Project
A project is the top-level governance boundary. A typical deployment has 5–500 projects: one per team, one per product, one per "line of business" — pick the granularity that matches how your existing IAM groups are scoped.
Projects own:
- A set of repositories
- A retention policy default (overridable per repository)
- A license policy
- A quarantine policy
- A list of project-owners (full admin within the project)
- A list of project-editors (push but not policy-edit)
A project's slug is unique platform-wide. Renames are in-place — the UUID stays stable so any downstream referencing FK doesn't break.
Repository
A repository is a typed package store inside a project. Each repository has a single format (Maven, npm, PyPI, Docker, …) and is either local (uploads only), remote (proxy + caching mirror for an upstream), or virtual (federated view of multiple underlying repos).
The slug is (project, repo)-unique, not platform-unique, so acme-platform/maven and acme-finance/maven are both valid.
Artifact
An artifact is a single uploaded version. Identity is the tuple (repo_id, path, version):
pathis format-specific — for Maven,com/example/my-lib; for npm,@scope/pkg; for Docker,library/alpine.versionis the format's version string. SemVer for npm, Maven coordinates for Maven, OCI tag/digest for Docker, etc.
The artifact row carries the SHA-256 digest of the bytes, the content-type, and a JSONB metadata blob with format-specific fields.
Scanning and Detection
Every upload triggers a scan job. The scan-job worker pool runs the configured scanners against the artifact and writes findings to scan_findings. A finding is a tuple of:
(artifact_id, scanner, vuln_id, severity, license_id, …)vuln_idis the canonical CVE / GHSA / OSV id when availableseverityis normalised to CVSS-style buckets (CRITICAL,HIGH,MEDIUM,LOW,UNKNOWN)
A single artifact typically produces 10–100 findings — most are informational. The interesting ones are the ones above the project's quarantine threshold; those flip the artifact's quarantined bit.
A quarantined artifact:
- Still appears in listings (operators need to see it to triage)
- Returns HTTP 451 on download with a "why-blocked" envelope
- Cannot be promoted across repository boundaries
Security blocks
Detection is reactive — the scanner found something. Security blocks are proactive — an admin authored a rule that says "do not serve artifacts matching this pattern, with this customer-facing message":
block_type: sha256
pattern: "9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08"
reason: "Confirmed-malicious sample from FAS-2025-0042"
customer_message: |
This artifact was blocked because it matches a known supply-chain
attack indicator. Contact security@example.com if you believe this
is in error.Block types: sha256, path-glob, cve, repo. Blocks fire on every download path — Maven, npm, PyPI, Docker, the lot.
The public /blocked/<id> page (no auth) renders the customer message so a developer who ran npm install and got a 451 has somewhere to go.
Retention
A retention policy is a per-repository rule that prunes old versions on a schedule:
keep-N-newest— keep the latest N versions of eachpathkeep-by-age— keep versions newer than N days- Combinations are allowed; the union of all matching rules survives
Pruned artifacts soft-delete first (visible in Trash for 30 days), then hard-delete the row + S3 object.
Retention runs hourly. The retention_audit table records every deletion with the rule that triggered it, the artifact metadata, and the operator (or service account) who installed the rule.
Promotion
Promotion moves an artifact between repositories under a gate. The gate has three sub-checks:
- CVE policy — no findings above the project's threshold
- License policy — every detected license appears in the project's allow-list
- Scan rule policy — no scanner-specific custom rules failing
A promotion request that passes the gate runs as a copy + a write to promotion_audit; one that fails returns the failing checks so CI can decide whether to block the build or surface a warning.
Sigstore trust policies
When you wire OrbitalReg into a CI flow that signs artifacts via cosign keyless, the verifier needs to know which (identity_pattern, issuer_pattern, fulcio_root, rekor_url) tuples it trusts. Those live in sigstore_trust_policies and are managed under Admin → Sigstore → Trust policies.
Service accounts + tokens
Service accounts are non-human principals scoped to a project. Each can have one or more tokens (the actual orbsa_… bearer strings used in Authorization: Bearer … headers).
For CI, prefer the OIDC token exchange flow — it eliminates long-lived bearer tokens entirely. See OIDC token exchange.
Webhook subscriptions
Outbound events: artifact uploaded, artifact promoted, finding above threshold, retention deletion, etc. Each subscription has:
- A target URL (HTTPS only, validated at CRUD time)
- A shared HMAC secret (write-only — list responses return
has_secret: bool) - An event filter (subset of the published catalog)
- A delivery target type — generic webhook, Slack, Microsoft Teams
The full event catalog lives at Webhook events.