v0.0.0
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 runsfirma 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)
Replacefirma stackper CLI spec v0.5:firma initscaffolds a project (config dir, keys, default
policies). Supports interactive wizard,--yes, scripted
(--agent,--provider,--workspace,--authority), and a
user-global--globalflag. Defaults to<cwd>/.firma/.firma sidecar {start,stop}replacefirma stack {start,stop};
firma sidecar statuscovers the droppedfirma stack status.firma runcalls the scaffold implicitly on first use when no
firma.tomlis discoverable.firma_config::resolve_configgains 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-stackcrate 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 thefirma runinvocation that produced them. -
proto: add
sandbox_id(field 17) toExecutionEvent -
sidecar:
EventBuilder::with_sandbox_idstamps the configured ID on
every event and includes it in the ECDSA signing payload -
startup: read
FIRMA_RUN_SANDBOX_IDenv at sidecar boot; empty when
the sidecar is not autostarted byfirma run -
firma-run:
SidecarSupervisorexportsFIRMA_RUN_SANDBOX_IDon 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 appendssandbox=<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_withwith a single--sidecar <local|url>flag,
mirroring the existing--authorityselection shape.
--sidecar localautostarts a per-run sidecar.--sidecar tcp://...|unix://...targets an external sidecar; never autostarts.- omitted: persisted
sidecar_endpoint(external) else local autostart. --no-autostartstays 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. - .sha256, verifies SHA-256, extracts into a user-writable bin dir,
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 ] || diechain 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 validatefailed on all three and the Authority loaded them
parse-only (a forbid on an unknown action loaded fine and silently never
fired). Two fixes:
-
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 passfirma policy validate.
- Drop the
-
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