Skip to content

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 04 Oct 00:46
· 77 commits to main since this release
e7a8505

The first general-availability release. Everything in this section and in the two release candidates ships here. Verified in CI on every change, and run end to end before this tag: Linux, macOS and Windows builds; the installers, halod as a launchd daemon and as a Windows SYSTEM scheduled task; the GitHub Action, the GitLab template and the dev container Feature; Helm on a kind cluster with pod-kill, rolling-upgrade and eviction fault injection under load; halo-kong in open-source Kong 3.9.3; the real pinned Claude Code, Codex, Gemini CLI and Copilot CLI driven headlessly through halo-proxy; halo-proxy against the real Anthropic and OpenAI APIs nightly; a headless browser click-through of every console page.

GA scope. Linux and macOS hosts, dev containers, the four CLIs' managed configuration, halo-proxy with Anthropic and OpenAI upstreams, and halo-kong on open-source Kong are GA. Windows hosts, MDM-delivered laptops (Jamf, Kandji, Intune), Codespaces and Coder, the Codex and Copilot CLI onboarding entry points, and the Bedrock, Vertex and Azure OpenAI upstreams are supported but not yet field-verified: each is built, unit- and fixture-tested, and exercised in CI as far as a hosted runner can, but has not run against a real tenant, device fleet or cloud account. See Known gaps.

Added

  • Device posture gate (Ring.posture: off|warn|enforce, default warn): halo-proxy and halo-kong ask halo-server (GET /api/v1/gateway/posture, gateway token, rate-limited) whether the calling device's halod reported it stale, drifted or off its ring's release, and refuse model calls in enforce. Verdicts are cached (1 m) and the last verdict serves for a 15 m grace window when halo-server is unreachable, after which requests pass and are counted outcome="unknown". halo_proxy_gate_total metrics. ADR-0011.
  • CLI version gate (Ring.versionGate: off|warn|enforce, default warn): the gateway reads the CLI version from the User-Agent and compares it with the ring's pinned versions (ring profile and the variant profiles of running client-axis experiments). This covers Codex, Gemini CLI and Copilot CLI, which do not enforce a pin themselves. User-Agent formats come from recorded headers and vendor source, cited in ADR-0011.
  • Immutable managed files: halod.yaml immutable: true sets chflags schg (macOS) / chattr +i (Linux) after each atomic write and clears it before a rewrite; a missing tool or permission is logged once and skipped.
  • Policy API v1: apiVersion: halos.dev/v1 is the stable document version; every kind and field is frozen as it was in v1alpha1. halo migrate --policy-dir DIR [--dry-run] rewrites v1alpha1 documents in place, keeping comments and formatting (idempotent). halo init and the intent commands write v1; schemas/*.schema.json describe v1 and schemas/v1alpha1/ keeps the old ones. Compatibility states the v1 guarantees, the deprecation policy and the supported version skew across halo, halod, halo-server and halo-proxy. ADR-0012.
  • Agentic onboarding from whichever AI CLI you have. halo quickstart brings up the demo and prints a tour. halo doctor reports installed CLIs and versions, tools, which credential variables are set (never their values), policy validity and gateway reachability, with a fix per problem. halo onboard local|install|proxy|verify takes a machine from nothing to a validated halos.yaml, a dry-run (then --apply) install of the managed config, an optional loopback halo-proxy, and a real claude -p / codex exec / gemini -p / copilot -p round trip. halo onboard company interviews an admin (IdP, gateway, provider, delivery) and generates the policy repo, Helm values, OIDC client, enrollment config, CI workflow and smoke eval, then stops before anything outward. All --output json, idempotent, dry-run by default. MCP tools of the same names plus an onboard prompt; entry points for Claude Code (/halos:halo-onboard), Codex ($halos-onboard), Gemini CLI (extension) and Copilot CLI (.github/mcp.json). New Start here page.
  • Helm HA: halo-proxy runs with probes, a PodDisruptionBudget, topology spread, an optional HPA, a hardened securityContext and an optional NetworkPolicy; values.schema.json pins halo-server and halo-shadow to one replica because each is a single writer over local JSONL files (documented in the chart). make uat-k8s now kills a proxy pod mid-traffic, performs a rolling upgrade and tests the PDB under 200 rps with zero client-visible errors required.
  • Operations docs: Operations (HA model, SLOs, Prometheus alert rules on the real metric names, backup and restore of every --data-dir file and key, runbook for killing a change, rolling back a ring, rotating release and kill-switch keys, a lost signer state file, gateway or server down) and Support policy (SemVer scope per surface, supported versions, upgrade order halo-server → halo-shadow → halo-proxy/kong → halod → halo, EOL).
  • Nightly soak (soak.yml): 60 minutes of test/load against a real halo-proxy, failing on errors, cut SSE streams, goroutine or heap growth, and p99 regression against a committed baseline (records only until test/load/baseline.json is committed).
  • Fuzzing: 16 native Go fuzz targets over every parser of untrusted input (policy YAML, JWTs, ring pointers, bundle tar and manifest, kill lists, SSE, identity headers, webhook signatures, server JSON, audit chain, shadow replay, halod paths and halod.yaml), run briefly on every PR and for 10 minutes per target nightly. An OpenSSF Scorecard workflow and a SECURITY.md with the disclosure process and supported versions.
  • Security model, bound to tests: every claim in the security model names the test that proves it, and TestSecurityModelClaimsBound fails if a named test disappears.
  • CI verifies every delivery path on every PR: install.ps1, enroll.ps1 and halod service install on Windows; install.sh, enroll.sh and launchd on macOS; the composite Action on three OSes; the GitLab template under gitlab-ci-local; the dev container and the Feature under the devcontainer CLI; Playwright clicks through every console page and button (make demo-e2e).
  • One-command releases: scripts/release.sh [--dry-run] [--yes] <tag> runs the preflight (main, clean, HEAD == origin/main, SemVer, CHANGELOG section, green CI, go test, goreleaser check) and pushes the tag; release.yml gates, builds, attests provenance and then verifies the published artifacts (cosign bundle, checksums, attestation, image signatures, install.sh, tap and bucket); release-drift.yml fails daily if the tap or bucket drift from the latest release. RELEASING.md.
  • Demo kiosk: make demo serves a pinned halod with its checksum and configures every launcher, so "Set up my laptop" and the dev container launcher work end to end locally. Unconfigured launchers never show a raw server error: GET /api/v1/capabilities reports each launcher's availability, the kiosk shows only usable ones, and admins see what to set. Harness cards list only the model aliases that harness can use (the same wire check as halo validate).
  • halo eval online reports per-arm error rate, mean latency and output tokens over every shadow pair, errored ones included, and exports halo.eval.shadow.* (ADR-0004: regressions in refusal rate, latency and cost are now caught, not only judge scores).
  • Guardrails guardSandboxEgress (a ring profile with permissions.sandboxRequired must set a non-empty egress.allowedDomains) and guardGARing (a default ring that ships hooks must make them managed-only); guardNoBypass now also scans profile env and harness overrides. ExtraGuardrails lets an org add checks that can only add issues. halo release publish refuses a ring pinned to a different release: digest. Every ADR 0001–0010 carries an Implementation status table mapping each commitment to code and a test, with dated addenda where a decision was superseded.
  • halo plan no longer requires --against: a first release has no baseline.

Changed

  • halo init and the intent commands write halos.dev/v1.
  • Release candidates are published as GitHub prereleases and never move the :latest image tag or the Homebrew and Scoop manifests; only a final vX.Y.Z tag does.
  • The Scoop manifest is halo.json; the Homebrew formula lives in the tap's Formula/ directory.

Deprecated

  • apiVersion: halos.dev/v1alpha1 still loads with identical semantics and a validation warning per file. It is removed only in halos.dev/v2.

Fixed

  • halod on Windows: state.json is written with the managed var directory's DACL instead of an owner-only one, so the SYSTEM scheduled task no longer rejects a state file first written by an admin during enrollment.
  • GitLab template: .halos no longer sets a job-level HALOS_VERSION default that shadowed the pipeline-level pin.
  • halo exp analyze could fail with json: unsupported value: -Inf when a guardrail's two arms had no variance yet; the sequential guardrail now reports the exact estimate instead of an unbounded interval.
  • halo-proxy no longer logs a spurious export error when a telemetry flush is cut short by shutdown.
  • test/load paces requests with -rps; an unthrottled run exhausted the kind ingress's ephemeral ports and reported harness 502s as chart failures.

Security

Each finding below has a regression test; none changed an invariant.

  • Policy: bypassPermissions / danger-full-access in profile env or harness overrides is now a halo validate error, not only a release-build backstop.
  • Bundles: halo release build refuses any rendered file carrying a literal credential (Anthropic, GitHub, AWS keys, private keys), without echoing it.
  • halod archive extraction accepts only regular files and no entry larger than the tar itself (PAX/GNU sparse bombs and symlink or hardlink entries are refused); managed files owned by another user, group- or world-writable, or with a loose DACL are replaced rather than adopted; Windows paths are normalised and DOS device names refused.
  • Gateway: JSON bodies are re-encoded with duplicate and case-variant "model" keys dropped (an alias could otherwise be smuggled past the allowlist); request trailers are not forwarded; upstream event-stream chunks are compacted and event names with line breaks refused; halo-kong handles Kong's header-list cap.
  • halo-shadow and the kill-switch fetch never follow redirects.
  • halo-server: login and enrollment are rate-limited; CSRF checks no longer rely on Origin alone; promotion branch names are validated; invalid UTF-8 no longer breaks the audit chain.
  • Docker base images are pinned by digest.

Known gaps

  • Not field-verified (built and tested, never run against the real thing): Jamf, Kandji and Intune tenants; real Codespaces and Coder; Codex and Copilot CLI onboarding entry points (their formats follow the vendors' docs); Bedrock, Vertex, Azure OpenAI and Kong Enterprise/Konnect; the Helm chart on a managed cloud cluster (it runs on kind); kill-switch key rotation on a live cluster (the runbook is derived from code).
  • The nightly fuzz, Scorecard and soak workflows ship here and have not yet had a scheduled run. The soak's p99 gate arms once a reviewed test/load/baseline.json is committed.
  • halod on Windows is a SYSTEM scheduled task, not an SCM service (ADR-0006 addendum). The immutable-file flag has no Windows equivalent.
  • The posture gate has no hardware attestation and the version gate trusts a client-controlled User-Agent; both are honest-client controls, documented in ADR-0011.
  • The support window in the support policy is a stated commitment, not something the code enforces.
  • The CI jobs that install a released halo validate a v1alpha1 copy of the example policy (test/ci/policy-v1alpha1) because the previous release predates halos.dev/v1; they return to examples/acme-corp with the first release after this one.