← Docs
Helix CLI docs
Browse Helix CLI docs

Teams v0 (artifact store + run registry + RBAC)

Teams v0 turns Helix’s trust engine into a workspace: every run produces immutable, signed receipts that are searchable and shareable.

What exists today (minimal scaffold)

  • Content-addressed artifact store: blobs are stored by SHA-256; server enforces hash on upload when provided and never overwrites an existing digest.
  • Run registry (SQLite): runs point to verdict + summary digests (and optional artifact digests).
  • RBAC (bearer tokens): roles are viewer, runner, approver, admin.
  • Audit log: mutating actions write an append-only audit row (DB table).
  • Shareable proof link: each run has a read-only proof URL (/r/<run_id>?token=...) that renders verdict status + digests + summary.

This is intentionally small: it’s the spine you can harden into a real Teams product (workspaces/projects/RBAC UI, job queue, retention enforcement, SSO).

Data plane migrations stance (v0)

Teams v0 uses a single SQLite DB file. On startup, it runs idempotent, additive schema upgrades (tables are CREATE TABLE IF NOT EXISTS; new columns are added via ALTER TABLE ... ADD COLUMN).

Practical implications:

  • Upgrades are supported for additive changes (new nullable columns, new tables, new indexes, backfills).
  • Downgrades are not guaranteed (older binaries may not understand newer columns/rows).
  • For anything non-additive, treat the DB as requiring an explicit migration plan (or a wipe/reseed) and rely on backups for recovery.

Quickstart (local dev)

Initialize a Teams DB and create an admin token + a default workspace/project:

helix teams init --db out/teams/teams.db --workspace default --project default

Start the server:

helix teams serve --db out/teams/teams.db --blobs out/teams/blobs --host 127.0.0.1 --port 8787

User config (profiles, non-secrets)

Helix can read non-secret defaults from a user config file:

  • Path: ~/.config/helix/config.toml (or override with HELIX_CONFIG)
  • Profile: HELIX_PROFILE=<name> selects [profile.<name>]

Create/edit it with:

helix configure
helix config list
helix config set registry_url http://127.0.0.1:8787
helix config set default_workspace_id <WORKSPACE_ID>

Do not store secrets in this file:

  • Registry tokens (HELIX_REGISTRY_TOKEN), AWS credentials, signing keys

Those stay in env vars / AWS credential chain / OIDC/IRSA.

Auth (API tokens + optional OIDC JWT)

Teams accepts Authorization: Bearer <token> where <token> is either:

  • a Teams API token issued into the DB (helix teams token), or
  • an OIDC JWT (RS256) verified against a JWKS file (optional; RC2 path).

Resolution order:

  1. If the bearer token matches an issued API token hash in the DB, Teams uses it.
  2. Otherwise, if OIDC is configured, Teams treats the bearer as a JWT and verifies it.

Configure OIDC JWT verification (RS256):

export HELIX_TEAMS_OIDC_ISSUER="https://issuer.example"
export HELIX_TEAMS_OIDC_AUDIENCE="helix"                  # comma-separated allowed audiences

# Choose exactly one JWKS source:
export HELIX_TEAMS_OIDC_JWKS_PATH="/path/to/jwks.json"      # local JWKS JSON file (static)
# export HELIX_TEAMS_OIDC_JWKS_URL="https://issuer.example/jwks"            # fetch JWKS over HTTPS
# export HELIX_TEAMS_OIDC_DISCOVERY_URL="https://issuer.example/.well-known/openid-configuration"  # discovery -> jwks_uri

# Optional JWKS fetch tuning (URL/discovery modes):
export HELIX_TEAMS_OIDC_JWKS_REFRESH_INTERVAL_S="300"       # cache TTL; kid-miss forces refresh
export HELIX_TEAMS_OIDC_JWKS_TIMEOUT_S="5.0"                # HTTP timeout (seconds)

Optional claim mapping knobs:

export HELIX_TEAMS_OIDC_USER_CLAIM="sub"                  # default: sub
export HELIX_TEAMS_OIDC_ROLE_CLAIM="helix_role"           # default: helix_role
export HELIX_TEAMS_OIDC_WORKSPACE_CLAIM="helix_workspace_id"  # default: helix_workspace_id
export HELIX_TEAMS_OIDC_LEEWAY_S="30"                     # default: 30

JWT checks (enforced):

  • alg must be RS256
  • signature verified against the JWKS key (kid when present)
  • iss must equal HELIX_TEAMS_OIDC_ISSUER
  • aud must include one of HELIX_TEAMS_OIDC_AUDIENCE
  • exp required; nbf optional; both enforced with HELIX_TEAMS_OIDC_LEEWAY_S seconds of leeway

Role mapping:

  • Claim value may be a string or list.
  • Allowed roles: viewer < runner < approver < admin.
  • If claim missing, role defaults to viewer.

Workspace scoping:

  • If the workspace claim is present (non-empty), access is restricted to that workspace.

Smoke it with:

bash scripts/auth_matrix_smoke.sh

Blob storage backend (FS or S3)

By default, Teams stores blobs on the local filesystem under --blobs (HELIX_BLOB_BACKEND=fs).

To use S3-compatible object storage (MinIO/AWS S3), set:

export HELIX_BLOB_BACKEND=s3
export HELIX_S3_BUCKET=helix-blobs
export HELIX_S3_PREFIX=helix   # optional
export HELIX_S3_ENDPOINT_URL=http://127.0.0.1:9000  # optional (MinIO)
export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_DEFAULT_REGION=us-east-1

Notes:

  • Blob keys are content-addressed: <prefix>/blobs/sha256/<hex>.
  • Reads stream (no in-memory buffering for blob downloads).
  • If HELIX_BLOB_BACKEND=s3 and boto3 is missing, Helix fails closed with a clear error (install with pip install -e ".[s3]").
  • S3/MinIO tuning knobs:
    • HELIX_S3_CONNECT_TIMEOUT (default: 5), HELIX_S3_READ_TIMEOUT (default: 60)
    • HELIX_S3_RETRY_MAX_ATTEMPTS (default: 10), HELIX_S3_RETRY_MODE (default: standard)
    • HELIX_S3_ADDRESSING_STYLE=auto|path|virtual (auto forces path when HELIX_S3_ENDPOINT_URL is set)
    • HELIX_S3_STRICT_NO_OVERWRITE=1 enables conditional puts (never overwrite existing keys).

Issue a runner token (offline helper; for real deployments this would be a managed admin workflow):

helix teams token --db out/teams/teams.db --user runner1 --role runner

Token expiry and revocation (enterprise hygiene):

  • Offline token issuance supports --ttl-hours or --expires-utc.
  • API token issuance supports ttlHours and returns expiresAtUtc.
  • Admins can revoke a token by sha256 via POST /api/v0/tokens/revoke with JSON { "tokenSha256": "..." }.

Metrics (Prometheus)

Teams exposes a minimal Prometheus scrape endpoint:

  • GET /metrics (unauthenticated by default; restrict via network policy / ingress)

It includes request counters plus seat/DB gauges.

Optional hardening:

  • Set HELIX_TEAMS_METRICS_MIN_ROLE=viewer|runner|approver|admin to require a bearer token for /metrics.

Run a validation pack as a “remote lane” and upload the receipts:

helix teams push-pack \
  --server http://127.0.0.1:8787 \
  --token <RUNNER_TOKEN> \
  --workspace-id <WORKSPACE_ID> \
  --project-id <PROJECT_ID> \
  --pack signed_plugin_trust_chain_v1 \
  --deterministic

The command prints a proofUrl you can open in a browser and share.

Audit export (signed, deterministic)

Export an append-only, workspace-scoped audit log bundle from the Teams DB:

helix teams audit-export \
  --db out/teams/teams.db \
  --workspace-id <WORKSPACE_ID> \
  --signing-key <ed25519_private_key_path> \
  --key-id <key_id> \
  --outdir out/teams/audit_export

Outputs:

  • audit_export_v1.json: signed manifest (includes time range + digests + signature)
  • audit_events.jsonl: canonical JSONL event stream (stable bytes for same inputs)

Determinism contract smoke:

bash scripts/audit_export_smoke.sh

Acceptance gate (Teams contract)

Teams becomes sellable when a deployment can:

  1. run the public validation packs via the remote lane
  2. store receipts/artifacts in the artifact store
  3. register runs in the registry
  4. verify receipts against the published reference validation bundle

Treat the published reference bundle as non-negotiable platform contract tests for every Teams deployment.

Receipt fetch (Phase 3.20)

Given an approval receipt id (effective transition_request_v1 event id), materialize the exact bundle snapshot and verify it:

helix fetch \
  --receipt sha256:... \
  --out out/fetched_bundle

Defaults:

  • --server defaults to HELIX_REGISTRY_URL or profile.registry_url
  • --token defaults to HELIX_REGISTRY_TOKEN

The command fails closed if:

  • the receipt id is unknown
  • the referenced bundle blob is missing
  • the reconstructed bundle fails helix verify (integrity/signatures)
  • the bundle’s effective approval receipt does not match the requested id

Registry v1 (Phase 4 V1)

Registry turns governed bundles into reusable, organization-visible ProgramVersions with semver and explicit dependency edges.

Publish

helix registry publish \
  --bundle out/bundle_dir \
  --program TP53_cut \
  --version 1.2.0 \
  --tag crispr --tag demo

Defaults:

  • --server defaults to HELIX_REGISTRY_URL or profile.registry_url
  • --token defaults to HELIX_REGISTRY_TOKEN
  • --workspace-id defaults to profile.default_workspace_id
helix registry search \
  --gene TP53 \
  --nuclease SpCas9-NGG \
  --off-target-severity-max medium

Dependency graph + impact

helix registry depend --server ... --token ... --program <DEP_ID> --version 1.0.0 --on <BASE_ID>@1.0.0 --reason "reuse"
helix registry deprecate --server ... --token ... --program <BASE_ID> --version 1.0.0 --reason @reason.txt
helix registry acknowledge --server ... --token ... --program <DEP_ID> --version 1.0.0 --on <BASE_ID>@1.0.0 --rationale "accepted risk"

Enforce-mode export blocking (needs_review)

When HELIX_GOVERNANCE_MODE=enforce and HELIX_REGISTRY_URL is set, official exports require governance/registry_ref.json and are gated by registry status.

Set:

  • HELIX_GOVERNANCE_MODE=enforce
  • HELIX_REGISTRY_URL=http://127.0.0.1:8787
  • HELIX_REGISTRY_TOKEN=<TOKEN>

Then exports fail-closed when:

  • the bundle is missing governance/registry_ref.json (not registered),
  • the registry is unreachable, or
  • the registry reports the ProgramVersion is deprecated or needsReview (unacknowledged deprecated upstream dependencies).

Local dev escape hatch:

  • HELIX_REGISTRY_ALLOW_UNREGISTERED_EXPORT=1 allows official exports even if the bundle is not registered or the registry is unreachable.

Visibility + membership (registry ACL)

Programs are workspace-scoped and have visibility:

  • workspace: readable by anyone with workspace access
  • private: readable only by the owner, explicit members, or admin tokens (otherwise behaves like not found)

Write/admin actions are permissioned per program (in addition to token role checks):

  • Publish version: requires program write/admin (or owner/admin token)
  • Deprecate version: requires program admin (or owner/admin token)
  • Acknowledge dependency impact: requires program write/admin on the dependent program

Dependency/graph endpoints redact private upstream programs the caller cannot read.

GitHub PR verify/diff workflow (Phase 3.22)

Helix ships a PR workflow that:

  • detects bundle/governance changes
  • runs strict artifact bundle verification
  • computes governance state (best-effort)
  • optionally queries registry status (if configured)
  • posts a sticky PR comment and uploads a small evidence artifact

Workflow: .github/workflows/helix-verify-diff.yml

Optional secrets (for registry status checks in PR comments):

  • HELIX_REGISTRY_URL
  • HELIX_REGISTRY_TOKEN