Skip to main content

Changelog

Version history for the Governance SDK. Each release lists every shipped change grouped by category.

v0.7.0

newApril 19, 2026

Platform bridge + distribution pivot. Distribution-pivot release. The SDK gains an optional platform bridge that dual-writes audit events to a hosted Code Atelier Governance platform (at codeatelier.tech/api/v1/ingest/events) while keeping the customer's local Postgres as the authoritative source of record. The bridge is opt-in and non-blocking: the host application continues to work unchanged if the platform is unreachable, rate-limited, or the token is revoked. Also shipping: an agent-recipe scaffolder CLI (governance init agent-<kind>), a Microsoft AGT integration wrapper (wrap_agt_agent + migration guide), and budget-alert webhooks (BudgetPolicy.alert_webhook_url, HMAC-signed, threshold-crossing — not first-breach).

Everything in v0.7.0 is additive — no BREAKING API changes from v0.6.2. Setup walkthrough at Connect to the hosted platform.

Explicit opt-in required for the platform bridge

  • The bridge default is platform_bridge_enabled=False, matching sibling modules (enable_routing, enable_coverage). Setting GOVERNANCE_PLATFORM_INGEST_URL + _TOKEN env vars is not enough on its own — you must also pass platform_bridge_enabled=True (or set GOVERNANCE_PLATFORM_BRIDGE_ENABLED=true). When activated, a single platform.bridge_enabled WARN line surfaces the configured URL + a link to the data-residency page, so bridge activation is never invisible to an operator reading logsnew
  • Data residency — activating the platform bridge routes a copy of every audit event (event_type, agent_id, session_id, metadata up to 64 KiB) to codeatelier.tech. The bridge is designed to be OFF by default; customers who cannot move audit metadata off-premise should leave it off — the local Postgres is the authoritative source of recordnew

Added

  • Platform bridge (codeatelier_governance.platform) — async HTTP client that POSTs each local audit event to the platform's ingest endpoint. Fire-and-forget from the audit hot path; retries with exponential backoff on 429; silent on 5xx; logs (but does not raise) on 4xx. Bounded in-process queue (default 1000; drops oldest on saturation). Observability-grade, not durable-queue: on crash / kill -9, up to max_queue_size in-flight rows on the bridge path may be lost. Local Postgres writes are unaffectednew
  • New SDK kwargs: platform_ingest_url, platform_ingest_token, platform_bridge_enabled (default False), platform_trusted_hosts. Env equivalents: GOVERNANCE_PLATFORM_INGEST_URL, GOVERNANCE_PLATFORM_INGEST_TOKEN, GOVERNANCE_PLATFORM_BRIDGE_ENABLED, GOVERNANCE_PLATFORM_TRUSTED_HOSTS (comma-separated)new
  • seq self-heal — on a seq_out_of_order 409 the bridge reads the server's expected_seq and retries once, so an SDK process restart that jumps the local seq counter converges without operator intervention. stats.dropped_seq_conflict surfaces the cases where even the self-heal couldn't converge (should be 0 in steady state)new
  • Bridge hardening — default-ON SSRF guard (rejects RFC1918 / loopback / link-local / AWS-GCP-Azure metadata hosts even without an explicit trusted_hosts allowlist), trusted_hosts pinning allowlist, trust_env=False on the httpx client (blocks HTTPS_PROXY exfil), follow_redirects=False (blocks 302 exfil), queue-WARN rate-limiter (1 WARN per 30s), whitespace-stripping on ingest tokens, 401-latch self-disable (revoked tokens never retry)new
  • Agent recipe CLI (F3) — governance init agent-<kind> where <kind>{customer-support, data-enrichment, internal-research}. Generates a ruff-clean + mypy-strict .py file that passes --smoke on first run. (This is an agent scaffolder, not an AGT recipe — for AGT use wrap_agt_agent below.)new
  • Microsoft AGT integration (F4) — AGTBridge (telemetry ingestion, maps AGT event dicts → AuditEvent) plus wrap_agt_agent(agent, sdk, agent_id=...) for pre-execution enforcement on async AGT ChatAgent instances. Sync-agent wrapping raises at wrap-time (AGT's documented default is async). Top-level re-exports: AGTBridge, wrap_agt_agentnew
  • Budget-alert webhooks (F2) — BudgetPolicy.alert_webhook_url + alert_webhook_secret + alert_threshold_pct. Fires a canonical-JSON HMAC-SHA256 signed POST (schema governance.cost.budget_alert/v1) on threshold CROSSING (default 80%), deduped per (agent_id, cap_id, UTC-day-bucket). Gated by GOVERNANCE_COST_WEBHOOKS_ENABLED=true (default false). Blocks RFC1918 / cloud-metadata hosts, trust_env=False, follow_redirects=False, 1-retry-then-dropnew
  • Cost CSV exportcost.csv_export._csv_safe prefix-quotes CSV-injection characters (=, +, -, @, \t, \r); idempotentnew
  • Optional dep: pip install "code-atelier-governance[platform]" adds httpx>=0.27 for the bridge. Without it, the bridge imports fail loudly at SDK init if creds are set — never silentlynew

Known limitations shipped in v0.7.0

  • Bridge seq counter is process-scoped. An SDK restart re-starts the counter at 1; seq self-heal converges after the first retry. Postgres-persisted seq is a v0.8 item
  • Budget-alert dedup is in-memory — duplicate POSTs on process bounce within the same UTC day. Postgres-backed dedup in v0.7.1
  • LOC budget: v0.7 target was ≤2k LOC net; actual is larger. Platform bridge + AGT integration + cost webhook + recipe CLI compressed a v0.7 + v0.7.5 cadence into one tag. v0.7.1 will split narrower

Upgrade notes

  • pip install --upgrade "code-atelier-governance[platform]>=0.7.0" — add the [platform] extra only if you plan to activate the bridge; the SDK still installs without it
  • No new Postgres migrations. Drop-in upgrade from v0.6.2 — every v0.7.0 addition is additive and opt-in
  • See Connect to the hosted platform for the sign-up → workflow → token → env-var walkthrough, plus data-residency notes and the hardening-defaults list

v0.6.2

April 17, 2026

v4 console default flip + 5 P0 enforcement fixes. Patch release lands the four parked Wave 1.5 worktrees from the v0.6.1 polish sprint, flips the default console UI from v3 to v4, and bundles five P0 fixes uncovered during the v0.6.1 post-ship team review and a subsequent live demo walkthrough: wheel-packaged migrations, grant/deny TOCTOU, halt enforcement expanded across cost + gates + LLM wrappers, grant/deny token HMAC verification (broken since v0.2), and rotation-aware session chain verify. Phase 2 additionally lands end-of-stream reconciliation for the Anthropic + OpenAI wrappers, claude-opus-4-7 pricing, strict-by-default CostModule/RevocationStore/InMemoryAuditStore, and v2 gate tokens (opt-in).

Four BREAKING blocks apply — see the 0.6.2 upgrade guide before pinning. No new migrations.

BREAKING DEFAULTS — four defaults flipped to fail-closed

  • CostModule.strict_unknown_models=True — unknown model names raise UnknownModelError instead of returning 0.0. Add pricing entries (cost/pricing.py::MODEL_PRICING) or set cost_strict_unknown_models=False with a fallback rate. LangChain handler is already wired to observe-only mode (never raises); direct SDK callers see the raise. New env vars: GOVERNANCE_COST_STRICT_UNKNOWN_MODELS, GOVERNANCE_COST_UNKNOWN_MODEL_FALLBACK_USD_PER_MILLIONnew
  • InMemoryAuditStore.on_full="raise" — hitting max_events raises StoreUnavailableError instead of silently evicting. Callers needing ring-buffer semantics must pass on_full="evict". BatchingWriter's internal fallback opts into eviction automatically. .stats() + .verify_not_truncated() are newnew
  • RevocationStore.strict_chain=True — when the audit write inside revoke_with_chain_event fails, the revocation now RAISES (previously it wrote the row with chain_event_id=None). Pass strict_chain=False to preserve degraded-mode behavior; WARN is logged as identity.revocation_without_chain_eventnew
  • Gate resolve + audit event now run through a single serialized path (on_commit hook). The narrow residual window (audit commits, gates rolls back) is documented and detectable via duplicate approval.granted chain rows on one request_id. True cross-engine atomicity is a v0.7+ targetnew

BREAKING WIRE CONTRACT — /api/gates/pending + verify failure reasons

  • /api/gates/pending (v1) is now admin-only and caps at 500 rows. Response shape is unchanged (plain array) but carries Deprecation: true, Sunset: Thu, 01 Oct 2026, and X-Truncated: true when the cap is hit. Migrate to /api/v2/gates/pending which returns {items, has_more, next_cursor} with keyset pagination (cursor format: "<iso_ts>|<request_id>")new
  • Per-agent reviewer scope is deferred to v0.6.3; admin is the only role with access today. Grant/deny were already admin-only, so read-scope now matches act-scopenew
  • GET /api/session/{id}/verify may return new failure_reason values (rotation_marker_dual_mac_failed, rotation_marker_no_incoming_key, rotation_marker_unresolved_incoming:<fp16>, rotation_marker_without_key_versions, unresolved_key:<fp16>, hmac_mismatch). New top-level first_failure_reason field scopes the first breaking eventnew

BREAKING BEHAVIOUR (gate token format) — v2 opt-in

  • GatesModule(enable_v2_tokens=False) is the default in v0.6.2. Tokens mint in legacy v1 format. Set enable_v2_tokens=True (or env GOVERNANCE_GATES_ENABLE_V2_TOKENS=true) to opt in to the v2:<key_prefix>:… format, which binds tokens to the HMAC key version active at issue time — pre-rotation tokens keep verifying after rotate-chain-key. Both formats verify in v0.6.2new
  • v1 tokens accepted until accept_v1_until (default: ~2026-07-17, 90 days post-release). After that cutoff, v1 tokens raise TokenVersionTooOldError. Override via GatesModule(accept_v1_until=...) or env GOVERNANCE_GATES_ACCEPT_V1_UNTIL. Pre-cutoff parses emit DeprecationWarning and gates.legacy_token_parsed INFO eventsnew
  • v0.6.3 will flip enable_v2_tokens=True as the default. Rolling deploys spanning that boundary should set the flag explicitlynew

BREAKING BEHAVIOUR (streaming accounting) — Anthropic + OpenAI wrappers

  • Streaming responses reconcile actual token usage at end-of-stream. Previous releases tracked only the projected max_tokens value. Customers with hard USD caps should expect more accurate (and often higher) cost numbersnew
  • Abandoned streams (proxy returned but never iterated) emit governance.stream.abandoned_without_reconcile WARN and best-effort reconcilenew
  • Mid-stream exceptions and asyncio.CancelledError reconcile with a conservative chunks × 8 token estimate instead of silent projected-wins — closes an agent-initiated budget-bypass vectornew
  • OpenAI chat.completions.create wrappers auto-inject stream_options={"include_usage": True} unless the caller explicitly sets it. Explicit include_usage=False is honored but logs a one-shot WARNnew
  • Reconciling proxy preserves isinstance() identity with the wrapped stream classnew

BREAKING BEHAVIOUR (halt enforcement)

  • Calling any enforcement path — cost.check_or_raise, gates.request, wrap_openai, wrap_anthropic — against a halted agent now raises AgentHaltedError. On v0.5.4–v0.6.1 these paths silently succeeded because only scope.check was wired into halt. If your application catches and ignores enforcement errors to allow graceful degradation, add an explicit except AgentHaltedError guard before upgrading. Tokens minted BEFORE the halt still resolve through gates.grant/gates.deny, since the reviewer — not the agent — is the principal on resolutionnew

Added

  • Wheel-packaged migrations (P0). alembic.ini and the full migrations/ tree now ship inside the codeatelier_governance package. v0.6.0/v0.6.1 wheels omitted these files so fresh pip install users ran base DDL only; the alembic step silently no-op'd and the first audit write raised StoreUnavailableError against the missing signature_status columnnew
  • Grant/deny TOCTOU closed (P0). POST /api/gates/:id/grant and /deny now pin the UPDATE to the reviewer_id read during the authz check and use RETURNING to detect a racing claim. A lost race returns 409 instead of silently granting/denying on a claim owned by a different reviewernew
  • Grant/deny token HMAC verification (P0, silently broken since v0.2). The console's grant/deny handlers compared the full signed token against a self-computed HMAC of just the request_id — always mismatched, so any real SDK-minted token rejected. Invisible to every unit test because mock gate rows used token: None. Caught during a live demo walkthrough. Fix: dogfood the SDK's own parse_token and cross-check request_id AND action_hash on both grant and denynew
  • Session-drawer chain verify is rotation-aware (P0). GET /api/session/{id}/verify now loads governance_audit_chain_keys and verifies each row under the key active at ITS chain_seq rather than under the single current AUDIT_SECRET. Pre-fix, any customer who ran cga rotate-chain-key saw legitimate pre-rotation events as verified=falsenew
  • v4 is the default console UI. / rewrites to /agents under v4. Compliance entry in the v4 sidebar (/compliance). ComplianceHeaderPill navigates to /compliance on click; re-verify is an adjacent keyboard-reachable icon button with explicit aria-label. Officer-voice empty-state copy for the v4 drill panelsnew
  • console_ui_version cookie persistence. The ?ui=v3 / ?ui=v4 query override survives subsequent navigations via a 30-day SameSite=Lax cookie. Precedence: query → cookie → env var → default v4. Query param stripped from URL on the persist-redirectnew
  • UTC timestamps across the console (LiveBadge, /cost last-updated, v3 root agent-card, /stream event timestamps, compliance page). New shared formatDate.ts helper. Sidebar approval-count badge always visible (was /gates-active-only). Compliance page redesign — hero-first IA with promoted Export button and inline download confirmation. Walkthrough refreshed for v0.6.2 (dev-voice → compliance-officer-voice)new

Upgrade notes

  • No new migrations. Drop-in from v0.6.0/v0.6.1 for already-migrated schemas. Fresh installs now work end-to-end via pip install code-atelier-governance[migrations]==0.6.2 + governance migrate
  • Default console is v4. Run-time rollback: append ?ui=v3 to any console URL (persists via 30-day cookie). Build-time rollback: set NEXT_PUBLIC_CONSOLE_UI_VERSION=v3 BEFORE next build. v3 is removed in v0.7
  • See the dedicated 0.6.2 upgrade guide for the four BREAKING blocks with code-level migration recipes

v0.6.1

April 16, 2026

Security sweep fixes. Patch release driven by a 5-agent security sweep against v0.6.0 and a follow-on Devil's Advocate pass. No API changes; one wire-contract change to the compliance bundle signature scheme. Superseded one hour after publish by v0.6.2, so no production bundles exist under the original v0.6.0 scheme.

Security

  • AuditEvent field sanitization (S5 P1). Every caller-controllable string field on AuditEventkind, agent_id, model, input_hash, output_hash — now flows through the same NFC-normalise + C0/ANSI-strip sanitizer as metadata. Closes an insider-with-SDK-creds text-injection primitive against surfaces that render audit rows in a terminal or HTML shell (operator governance audit tail CLI, console event list, compliance exports)new
  • OTel exporter redacts secret-shaped metadata (S5 P1). OTelExporter._build_attributes applies redact_secrets to record.metadata before flattening values into span attributes. Stack traces and vendor DSNs that accidentally land in audit metadata no longer leak over the host's OTel pipe. redact_secrets moved to a new security/ package so both audit and console can call it without cross-package layering violationsnew
  • Database DSN pattern added to redact_secrets (DA follow-up). postgres://, postgresql://, mysql://, mongodb://, mongodb+srv://, redis://, rediss:// URLs (with or without embedded credentials) are now redacted. Matches the frontend sanitizeErrorMessage DSN pass for paritynew
  • POST /api/gates/{id}/escalate claimant check (S3 P1). A gate claimed by reviewer A can now only be escalated by reviewer A or by an admin (403 otherwise). Prior behaviour let any authenticated user — including viewers — release any reviewer's claim by NULL-ing reviewer_id, a continuous griefing vectornew
  • Escalate TOCTOU closed (DA follow-up). The SELECT-for-authz / UPDATE split in escalate_gate could let a racing writer mutate reviewer_id between the two statements at default READ COMMITTED isolation. The UPDATE now pins the expected reviewer_id via IS NOT DISTINCT FROM with RETURNING and 409s on a lost racenew
  • Console error-message sanitizer gains high-entropy passes (S5 P2). sanitizeErrorMessage now strips bare 32+ char hex runs and 40+ char base64 runs with entropy lookaheads. Catches fake AUDIT_SECRETs, HMAC digests, and Ed25519 signatures that a server could echo into an error body without a surrounding token= keywordnew

Changed — wire contract

  • Compliance bundle signature scheme is algorithm-pinned. Both bundle_hash and bundle_signature.signature now cover bundle_signature.algorithm and bundle_signature.key_fingerprint. The prior scheme (v0.6.0) excluded the whole bundle_signature sub-object from the hash input and so permitted a version-confusion downgrade. v0.6.0 bundles will NOT re-verify under the v0.6.1+ verifier; v0.6.0 shipped ~1 hour before v0.6.1 so no production bundles exist under the old schemenew

v0.6.0

April 16, 2026

Ed25519 + HMAC rotation + Article 12 evidence export + fresh-install fix. Major release implementing F2–F9 of the v0.6 PRD plus a polish pass (Track A finish, LLM-theater tripwire closure, compliance export button, fresh-install wiring). Upgrade path for v0.5.x deployments: install the [migrations] extra and run governance migrate — it now applies the base DDL and runs alembic upgrade head in one shot. See the full release notes on PyPI.

Added

  • Ed25519 agent identity with file, env, and ephemeral keystores. Per-row Ed25519 signature over the HMAC audit chain. Graceful degradation to signature_status='unsigned_local_failure' when a signer cannot load its private key — the host call path never raises
  • HMAC chain key rotation with dual-signed rotation marker rows, salted fingerprint construction, bounded LRU resolution cache, and a governance rotate-chain-key CLI command
  • Article 12 evidence exportPOST /api/compliance/export packages the compliance report and chain verification into a single HMAC-signed JSON bundle (bundle_hash + bundle_signature) you can hand to a regulator. "Export Article 12 evidence" button in the v4 console with Windows-safe filename and screen-reader-announced download lifecycle
  • Wrapper coverage registry — opt-in registry of every wrapped LLM client at import time, surfaced via GET /api/coverage and the new /health/governance endpoint
  • GOVERNANCE_COMPLIANCE_RATE_LIMIT env var — overrides the default 1 req / 60s per-user ceiling on compliance endpoints

Changed

  • governance migrate now applies the base DDL and runs alembic upgrade head automatically — one command takes a new database all the way to HEAD. Closes a latent P0 where fresh v0.6 installs that ran DDL-only silently dropped audit rows with StoreUnavailableError against the missing signature_status column
  • killhalt rename across SDK, console, and audit events. Backward-compat aliases preserved in v0.6, removed in v0.7. Historic agent.killed rows stay in the chain as-is; a SQL view governance_audit_events_halted unions both kinds
  • Append-only grants on governance_audit_events enforced at the role level (previously only at the row-trigger level) — closes a latent invariant-2 gap

Upgrade notes

  • pip install "code-atelier-governance[migrations]>=0.6.0"
  • governance migrate --database-url $DATABASE_URL (runs DDL + alembic; idempotent)
  • Three new columns on governance_audit_eventssignature, signing_key_fingerprint, signature_status. Strict-schema SIEM / BI pipelines must widen
  • Queries filtering on kind='agent.killed' will silently stop matching new halt events. Either query the governance_audit_events_halted view or filter IN ('agent.killed', 'agent.halted')

v0.5.4

April 14, 2026

Kill switch enforcement hotfix. Closes a v0.5.3 production bug where the console halt button updated presence metadata and emitted an audit event, but the SDK enforcement path never read the kill marker. Agents kept running after being "killed." v0.5.4 wires scope.check() through a new presence kill check that fail-closes on operator-killed agents.

Kill switch enforcement (closes v0.5.3 production bug)

  • PresenceModule.is_killed(agent_id) and PresenceModule.assert_alive(agent_id) — read from a 5-second TTL in-memory cache backed by the operator-written kill marker on the presence rownew
  • AgentKilledError — new exception raised by assert_alive() with full kill metadata (operator, timestamp, reason). Inherits from RuntimeError, not from GovernanceError — a bare except ScopeViolation will NOT catch a kill. Catch explicitly with except AgentKilledError if you need to handle the kill in application codenew
  • ScopeModule.set_presence_module(presence) — wired automatically by GovernanceSDK.__init__ when both enable_scope=True and enable_presence=Truenew
  • scope.check() calls presence.assert_alive(agent_id) first — fires before PolicyNotRegistered and before the missing-tool-or-api ValueError. Defense-in-depth ordering verified by testnew
  • PresenceModule.force_refresh_killed_cache() — bypass the 5-second TTL on demand. Used by tests and by future push-based invalidation in v0.6new

Reliability — Invariant #1 preserved under DB outage

  • When the governance database is unreachable, the kill cache holds the last known state and a structlog warning is logged. Already-killed agents stay killed, live agents stay live, and the host application keeps running. The refresh path never raises out to the callernew
  • A failed refresh bumps the cache timestamp so the SDK does not hammer the database during a sustained outagenew
  • Detection uses the operator-written kill marker on the presence row, NOT the status column. The status column is overloaded by stale-heartbeat detection, so gating on it would also block agents that simply went idle. The metadata marker is the unambiguous kill signalnew

Tests

  • 441 → 469 backend tests. New: tests/presence/test_kill_switch.py (28 tests across 7 categories: AgentKilledError construction, happy path, cache TTL behavior including 50-concurrent double-checked locking, Invariant #1 DB outage resilience, in-memory mode, edge cases (unicode IDs, 500-agent scaling, partial metadata, un-kill, idempotent re-kill), and ScopeModule integration with two ordering tests)
  • Wheel build → clean-venv install → smoke test was run against real Postgres before publish (editable installs hide packaging bugs). The full scripts/live_test.py integration harness remains the source of truth for release gating

Scope deferred to v0.6

  • Only scope.check() is patched in v0.5.4. cost.check_budget(), gates.check(), and the LLM wrappers (wrap_anthropic, wrap_openai) still need kill-check wiring — that lands in v0.6 as part of the broader enforcement-path expansion
  • Cache invalidation is TTL-only — worst-case 5-second delay between an operator clicking halt and SDK enforcement. Sub-second invalidation via Postgres LISTEN/NOTIFY is on the v0.6 roadmap
  • No restore endpoint yet. To restore a killed agent, clear the kill marker from the presence row directly. v0.6 ships an admin restore action

Migration

  • Drop-in upgrade from v0.5.3. No schema migration required: kill detection reads from an existing JSONB metadata field that the v0.5.3 console already writes
  • pip install --upgrade code-atelier-governance==0.5.4

v0.5.3

April 13, 2026

Enforcement integrity patch: scope check wired into wrappers, projected budget gate, streaming token tracking, startup wrapper-coverage warning, on-demand HMAC chain verification API, Article 12 report coverage caveat, and a written threat model. Every enforcement surface now gates actions at the wrapper layer.

Enforcement wiring

  • wrap_openai and wrap_anthropic now call sdk.scope.check() with a chat.completions.create / messages.create sentinel before the LLM call — scope enforcement is active at the wrapper layer, not only at the tool-execution layernew
  • Projected budget gate — cost.check_or_raise() now projects forward using the call's declared max_tokens and denies the call before the stream opens if the projected total would exceed the capnew
  • Streaming token tracking — streaming calls record actual usage from the final usage object; fall back to the projected max_tokens ceiling if the API does not return a usage payloadnew
  • warn_on_no_wrappers — structlog warning at sdk.start() when no wrap_openai or wrap_anthropic has been registered. The only startup signal that enforcement is not covering your LLM calls. Default Truenew

Audit — on-demand chain verification

  • await sdk.audit.verify_chain(session_id=None, from_seq=None, to_seq=None) — public API for on-demand HMAC chain verification. Supports partial-range verification. Returns True on a clean chain; raises ChainIntegrityError with the bad sequence number on tampernew
  • verify_chain_on_read SDK config option — when True, verifies the chain on every get_events() call. Default False (O(n) in returned events). Use for compliance reporting or post-incident reviewnew

Compliance — Article 12 report integrity

  • ReportGenerator(audit_module=sdk.audit) — new constructor parameter for wiring the audit module to enable chain verification inside compliance reportsnew
  • generate_article12(verify_chain=True) and generate_summary(verify_chain=True) — new keyword-only parameter runs HMAC chain verification and sets chain_integrity_status to "verified" or "failed" in the report. Raises ValueError immediately if verify_chain=True is requested without an audit_module — no silent degradationnew
  • ComplianceReport.coverage_caveat — new field that always prints the scoping language: "This report covers only actions routed through the SDK wrappers. Actions made via direct LLM client calls are not included."new
  • ComplianceReport.coverage_pct — Pydantic-validated [0.0, 1.0] float or None. Reserved for v0.6 wrapper registry; always None in v0.5.x. The field is always present — its absence would imply 100% coveragenew

Config — opt-in module flags (CLAUDE.md invariant restored)

  • enable_loop (default True) — when False, sdk.loop is not constructed; accessing it raises AttributeError. Emits a structlog sdk.loop_disabled warning at initnew
  • enable_presence (default True) — when False, sdk.presence is not constructed. Emits a structlog sdk.presence_disabled warning at initnew
  • default_max_tokens — default ceiling used by the projected budget gate when the caller does not declare max_tokens on the API call. Suppresses the max_tokens_not_declared warning. Must be >= 1 (enforced by __post_init__)new
  • All module toggles now documented in the README "Configuration Reference" section with module toggles, audit options, wrapper options, and four deployment-pattern examplesnew

Docs — threat model + scoping language

  • New "Threat Model" section in the README documents what the SDK protects against (scope violations, budget overruns, HITL bypass, audit tampering) and what it does NOT protect against (direct client bypass, process-level bypass, streaming cost precision, on-demand tampering detection only, HITL non-blocking mode, tool invocations inside LLM responses)new
  • Positioning tightened across README and docs site — "enforcement gates for every action routed through the SDK" replaces unscoped claims. Article 12 compliance framed as evidence for actions the SDK observednew
  • Removed the "Prompt Versioning" claim from the shipping-feature list. enable_prompts remains as a forward-compat stubnew

Fixes

  • GovernanceSDK.close() now guards self.loop.close() and self.presence.close() with hasattrasync with GovernanceSDK(enable_loop=False) no longer raises AttributeError on teardown
  • _run_chain_verification return type narrowed to ChainIntegrityStatus literal — mypy strict clean across 65 source files
  • scripts/live_test.py switched to AsyncOpenAI (the sync client crashed inside the running event loop)

Tests

  • 436 → 441 backend tests. New: tests/test_v053_edge_cases.py (11 edge cases), partial-range chain verification boundary test, strengthened streaming cost-tracked assertion, 3 tests for close() with disabled modules, 2 tests for generate_article12/generate_summary(verify_chain=True) without audit_module raising ValueError, full end-to-end wrap_anthropic + budget + audit flow
  • 26/26 live integration tests passing against real Postgres and real OpenAI

v0.5.2

April 12, 2026

Console gate workflow hardening: reviewer tracking, batch approve with per-item self-approval blocking, deny rationale in the HMAC chain, halt endpoint, and SSE-backed presence broadcast.

Console - Gate Workflow

  • POST /api/gates/{id}/deny records a rationale in audit metadata so denials are tamper-evident in the HMAC chainnew
  • POST /api/gates/{id}/claim and /escalate track reviewer assignment and hand-offnew
  • POST /api/gates/batch-approve with a 50-request hard cap and per-item self-approval enforcement (one blocked item does not abort the batch)new
  • POST /api/agents/{id}/kill halt endpoint for operatorsnew
  • GET /api/events/stats aggregate counters for the console dashboardnew
  • SSE broadcast layer with session revocation on logoutnew

Database

  • Migration a1b2c3d4e5f6_gates_reviewer_columns adds claimed_by, claimed_at, escalated_to, escalated_at to governance_gates_pendingnew
  • New triggers.sql enforces append-only semantics on the audit log at the DB layernew

Security

  • Deny rationale is stored in application/json responses only — the console never renders user-supplied text as HTML, locked by regression testnew
  • Batch approve has a belt-and-suspenders runtime length guard in addition to the Pydantic field constraintnew
  • Self-approval check called inside the batch loop — an operator cannot approve their own actions in bulknew

Frontend (v4, opt-in via CONSOLE_UI_VERSION)

  • Parallel-route drill panel for the agents listnew
  • mapAgentStatus liveness heuristic with a 15-second idle threshold so dormant agents no longer render as pulsing greennew
  • Stream page pause indicator reflects paused state (disconnected > connecting > paused > connected precedence)new
  • Two-pass error-message sanitizer strips Bearer, token, secret, authorization values before displaynew
  • vitest harness with 34 frontend unit testsnew

Tests

  • 369 backend tests (up from 356), plus 34 vitest cases on the console frontend
  • New multi-agent live integration test (scripts/live_test_multi_agent.py) exercises 6 concurrent agents against real OpenAI, covering scope violation, budget exceeded, HITL contract, and loop detectionnew
  • Posture endpoint status-literal contract locked textually — frontend and backend break loudly on driftnew

v0.5.1

April 12, 2026

Hotfix covering four findings from a DX audit: three activation-consistency bugs and one silent HITL failure on Postgres. No audit data was lost or corrupted.

Security

  • HITL gates silently broken on Postgres. ContractsModule._check_hitl_approved returned False unconditionally for PostgresGatesStore, causing HITL-gated actions to be blocked even after human approval (over-blocking, not bypass). Fix: new GatesStore.has_granted_approval() abstract method with strict agent_id + expiry filtering
  • ScopeModule.filter_tools silently returned the full tool list when no policy was registered, bypassing hidden_tools and contradicting the module's documented default-deny contract. Now raises PolicyNotRegistered; the LangChain handler catches it and fails closed

Breaking changes

  • enable_audit, enable_scope, enable_cost, enable_gates, enable_prompts flags are now honored. In v0.2–v0.5.0 these flags were accepted by GovernanceConfig but never read. Customers setting any of these flags expecting them to disable the corresponding module should review their deployment immediately
  • ScopeModule.filter_tools("unknown_agent", ...) now raises PolicyNotRegistered instead of returning the full tool list

New module - Routing (model selection policy)

  • Advisory sdk.routing.suggest() remaps the requested model based on remaining budget (cost_aware) or explicit rewrite rulesnew
  • Off by default — both enable_routing=True AND a registered RoutingPolicy are requirednew
  • Honors ScopePolicy.allowed_models as a hard constraintnew
  • Emits routing.policy_changed and routing.suggestion audit eventsnew
  • Wraps wrap_openai and wrap_anthropic transparentlynew

Fixes

  • asyncio.run() no longer called from the sync registration path in scope, cost, and routing modules — removes a hidden sync-over-async deadlock risk (invariant #3)
  • Background policy-upsert tasks hold strong references via per-module _pending_upsert_tasks sets
  • ScopePolicy.allowed_models frozen set — a hard ceiling routing cannot exceed

Tests

  • 322 → 356 tests (+21 routing, +13 hotfix regression pins in tests/test_hotfix_v0_5_1.py)

v0.5.0

April 12, 2026

Self-approval prevention, chain fork detection, a sync facade for Flask/Django, and a shared-pool performance sweep that cut Postgres connection count from ~74 to ~15 per SDK.

Security

  • Self-approval prevention (fail-closed) — HITL gates compare the granting operator_id against the session's user_id; an agent cannot approve its own action. DDL adds an operator_id column to the gates tablenew
  • Chain fork detectionaudit.trace_session_chain raises ChainIntegrityError when two events share the same prev_hash, surfacing tamper attempts or concurrent-write corruptionnew
  • New coverage: budget race at the cap boundary, SQL injection payloads on every user-controllable field, case-sensitivity scope bypass, production error leakage via sanitize_db_error, weak-secret entropy rejection, account enumeration parity

New

  • GovernanceSDKSync — sync facade for Flask/Django and any non-async host. Runs an asyncio loop on a background thread and dispatches via run_coroutine_threadsafe. Matches the async SDK surface one-to-onenew
  • SSE endpoint GET /api/stream/events delivers live audit events to the console (session auth, keepalive frames)new
  • Halt agent UI — renamed from "kill" because the SDK blocks gates, it does not terminate the host processnew
  • Multi-agent OpenAI integration test script exercising delegation workloads end to endnew

Performance

  • Shared engine pool — consolidated seven separate AsyncEngine instances into one shared pool per SDK. Dropped Postgres max connections per SDK from ~74 to ~15
  • Concurrent audit writes — pre-call audit log backgrounded, post-call audit + cost tracking run under asyncio.gather, saving 4–12 ms per LLM call on the critical path
  • Combined budget query — session + daily counter reads merged into one round-trip in PostgresCostStore, halving pre-call enforcement latency

Fixes

  • Streaming cost-tracking bypass now detected and logged (users must call sdk.cost.track() manually after consuming the stream)
  • Serverless cold-start policy preload in sdk.start() eliminates the 30-second gap where _policies was empty on first request (AWS Lambda)
  • JSONL audit fallback tolerates read-only filesystems and rotates at 50 MB
  • Session time budget uses Postgres-side elapsed computation to avoid mixed-clock skew
  • Sync wrapper coroutine-leak fix in the Anthropic/OpenAI integrations
  • Policy upsert SQL cast corrected (::jsonbCAST AS jsonb) so scope and budget policies persist across restarts
  • Top-level __init__.py exports ScopePolicy, BudgetPolicy, AuditEvent
  • command_timeout=5 on the shared engine prevents pool exhaustion under slow-query storms

Tests

  • 258 → 322 tests (+64). New suites: streaming detection, JSONL fallback, cold start, sync wrapper, console endpoints, SSE, error handling, SQL injection, case-sensitivity bypass, chain fork detection, end-to-end enforcement. Test suite runs in ~5 s (was ~12 s)

v0.4.0

April 10, 2026

Behavioral contracts for pre/post conditions on tool calls, EU AI Act Article 12 compliance reports, and a native Anthropic SDK adapter with automatic cost tracking.

SDK - Behavioral Contracts (new module)

  • sdk.contracts module with declarative pre/post conditions on tool callsnew
  • PreConditions enforce that budget is available, scope is allowed, or HITL is approved before any tool firesnew
  • PostConditions verify audit was logged after tool executionnew
  • Context manager API: async with sdk.contracts.enforce(agent_id, session_id, tool):new
  • 18 test casesnew

SDK - EU AI Act Article 12 Compliance Reports (new module)

  • Automated compliance evidence reports mapping audit data to the seven sections of Article 12 (binding August 2, 2026)new
  • Three-state status model: compliant, partial, non_compliantnew
  • Privacy-preserving by default - hashes, not raw contentnew
  • Immutable frozen reports for internal compliance reviewnew
  • CLI: governance compliance reportnew
  • 10 test casesnew

Integrations - Anthropic SDK Adapter (new)

  • wrap_anthropic() patches message calls with automatic token trackingnew
  • USD cost estimation using Anthropic pricingnew
  • Audit event generation and budget enforcementnew
  • Async and sync supportnew
  • Idempotent - safe to patch multiple timesnew
  • Install via pip install "code-atelier-governance[anthropic]"new
  • 11 test casesnew

v0.3.0

April 10, 2026

Loop/anomaly detection, agent presence tracking, policy hot-reload, per-model cost aggregation, console GUI overhaul with Code Atelier branding, and security hardening.

SDK — Loop Detection (new module)

  • sdk.loop module with LoopPolicy and LoopDetectednew
  • await sdk.loop.record_call(agent_id, session_id, tool_name) — records tool call and checks for loopsnew
  • await sdk.loop.check(agent_id, session_id) — read-only loop status checknew
  • Sliding-window detection on (session_id, tool_name) pairsnew
  • Tool names normalized to lowercase (case-insensitive detection)new
  • Configurable action: raise (kill the loop) or log (observe only)new
  • Emits loop.detected audit event on detectionnew
  • DDL: governance_loop_tracking tablenew

SDK — Agent Presence (new module)

  • sdk.presence module with heartbeat-based lifecyclenew
  • await sdk.presence.heartbeat(agent_id) — mark agent as Livenew
  • await sdk.presence.mark_idle(agent_id) — transition to Idlenew
  • await sdk.presence.close_agent(agent_id) — remove from presence tablenew
  • await sdk.presence.list_agents() — all agents with statusnew
  • await sdk.presence.check_stale(timeout_seconds=300) — mark unresponsive agentsnew
  • Three states: Live, Idle, Unresponsivenew
  • DDL: governance_agent_presence tablenew

SDK — Policy Hot-Reload

  • GovernanceSDK(hot_reload=True, hot_reload_interval=30) — opt-in policy pollingnew
  • Polls governance_policies table at configurable intervalnew
  • Atomically replaces scope and cost policies in memorynew
  • In-process asyncio task — no background workernew

SDK — Cost Module

  • track_usage() now accepts model= for per-model cost trackingnew
  • await sdk.cost.model_breakdown(agent_id) — per-model cost aggregationnew

Console

  • Code Atelier brand alignment (violet accent, Inter/JetBrains Mono fonts)new
  • Login page with RBAC authenticationnew
  • User management page (admin only)new
  • Loading, empty, and error states on all pagesnew
  • NavBar with admin-only tabsnew
  • GET /api/agents/presence endpoint — agent statusnew
  • GET /api/cost/models endpoint — per-model cost breakdownnew

Security

  • Login rate limiting: 5 attempts per IP per 60 secondsnew
  • Gate audit events now included in HMAC chainnew
  • Metadata size cap: 64KB maximumnew
  • Request model size constraintsnew

CLI

  • governance migrate now includes loop and presence DDLnew

v0.2.2

April 10, 2026

Session time limits, built-in model pricing for 24 models, hidden tool policies, console RBAC authentication, and LangChain hidden tool filtering.

SDK — Cost Module

  • per_session_seconds field on BudgetPolicy — session time limits enforced in check_or_raise()new
  • Built-in pricing table for 24 models (OpenAI, Anthropic, Google, Meta, Mistral)new
  • await sdk.cost.track_usage(agent_id, session_id, model="gpt-4o", input_tokens=N, output_tokens=N) — auto-computes USDnew
  • Prefix matching for versioned model names (gpt-4o-2024-05-13 matches gpt-4o)new
  • Unknown models return $0 (non-breaking)new

SDK — Scope Module

  • hidden_tools field on ScopePolicy — tools removed from LLM context entirelynew
  • sdk.scope.filter_tools(agent_id, tool_list) — removes hidden tools before passing to LLMnew

Console

  • RBAC authentication with PBKDF2-HMAC-SHA256 password hashing (600k iterations, OWASP recommendation)new
  • Postgres-backed sessions with httpOnly cookies (8h TTL, revocation)new
  • Two roles: viewer (read-only) and admin (full access + user management)new
  • API endpoints: POST /api/auth/login, POST /api/auth/logout, GET /api/auth/menew
  • Admin endpoints: GET/POST /api/auth/users, PATCH /api/auth/users/{id}, DELETE /api/auth/sessions/{id}new

Integrations

  • LangChain handler: hidden tool filtering in on_llm_start (enforcement mode)new
  • OpenAI wrapper: auto USD via built-in pricing tablenew
  • OpenAI wrapper: double-wrap sentinel warns and returns if client already wrappednew

CLI

  • governance console add-user / list-users / disable-user / reset-password commandsnew
  • governance migrate now includes console DDL (auth tables)new

v0.2.1

April 10, 2026

Enforcement mode for LangChain, fail-closed cost gates by default, durable JSONL fallback, and a major Console upgrade with Grant/Deny buttons, event detail panel, and inline violation details.

SDK

  • LangChain handler enforce=True mode — scope enforcement through callbacksnew
  • wrap_openai double-wrap sentinel — calling it twice is now idempotentnew
  • model as first-class field on AuditEvent (included in the HMAC chain)new
  • Policies persisted to governance_policies Postgres tablenew
  • JSONL durable fallback — audit events survive process crashesnew
  • Weak secret rejection (minimum 8 unique bytes)new

Console

  • Grant/Deny buttons on pending approvalsnew
  • Event detail slide-out panel (full HMAC, prev_hash links, verify button)new
  • Inline violation details on posture cardsnew
  • Real Live/Idle status badge (no longer hardcoded)new
  • Recursive metadata redaction (nested PII stripped)new
  • Events page pagination (25/50/100 per page)new
  • CORS wildcard rejectionnew
  • Posture query performance bounds (LIMIT on all sub-queries)new

CLI

  • governance migrate --dry-run flagnew
  • Improved error messages for invalid UUIDsnew

Security

  • Fail-closed cost gate by defaultnew
  • Console auth warning for dev modenew

Docs

  • Fixed "5 lines" hero claimnew
  • Blue to violet design token consistency on sub-pagesnew
  • Quickstart split into SDK-only + Console sectionsnew
  • HMAC diagram field-coverage clarificationnew

v0.2.0

April 10, 2026

Initial public release of the Governance SDK with all four enforcement modules and the read-only Governance Console.

SDK

  • LangChain BaseCallbackHandler adapter
  • OpenAI SDK wrap_openai adapter
  • OpenTelemetry GenAI exporter
  • Multi-process correctness via Postgres advisory locks
  • HMAC-chained tamper-evident audit trail
  • Scope enforcement (tool/API whitelisting)
  • Spend limits with fail-closed budget gates
  • Human-in-the-loop signed approval tokens

Console

  • Initial release of the Governance Console (read-only dashboard)

CLI

  • governance CLI with migrate, verify, tail, and budget commands