Skip to content

Latest commit

 

History

History
121 lines (98 loc) · 5.49 KB

File metadata and controls

121 lines (98 loc) · 5.49 KB

Ardur Proxy OCI Image Contract

Availability boundary: this page defines the reviewed release contract. It does not claim that an Ardur image is public. Treat STATUS.md as the source of truth and use the pull commands below only after that status is updated with a verified registry digest.

Supported image

The first supported OCI surface is the governance proxy:

ghcr.io/ardurai/ardur-proxy

Release automation creates only immutable version tags, such as v0.2.0 and 0.2.0. It does not create latest, branch, or moving major/minor tags. The digest is the deployment identity and should be recorded in GitOps manifests:

docker pull ghcr.io/ardurai/ardur-proxy@sha256:<published-digest>

The Personal Hub remains source-build-only and is outside this release contract.

Runtime contract

Property Contract
Process user UID/GID 65532:65532
Listener TCP 8443 on 0.0.0.0
Persistent state /home/ardur/.ardur
Health GET /health and Docker HEALTHCHECK
Authentication Required by default; inject VIBAP_API_TOKEN at runtime
TLS Self-signed TLS by default; supply reviewed cert/key arguments for production
Root filesystem Supports --read-only with the state path mounted writable
Linux privileges No capabilities are required; use no-new-privileges

Signing keys, session state, the TLS certificate, and the governance log all live under the state path. The directory must be writable by UID/GID 65532 and should use encrypted storage with access controls appropriate for signing-key material. Do not put API tokens, private keys, or development certificates in the image, build arguments, labels, or Kubernetes manifests.

Plain HTTP is supported only when a trusted local reverse proxy, sidecar, or service mesh terminates TLS before traffic reaches the container. Append the explicit --no-tls argument to the image command and set ARDUR_NO_TLS=1 so the container healthcheck probes HTTP. The environment variable selects only the healthcheck scheme; by itself it cannot disable proxy TLS. Bearer tokens must not cross an unencrypted or untrusted network.

An equivalent hardened Docker invocation is:

docker run --rm \
  --read-only \
  --cap-drop ALL \
  --security-opt no-new-privileges \
  --tmpfs /tmp:rw,noexec,nosuid,nodev,size=16m \
  --mount type=volume,src=ardur-data,dst=/home/ardur/.ardur \
  --env VIBAP_API_TOKEN \
  --publish 127.0.0.1:8443:8443 \
  ghcr.io/ardurai/ardur-proxy@sha256:<published-digest>

Release gates

.github/workflows/oci-proxy.yml performs the following sequence:

  1. Validate that the release tag exactly matches the Python package version and that the release commit is on main.
  2. Build a native image and run it with a read-only root filesystem, all Linux capabilities dropped, and no-new-privileges enabled.
  3. Prove public health, required bearer authentication, mission issuance, session start, one PERMIT, one DENY, signed attestation, session end, and authenticated metrics.
  4. Generate an SPDX JSON SBOM and a complete Trivy vulnerability/secret report.
  5. Stage amd64 and arm64 images by digest with BuildKit max-level provenance and SBOM attestations. Scan each exact digest before adding a registry tag.
  6. Create only the reviewed version tags after both platform scans pass, then verify that the public manifest contains exactly linux/amd64 and linux/arm64.

The publishing jobs use the repository GITHUB_TOKEN, not a registry PAT. packages: write and id-token: write are job-scoped to release staging; pull request and normal push jobs retain read-only repository permissions.

Residual vulnerability policy

Every run stores the full scanner output, including findings with no vendor fix. The blocking gate rejects embedded secrets and every HIGH or CRITICAL finding for which a fixed package is available. Unfixed findings require review at the protected ghcr environment before a release can proceed; they are not hidden in a permanent ignore file.

The 2026-07-09 baseline on the digest-pinned Python 3.13.14 / Debian 13.5 image reported no fixable HIGH or CRITICAL findings. It reported unfixed findings in the following groups: util-linux (CVE-2026-53615), gzip (CVE-2026-41992), libacl (CVE-2026-54369), ncurses (CVE-2025-69720), and perl-base (CVE-2026-42496, CVE-2026-8376, CVE-2026-42497, CVE-2026-48962, CVE-2026-9538). These are a dated baseline, not a standing waiver. Review the retained JSON report and current vendor status at every protected release approval.

The runtime restrictions reduce impact but do not prove those code paths are unreachable. Refresh the base digest promptly when Debian or the Python Official Image publishes fixes, then repeat the complete image smoke and platform scans.

Operations and cost

  • Keep release digests indefinitely unless a documented security revocation requires removal; deployments and attestations refer to them immutably.
  • Bound retention for CI artifacts and untagged failed staging digests. The workflow retains ordinary scan artifacts for 14 days, release scan artifacts for 30 days, and digest handoff artifacts for one day.
  • GHCR storage and egress are external operating costs. Measure pull volume and regional egress before broad distribution.
  • Do not update Helm defaults or public install claims until the versioned digest is pullable without maintainer credentials and its manifest, attestations, health, and authenticated lifecycle have been independently verified.