Changelog
The format is based on Keep a Changelog, and this project follows Semantic Versioning.
[4.4.0] - 2026-08-16
Added
ChainConflictErrorand compare-and-swap append semantics for everyHashChainStore.
Changed
HashChainAppenderrefreshes a raced tail and retries with jitter, defaulting to 32 attempts.JsonlHashChainStoreuses POSIXflockacross tail reads and appends and incorporates records written by other processes. Windows remains thread-only.
[4.3.0] - 2026-08-16
Added
briefcase.integrity: strict and compatibility canonical JSON, spec-versioned hash chains, in-memory and hardened JSONL stores, segment verification, Ed25519 signatures, RFC 8037 JWKs, and JWK thumbprints.
Changed
- Bitemporal and examiner-bundle hashes use the compatibility profile without changing existing digest bytes.
[4.2.0] - 2026-08-16
Added
- Python and TypeScript invocation controls, provider fallback, quota ports, cooldown classification, retries, exporters, and semantic conventions.
@briefcase-ai/nativefor Rust-backed cost estimation and model-ID normalization.capture_contentmodes, framework auto-instrumentation, OPA, RBAC/ABAC, GCP and OTel exporters, Kafka and webhook transports, vector and VCS adapters, Glue Iceberg, kdb+, and KMS signing.
Changed
- Unconfigured capture is a direct call-through. Full capture uses bounded rendering and background exports share one FIFO worker.
- Signed examiner-bundle verification requires a caller-pinned key ID and algorithm.
[4.1.0] - 2026-08-13
Added
- Replay executors, decision content hashes, batch storage writes, and a fully readable and flushable
BufferedBackend.
Changed
- Replay without an executor reports
pending, policy rules evaluate replayed outputs, andTimeoutWrapperstops waiting at its deadline.
[4.0.1] - 2026-08-12
Fixed
- The
mcpextra pinsmcp>=1.2,<2. mcp 2.0 removedmcp.server.fastmcp, whichbriefcase.mcpis built on, so a freshpip install briefcase-ai[mcp]on 4.0.0 resolved 2.x and the import failed. The guard also now distinguishes “mcp is not installed” from “mcp is installed but too new”, naming the version it found, instead of telling you to install a package you already had.
[4.0.0] - 2026-08-12
Security
- Card redaction is gated on an issuer prefix, not Luhn alone. A 16-digit run is still redacted on shape; other lengths (13-19) must pass Luhn and begin with an issuer digit (3-6). Luhn by itself accepts roughly one arbitrary digit run in ten, so epoch-millisecond timestamps and snowflake identifiers were being redacted out of stored records.
- Card, phone, and SSN matches are rejected when they continue into a longer digit run, directly or across a hyphen. All three patterns could previously match a prefix of a longer identifier, turning an all-numeric UUID into
[REDACTED_CREDIT_CARD]-[REDACTED_CREDIT_CARD]. Whitespace is not a continuation, so4111111111111111 5500000000000004is two cards and both redact. BriefcaseClientrefuses plain http to non-loopback hosts, on every redirect hop, since the API key travels in the request body.ClientConfig.allow_insecure_httpopts back in.- CLI state (
~/.briefcase) is created 0700/0600;briefcase secret set KEYreads from stdin or a prompt instead of argv. SQLite store files are created 0600, and record IDs are validated against path escapes.
Added
briefcase.integrations.evals(extraevals):EvalRunrecords evaluation cases aseval.caserecords and oneeval.runsummary with pass rate, per-score statistics, token totals, cost, and optional drift.from_inspect_log()andfrom_lm_eval_results()parse inspect-ai and lm-eval-harness logs without importing either framework;replay()emits them as decision records. See Evaluation Runs.briefcase.integrations.gym(extragym):GuardrailGymEnvexposes anyGuardrailEnvplus a task suite as a single-stepgymnasium.Env, and passesgymnasium.utils.env_checker.check_env.capture_episodes()records any rollout asrl.stepandrl.episode. See Gymnasium.AgentRouter.route(decided_at=...)pins the decision timestamp for deterministic replay.track_db_query/track_file_fetchacceptvalid_timeandsource_trust_level.
Changed
- Breaking:
VersionedClientrequires an endpoint and credentials and raises on live failures instead of returning fabricated data.mock=Trueopts into an offline stub whose metadata carries"mock": True;require_live=Truerejects it. - Breaking: Python bindings raise typed exceptions (
PermissionError,ConnectionError,ValueError,KeyError,OSError) instead of blanketRuntimeError.replay_batchraises the first failure’s typed exception and attachesresults,failed_indices,succeeded, andtotal, so a partial batch is recoverable. - Breaking:
python_to_json_valueraisesTypeErrorfor values with no JSON equivalent (a set, an arbitrary object, a non-string dict key, NaN/Infinity) rather than storingnull. Values with one obvious form still convert:datetime/date/timebecome ISO strings andUUIDits canonical string. - Breaking:
PromptValidationEngineraisesValueErrorfor modes other thanstrict/tolerant/warn_only. - Breaking (Rust):
ClientConfigandDriftMetricsare#[non_exhaustive];DriftMetricsgainedtotal_samples. The workspace declaresrust-version = "1.85". - Native calls release the GIL while blocking on the Tokio runtime.
Fixed
- SQLite
query()with a content filter stops scanning once it holdsoffset + limitmatches, instead of deserializing every row in the range. - Synchronous export no longer blocks a running event loop indefinitely; it waits at most 5 seconds, then warns and lets the export finish on its background thread.
SqliteBitemporalBackendopens read-only stores and normalizes legacy timestamps per query, so an archived database stops omitting records from as-of answers.PromptValidationEngineaccepts both lakeFSget_commit()contracts instead of silently pinning every report to"unknown".enable_logging(stream=...)no longer assumes the handler it finds by name is aStreamHandler.
[3.2.1] - 2026-05-30
Added
- Cost rate cards (
briefcase.cost.CostCalculator.estimate_cost): an optional keyword-onlyrate_cardselects aplatform × tier × modifierpricing scheme — platformsfirst_party/bedrock/vertex/azure, tiersstandard/batch/cached/priority/flex, and modifiers for long-context tiered pricing, data residency (us, +10%), and fast-mode. Cards are forgiving strings such as"batch","bedrock:batch", or"first_party:fast"; batch/flex are 0.5×, cache reads are 0.1× of input, and regional/residency add 10%. New keyword-onlycache_read_tokens/cache_write_5m_tokens/cache_write_1h_tokensarguments bill prompt-cache usage, acache_costfield is exposed onCostEstimate, andget_available_rate_cards()lists representative cards. Omittingrate_card(or passing"standard") preserves the previous first-party standard pricing. - Latest model pricing: added Anthropic Claude 4.x (
claude-opus-4-8/4-7/4-6/4-5/4-1,claude-sonnet-4-6/4-5,claude-haiku-4-5/3-5), OpenAI GPT-5.x (gpt-5.5,gpt-5.5-pro,gpt-5.4,gpt-5.4-mini,gpt-5.4-nano,gpt-5.4-pro), and Google Gemini (gemini-3.5-flash,gemini-3.1-pro,gemini-3.1-flash-lite,gemini-3-flash,gemini-2.5-pro/flash/flash-lite) to the default pricing table. All previously available models are retained.
Changed
CostCalculator.estimate_cost,estimate_cost_from_text, andproject_monthly_costgained keyword-onlyrate_card(and, forestimate_cost, cache-token) parameters. The existing positional arguments and theirinput_tokens/output_tokenskeyword names are unchanged, so existing calls behave identically.- The MCP
estimate_costtool accepts an optionalrate_cardand returns acache_costfield.
Fixed
- A single stable-ABI wheel per platform now installs on Python 3.9–3.13 (previously the prebuilt wheel was effectively 3.11-only).
- The source distribution now bundles
LICENSEandNOTICE.
[3.2.0] - 2026-05-30
Added
- Stock exporters in the base package (
briefcase.exporters):ConsoleExporter(JSON lines to stderr),JSONLFileExporter(append-only, thread-safe), andMemoryExporter(collects records in.records). - One-line observability setup:
briefcase.observe(exporter="console", *, level=None)wires the global exporter so@capturerecords are emitted, and returns the configured exporter for inspection. - Centralized logging in the base package: top-level
enable_logging,set_log_level,disable_logging, andget_logger. The library is silent by default (NullHandler); setBRIEFCASE_LOG_LEVEL=DEBUGto enable logging automatically at import. - MCP server (
pip install briefcase-ai[mcp]): thebriefcase-mcpconsole script (orpython -m briefcase.mcp) exposessanitize_text,estimate_cost,analyze_drift, andhow_totools plus abriefcase://llms-full.txtresource to MCP-capable clients.briefcase.mcpexportsbuild_server()andmain(). - LLM-friendly
llms.txt,llms-full.txt, andAGENTS.mdso coding assistants can discover the API surface. - Bitemporal evidence primitives (
briefcase.bitemporal):BitemporalRecord, theBitemporalStoreprotocol with in-memory, SQLite, and Iceberg backends,AsOfView, append-only corrections, and batch/stream ingest. - Versioned routing policy (
briefcase.routing):PolicyRegistry,PolicyVersion,PolicyRule,AgentRouter, andAgentRoutingDecision. - Audit bundles (
briefcase.compliance):ExaminerBundlewith SHA-256 content-hash integrity and tamper detection. - Top-level
briefcase.capture,briefcase.setup, andbriefcase.BriefcaseConfigre-exports for discoverability. ExternalDataTracker(sanitizer=...)to redact PII from external-data snapshots before they are persisted to durable storage.scripts/check_imports.pyimport-smoke test for the built wheel.
Fixed
briefcase.cost,briefcase.drift, andbriefcase.sanitizenow import from a clean source build. The native bindings were missingadd_classregistrations forCostEstimate,BudgetStatus,DriftMetrics,Redaction,SanitizationResult, andSanitizationJsonResult;briefcase.costalso imported a non-existentBudgetAlerttype.briefcase.ragno longer fails to import on a spuriouspyarrowrequirement.- Misleading
ImportErrormessages on native-backed modules now point to reinstall/rebuild rather than no-op pip extras. scripts/version_sync.pymissingIterableimport; the manifest now also tracksbindings/python/Cargo.toml.- The flagship
examples/python-basicand validation examples now run end-to-end.
Security
- External-data snapshots can be redacted before persistence; redaction fails closed if it errors.
- Expanded PII detection: corrected the email regex and added GitHub, GitLab, Stripe, and Hugging Face API-key prefixes.
- Robust telemetry opt-out:
BRIEFCASE_TELEMETRYnow accepts0,false,no, andoff. source_nameis sanitized before use in storage object keys (path-traversal hardening).
Changed
- Deduplicated the optional OpenTelemetry import into
briefcase._otel. - Extracted guardrail core data types into
briefcase.guardrails._types. - CI builds and tests across Python 3.9-3.13, runs the native binding tests, and import-smoke-tests the built wheel before publish.
[3.0.0] - 2026-03-22
Added
- Initial open-source release: decision tracking, deterministic replay, drift and cost calculation, PII sanitization, and SQLite storage, backed by a Rust core.