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 withHELIX_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:
- If the bearer token matches an issued API token hash in the DB, Teams uses it.
- 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):
algmust beRS256- signature verified against the JWKS key (
kidwhen present) issmust equalHELIX_TEAMS_OIDC_ISSUERaudmust include one ofHELIX_TEAMS_OIDC_AUDIENCEexprequired;nbfoptional; both enforced withHELIX_TEAMS_OIDC_LEEWAY_Sseconds 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=s3andboto3is missing, Helix fails closed with a clear error (install withpip 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 forcespathwhenHELIX_S3_ENDPOINT_URLis set)HELIX_S3_STRICT_NO_OVERWRITE=1enables 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-hoursor--expires-utc. - API token issuance supports
ttlHoursand returnsexpiresAtUtc. - Admins can revoke a token by sha256 via
POST /api/v0/tokens/revokewith 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|adminto 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:
- run the public validation packs via the remote lane
- store receipts/artifacts in the artifact store
- register runs in the registry
- 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:
--serverdefaults toHELIX_REGISTRY_URLorprofile.registry_url--tokendefaults toHELIX_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:
--serverdefaults toHELIX_REGISTRY_URLorprofile.registry_url--tokendefaults toHELIX_REGISTRY_TOKEN--workspace-iddefaults toprofile.default_workspace_id
Search
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=enforceHELIX_REGISTRY_URL=http://127.0.0.1:8787HELIX_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
deprecatedorneedsReview(unacknowledged deprecated upstream dependencies).
Local dev escape hatch:
HELIX_REGISTRY_ALLOW_UNREGISTERED_EXPORT=1allows 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 accessprivate: readable only by the owner, explicit members, oradmintokens (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/adminon 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_URLHELIX_REGISTRY_TOKEN