Skip to content

Changelog

The format is based on Keep a Changelog, and this project follows Semantic Versioning.

[4.4.0] - 2026-08-16

Added

  • ChainConflictError and compare-and-swap append semantics for every HashChainStore.

Changed

  • HashChainAppender refreshes a raced tail and retries with jitter, defaulting to 32 attempts.
  • JsonlHashChainStore uses POSIX flock across 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/native for Rust-backed cost estimation and model-ID normalization.
  • capture_content modes, 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, and TimeoutWrapper stops waiting at its deadline.

[4.0.1] - 2026-08-12

Fixed

  • The mcp extra pins mcp>=1.2,<2. mcp 2.0 removed mcp.server.fastmcp, which briefcase.mcp is built on, so a fresh pip 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, so 4111111111111111 5500000000000004 is two cards and both redact.
  • BriefcaseClient refuses plain http to non-loopback hosts, on every redirect hop, since the API key travels in the request body. ClientConfig.allow_insecure_http opts back in.
  • CLI state (~/.briefcase) is created 0700/0600; briefcase secret set KEY reads 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 (extra evals): EvalRun records evaluation cases as eval.case records and one eval.run summary with pass rate, per-score statistics, token totals, cost, and optional drift. from_inspect_log() and from_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 (extra gym): GuardrailGymEnv exposes any GuardrailEnv plus a task suite as a single-step gymnasium.Env, and passes gymnasium.utils.env_checker.check_env. capture_episodes() records any rollout as rl.step and rl.episode. See Gymnasium.
  • AgentRouter.route(decided_at=...) pins the decision timestamp for deterministic replay.
  • track_db_query / track_file_fetch accept valid_time and source_trust_level.

Changed

  • Breaking: VersionedClient requires an endpoint and credentials and raises on live failures instead of returning fabricated data. mock=True opts into an offline stub whose metadata carries "mock": True; require_live=True rejects it.
  • Breaking: Python bindings raise typed exceptions (PermissionError, ConnectionError, ValueError, KeyError, OSError) instead of blanket RuntimeError. replay_batch raises the first failure’s typed exception and attaches results, failed_indices, succeeded, and total, so a partial batch is recoverable.
  • Breaking: python_to_json_value raises TypeError for values with no JSON equivalent (a set, an arbitrary object, a non-string dict key, NaN/Infinity) rather than storing null. Values with one obvious form still convert: datetime/date/time become ISO strings and UUID its canonical string.
  • Breaking: PromptValidationEngine raises ValueError for modes other than strict / tolerant / warn_only.
  • Breaking (Rust): ClientConfig and DriftMetrics are #[non_exhaustive]; DriftMetrics gained total_samples. The workspace declares rust-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 holds offset + limit matches, 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.
  • SqliteBitemporalBackend opens read-only stores and normalizes legacy timestamps per query, so an archived database stops omitting records from as-of answers.
  • PromptValidationEngine accepts both lakeFS get_commit() contracts instead of silently pinning every report to "unknown".
  • enable_logging(stream=...) no longer assumes the handler it finds by name is a StreamHandler.

[3.2.1] - 2026-05-30

Added

  • Cost rate cards (briefcase.cost.CostCalculator.estimate_cost): an optional keyword-only rate_card selects a platform × tier × modifier pricing scheme — platforms first_party / bedrock / vertex / azure, tiers standard / 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-only cache_read_tokens / cache_write_5m_tokens / cache_write_1h_tokens arguments bill prompt-cache usage, a cache_cost field is exposed on CostEstimate, and get_available_rate_cards() lists representative cards. Omitting rate_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, and project_monthly_cost gained keyword-only rate_card (and, for estimate_cost, cache-token) parameters. The existing positional arguments and their input_tokens / output_tokens keyword names are unchanged, so existing calls behave identically.
  • The MCP estimate_cost tool accepts an optional rate_card and returns a cache_cost field.

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 LICENSE and NOTICE.

[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), and MemoryExporter (collects records in .records).
  • One-line observability setup: briefcase.observe(exporter="console", *, level=None) wires the global exporter so @capture records are emitted, and returns the configured exporter for inspection.
  • Centralized logging in the base package: top-level enable_logging, set_log_level, disable_logging, and get_logger. The library is silent by default (NullHandler); set BRIEFCASE_LOG_LEVEL=DEBUG to enable logging automatically at import.
  • MCP server (pip install briefcase-ai[mcp]): the briefcase-mcp console script (or python -m briefcase.mcp) exposes sanitize_text, estimate_cost, analyze_drift, and how_to tools plus a briefcase://llms-full.txt resource to MCP-capable clients. briefcase.mcp exports build_server() and main().
  • LLM-friendly llms.txt, llms-full.txt, and AGENTS.md so coding assistants can discover the API surface.
  • Bitemporal evidence primitives (briefcase.bitemporal): BitemporalRecord, the BitemporalStore protocol with in-memory, SQLite, and Iceberg backends, AsOfView, append-only corrections, and batch/stream ingest.
  • Versioned routing policy (briefcase.routing): PolicyRegistry, PolicyVersion, PolicyRule, AgentRouter, and AgentRoutingDecision.
  • Audit bundles (briefcase.compliance): ExaminerBundle with SHA-256 content-hash integrity and tamper detection.
  • Top-level briefcase.capture, briefcase.setup, and briefcase.BriefcaseConfig re-exports for discoverability.
  • ExternalDataTracker(sanitizer=...) to redact PII from external-data snapshots before they are persisted to durable storage.
  • scripts/check_imports.py import-smoke test for the built wheel.

Fixed

  • briefcase.cost, briefcase.drift, and briefcase.sanitize now import from a clean source build. The native bindings were missing add_class registrations for CostEstimate, BudgetStatus, DriftMetrics, Redaction, SanitizationResult, and SanitizationJsonResult; briefcase.cost also imported a non-existent BudgetAlert type.
  • briefcase.rag no longer fails to import on a spurious pyarrow requirement.
  • Misleading ImportError messages on native-backed modules now point to reinstall/rebuild rather than no-op pip extras.
  • scripts/version_sync.py missing Iterable import; the manifest now also tracks bindings/python/Cargo.toml.
  • The flagship examples/python-basic and 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_TELEMETRY now accepts 0, false, no, and off.
  • source_name is 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.