Skip to content

Policy schema

Source of truth: internal/policy/types.go (the yaml tags). JSON Schemas are published under schemas/ (halos, gateway, profile, ring, experiment, toggle, rollout) for editor autocomplete. All documents use apiVersion: halos.dev/v1. Decoding is strict: unknown fields are errors. Identifiers (names, aliases, upstreams, variants, MCP servers) match ^[a-z0-9][a-z0-9._-]{0,62}$.

Field Type Notes
org string Required. Must equal the org in signed pointers and releases
identity.issuer string OIDC issuer; used by the portal, halo-proxy, halo-kong
identity.clientID string Portal OIDC client
identity.audience string Expected in gateway bearer tokens; defaults to clientID
identity.userClaim / groupsClaim string JWT claims for user id (default email) and groups (default groups). With the email claim the token must carry email_verified=true, otherwise it is rejected unless unverified email is explicitly trusted; prefer a stable IdP subject
identity.adminGroups list May approve requests and manage experiments in the portal
selfService.enabled bool Turns on the portal kiosk
selfService.launchers list devcontainer, codespaces, coder, laptop
selfService.requestable list mcp-server, model, ring-opt-in, harness
selfService.catalog[] {name, url, command[], headers} MCP servers developers may request
selfService.enrollmentTTLSeconds int One-time laptop token lifetime, default 900
Field Type Notes
apiVersion string halos.dev/v1 (halos.dev/v1alpha1 is accepted with a deprecation warning; see Compatibility)
kind string Profile, Ring, Experiment, Gateway, Toggle, Rollout
name string
labels map optional
Field Type Notes
baseURL string What clients are pointed at (the gateway’s public listener)
protocols map harness to string anthropic-messages, bedrock-invoke, openai-responses, gemini
auth.helperCommand string Prints a short-lived token (Claude apiKeyHelper, Codex env_key source)
auth.ttlSeconds int
auth.identityHeader string Header the auth gateway sets with the verified user id. Used only by trusted_header mode and never an x-halo-* name
models map alias to route {upstream, model}; model is provider id or Bedrock inference profile ARN
upstreams map name to {url, kind} kind: orchestrator, anthropic, bedrock, vertex, openai, azure-openai, gemini
Field Type Notes
extends string Parent profile
harnesses.<name>.version string Exact CLI pin; required for rings
harnesses.<name>.overrides map Raw harness-native keys merged last. Only allowlisted keys are accepted (per-harness list in policy model); any other key is an error, and a harness with no allowlist accepts none
models.default / allowed / enforce string / list / bool enforce rejects rather than hides
permissions.mode string default, acceptEdits, plan, auto
permissions.allow / deny / ask list Rules
permissions.disableBypass bool Must be true on every ring’s profile
permissions.sandbox string off, workspace-write, read-only
mcp.managedOnly bool Block servers not listed
mcp.servers[] {name, url, command[], headers} Exactly one of url (https) or command. Header values that look like credentials are rejected; use ${VAR} references
mcp.denied list
hooks.managedOnly bool
hooks.items[] {event, matcher, command} event: PreToolUse, PostToolUse, SessionStart, Stop, UserPromptSubmit
telemetry.enabled / otlpEndpoint / protocol / logPrompts / attributes protocol: grpc or http/protobuf. Must be enabled on every ring’s profile
egress.allowedDomains list Only egress permitted from managed environments
instructions string Managed CLAUDE.md / AGENTS.md / GEMINI.md
env map Extra environment for every harness. Prefixes OTEL_, ANTHROPIC_, CLAUDE_CODE_, DISABLE_, CODEX_, GEMINI_, GOOGLE_GEMINI_ are reserved; literal secrets are rejected
Field Type Notes
order int Earliest first
profile string
release string Immutable release digest; empty means build from profile
membership.users list User ids always in the ring (checked before groups)
membership.groups list IdP groups always in the ring
membership.percent float 0-100, basis-point precision, of remaining users
membership.default bool Catch-all (GA)
membership.optIn bool Developers may request to join from the portal
Field Type Notes
type string ab, canary, shadow
axis string client, traffic
status string draft, running, paused, concluded
rings list Rings users are drawn from
variants[] name, weight (normalized), control, profile (client axis), routes (traffic axis: alias to {upstream, model})
sampleRate float Shadow only, 0-1
metrics.primary {metric, direction} metric must be a known halo.* metric
metrics.guardrails[] {metric, direction, maxRegression} maxRegression is relative (0.05 = 5%)
stopping.method string msprt, fixed
stopping.alpha / minSamples / maxDays / maxSpendUSD
salt string Defaults to name

axis has exactly two values, client and traffic; there is no both.