Skip to content

v0.1.0

Choose a tag to compare

@github-actions github-actions released this 26 May 07:58
· 90 commits to main since this release

0.1.0

Released on 2026-05-26

Added

  • add init arg to firma- install: add install.sh for Linux/macOS (FIR-82)

    POSIX shell installer for the firma CLI. Detects target triple from
    uname, resolves the latest release via the GitHub releases/latest
    redirect probe, downloads the .tar.gz + .sha256, verifies SHA-256,
    extracts into $HOME/.local/bin (overridable), ensures the dir is on
    PATH via the user's shell rc (bash/zsh/fish), and optionally prompts
    to run 'firma stack init'. Prefers 'brew install
    Firma-AI/openfirma/firma' when brew is present.

    Supports --version, --install-dir, --no-brew, --no-modify-path,
    --no-init, --force, --dry-run, plus FIRMA_* env-var equivalents.
    shellcheck-clean under --shell=sh; brew failures fall back to the
    tarball path; PATH edits are sentinel-guarded for idempotency.- install: add install.ps1 for Windows (FIR-82)
    Adds the PowerShell counterpart of install.sh. Detects arch, resolves
    the latest release via the GitHub redirect probe, downloads the .zip

    • .sha256, verifies SHA-256, extracts into a user-writable bin dir,
      adds that dir to the User PATH, and optionally runs firma stack init.

    Adds installer-lint.yml (shellcheck + PSScriptAnalyzer) and
    installer-smoke.yml (POSIX matrix + windows-latest) workflows.- cli: remove firma stack; add firma init; move start/stop to firma sidecar (FIR-182)
    Replace firma stack per CLI spec v0.5:

    • firma init scaffolds a project (config dir, keys, default
      policies). Supports interactive wizard, --yes, scripted
      (--agent, --provider, --workspace, --authority), and a
      user-global --global flag. Defaults to <cwd>/.firma/.
    • firma sidecar {start,stop} replace firma stack {start,stop};
      firma sidecar status covers the dropped firma stack status.
    • firma run calls the scaffold implicitly on first use when no
      firma.toml is discoverable.
    • firma_config::resolve_config gains a project-local tier that walks
      up from cwd looking for .firma/firma.toml (spec §4 step 1), ahead
      of the XDG/platform fallbacks.

    firma-stack crate is kept as the supervision library used by
    firma sidecar start/stop; only the CLI surface is rewritten.

    Docs, install scripts, demos, and tests refreshed accordingly.- init: split config_dir / state_dir; keys never in config tree

    • Add --state-dir flag (env: FIRMA_STATE_DIR; defaults to platform state
      dir via resolve_state_dir) to InitArgs

    • Rename output_dir → config_dir in CollectedInputs; add state_dir

    • Config tree (firma.toml, policies/, mappings/): mode 0700, no keys

    • State tree (authority.key, audit.key, revocations.txt, generated-CA):
      mode 0700, separate location — safe to commit config_dir to git

    • Template: all state paths are absolute {{ state_dir }}/... so they
      resolve correctly regardless of where firma.toml is loaded from

    • scaffold_from_plan aligned to same split

    • Tests: verify keys land in state_dir not config_dir, paths absolute- audit: add sandbox_id to ExecutionEvent and firma monitor filter (FIR-185)
      Per-run identity flows end-to-end so operators can attribute and filter
      audit events back to the firma run invocation that produced them.

    • proto: add sandbox_id (field 17) to ExecutionEvent

    • sidecar: EventBuilder::with_sandbox_id stamps the configured ID on
      every event and includes it in the ECDSA signing payload

    • startup: read FIRMA_RUN_SANDBOX_ID env at sidecar boot; empty when
      the sidecar is not autostarted by firma run

    • firma-run: SidecarSupervisor exports FIRMA_RUN_SANDBOX_ID on the
      spawned child so the marker dir name matches the audit field

    • firma monitor: --sandbox-id <id> filter, AuditLite.sandbox_id
      parsed for filtering, pretty output appends sandbox=<id> when set

    • docs-site: document the new field and filter in the audit-log guide- cli: unify firma run sidecar selection into authority-style flag (FIR-177)
      Replace the split --sidecar <auto|external> value-enum + --sidecar-endpoint

    • --no-autostart conflicts_with with a single --sidecar <local|url> flag,
      mirroring the existing --authority selection shape.
    • --sidecar local autostarts a per-run sidecar.
    • --sidecar tcp://...|unix://... targets an external sidecar; never autostarts.
    • omitted: persisted sidecar_endpoint (external) else local autostart.
    • --no-autostart stays global; incompatible with --sidecar local
      (typed SidecarLocalNoAutostart) and the no-endpoint case (MissingSidecar).

    Add SidecarCli/SidecarSelection + sidecar::resolve() resolved in resolve_profile;
    retire SidecarMode; simplify routing::resolve_effective_endpoint. Update CLI
    tests, docs/cli.md, the firma-run guide, README, and stray references.

Changed

  • use ancestors

Documentation

  • cli: improve cli help message to provide better help and context

    closes fir-181- quickstart: rewrite for binary install flow (FIR-180)
    Drop Rust/protoc/make prerequisites; firma now ships as a precompiled
    static binary. Replace git clone + make demo-ci with the install-script
    one-liner (install.openfirma.ai), then firma init and firma run as the
    zero-knowledge setup path. Add firma monitor to watch decisions and
    point useful references at firma doctor instead of the repo demo README.- readme: refresh README and add docs-site assets- release: add v0.1.0 release notes
    Human-written release notes for the v0.1.0 open-source launch: overview,
    install, and Known issues (firma monitor/doctor bug per FIR-193; prebuilt
    binaries are unsigned). Intended as the GitHub Release body for the v0.1.0 tag.

Fixed

  • install: strip v prefix from asset filenames; pin smoke version

    Release archives are published as firma--.{tar.gz,zip}
    (no v prefix), but install.sh/install.ps1 were building filenames with the
    full tag (v0.0.0) and 404ing on every download. Strip the v prefix when
    constructing ARCHIVE_NAME while keeping the v-tagged path segment for the
    release download URL.

    Pin FIRMA_VERSION=v0.0.0 in the smoke workflow so it does not rely on the
    releases/latest redirect, which excludes prereleases.- install: satisfy shellcheck SC2015 and PSScriptAnalyzer plural-noun

    • setup_tmp: rewrite [ -n ] && [ -d ] || die chain as an explicit
      if-block. SC2015 warns about A && B || C ambiguity; the explicit
      form is also easier to read.

    • Rename Get-AuthHeaders -> Get-AuthHeader to satisfy PSUseSingularNouns.- init: wire authority/sidecar listen addrs into template; add 0700 dirs

    • Add authority_listen, sidecar_listen, authority to CollectedInputs

    • Parameterize firma.toml.j2: [authority] block conditional on local
      authority; authority_url derived from AuthorityShape (local vs remote)

    • Set mode 0700 on output_dir and sensitive subdirs on Unix

    • Adapt init.rs integration tests to user's --output-dir API (not main's
      --config-dir/--state-dir split); rename mode test to match new layout

    • Fix cli_parsing test: use --name/--posture/--mapping (not --agent/--provider)- init: let sidecar use its own defaults; drop fixed port override
      The sidecar already defaults to unix_socket mode on Unix and http_proxy
      on Windows. Emitting mode/listen_addr in the template overrides that.
      Remove [sidecar.interceptor] block from the template so the sidecar
      picks the right transport per platform automatically. Drop sidecar_listen
      from CollectedInputs and ScaffoldPlan — no longer needed.- sidecar: hold ready until authority streams hydrate; rebase autostart template paths (FIR-183)
      Harden sidecar supervisor lifecycle so wrapped agents cannot race the
      readiness gate at startup.

    • Split the seven-line ready contract: emit lines 1-6 (log_pre_ready_sequence)
      immediately, then hold line 7 (ready) until both the policy-bundle and
      revocation streams report ready. With no authority_url, both flags are
      pre-seeded true so ready fires immediately (no behavior change).

    • Add ReadinessFlag::wait_until_fully_ready / snapshot and
      ReadinessState::fully_ready to drive the gate.

    • firma run autostart: rebase relative resource paths in the operator
      template (audit/policy/mapping/authority/capability_seed) onto the
      template's config dir, so they keep resolving against the operator's
      files after the synthesized config is written into the per-run marker dir.- wal: flaky test (#69)

    • fix(wal): flaky test

    • fix(wal): windows

    • more reliable test- generic profile mac and windows (#111)- policy: make scaffolded postures pass validation; authority validates bundle at load (FIR-190)
      The scaffolded postures referenced a schema that was never implemented, so
      firma policy validate failed on all three and the Authority loaded them
      parse-only (a forbid on an unknown action loaded fine and silently never
      fired). Two fixes:

    1. Conform the posture templates to the canonical Firma schema:

      • Drop the resource.id like "169.254.169.254*" forbid — Firma::Resource
        has no attributes, so it can't be expressed in Cedar. The metadata-endpoint
        block belongs at the network/sandbox layer; templates now say so.
      • Remove payment.refund / payment.payout from the payment auto-deny lists;
        neither action exists in the schema. payment.transfer / payment.purchase /
        browser.purchase remain.
        strict, dev, and dev-with-delete-watch now pass firma policy validate.
    2. Authority bundle load is now fail-closed on schema errors. Added
      firma_core::validate_policies (strict schema check) and call it from
      CedarPolicyStore::load (startup error) and reload (keeps the previous
      bundle on an invalid hot-edit), so a schema-invalid bundle can no longer
      load and silently disable a guardrail.- template mappings (#115)

[FIR-110]

  • [Auth] V1.1 mTLS + authorized-clients allow-list on Authority ↔ Sidecar gRPC (#71)
    • feat(auth): implement V1.1 mTLS + authorized client allow-list for Authority↔Sidecar

    • fix(CI): issues

    • fix(CI): errors

    • style: apply rustfmt after rebase conflict resolution

    • fix: clippy

    • test(authority): satisfy clippy in mtls cert fixture

    • chore(clippy): fix lint warnings across run/sidecar/authority tests

    • docs(run): clarify local authority dev mode vs V1.1 mTLS

    • fix(run): fail closed when local authority transport is ambiguous

    • docs: update llms transport-hardening notes and refresh mTLS playbook guidance

[FIR-184]

  • firma run: sandbox backend hardening (loud errors + WSL detection) (#108)
    • fix(run): loud errors + WSL detection for bwrap backend (FIR-184)

    • firma-run: harden bwrap preflight on WSL/userns, fail fast on implicit WSL backend, and tighten regressions/docs

    • test+lint: make socket-bind tests resilient to EPERM and fix wal clippy naming

    • fix(clippy): allow non-linux resolve_backend Result wrapper for pedantic lint

    • firma-run: auto-select wsl2 backend on WSL and add Linux-WSL compatibility path

    • firma-run: refactor wsl2 host-mode routing and add unit coverage for backend command selection

[FIR-192]

  • enforce 0700 on all private state directories (#113)
    • fix: directories permissions

    • fix: firma-stack and run dir permissions

    • refactor: revocations file

Style

  • cli: shorter CLI help texts