Skip to content

Commit ade5f30

Browse files
authored
fix(governance)!: complete outstanding v3.0.0 breaking changes (#88)
* feat(governance): reject non-finite values at ingress and stpa Extend defence-in-depth for IEEE-754 NaN/inf bypass (follow-up to PR #86): - TradeOrder: add math.isfinite guards to validate_positive (amount) and validate_confidence; NaN silently passed validate_positive because nan <= 0 is False. - ValidateActionRequest / ToolExecutionRequest: add field_validator that rejects non-finite floats in the params dict at the HTTP boundary. - stpa_compiler.py generate_python: add less_than operator branches (threshold_ref and literal) with identical math.isfinite fail-closed guards; emit import math in the generated validator template. - New test file test_ingress_nan_rejection.py covering all three ingress models; less_than finiteness tests added to test_stpa_compiler.py. * fix: resolve CI failures for sbom, lint, and obsolete tests * test: fix mock signature in cbf rollback test * feat(compliance): implement 5-part proof structure for refusal receipts * feat(governance): add JWKS multi-key support and AGW envelope builder - Add JWKSet class with thread-safe caching and key rotation (Finding #9) - Add /governance/jwks endpoint for external verifiers - Implement AGW envelope builder with RFC 8785 canonicalization (Finding #10) - Add sign_archytan_digest() for direct pre-hashed signing - Integrate JWKS lookup in verify_seal() with fallback to signer key - Refactor GFA routing_seal to re-export from gateway module - Add HMAC downgrade guard for production environment - Add comprehensive test suites for JWKS and envelope features * fix(governance)!: complete outstanding v3.0.0 breaking changes BREAKING CHANGE: Remove AGWEnvelope/AGWEnvelopeBuilder deprecated aliases, sign_archytan_digest() method, and create_ftra_node() deprecated kwargs. - Delete src/gateway/governance/agw_envelope.py module - Delete tests/test_agw_envelope.py - Remove sign_archytan_digest() from KMSSigner (use sign() instead) - Remove registry_path/plan_key kwargs from create_ftra_node() - Fix KMS_BATCH_ENABLED documentation (default is false) - Update CHANGELOG.md and docs/BREAKING_CHANGES_v3.md
1 parent 5afd017 commit ade5f30

36 files changed

Lines changed: 3943 additions & 1176 deletions

.trivyignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,3 +68,4 @@ CVE-2026-8286
6868
CVE-2026-8376
6969
CVE-2026-8927
7070
CVE-2026-9538
71+
CVE-2026-14456

AGENTS.md

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -260,23 +260,6 @@ When modifying STPA source files:
260260

261261
## Architecture & Design Standards
262262

263-
### Shared-Module Cross-Region Impact
264-
265-
The following modules deploy simultaneously to all three regional postures
266-
(`US_FED`, `EU_ECB`, `APAC_MAS`):
267-
268-
- `src/gateway/governance/`
269-
- `src/compliance_bridge/`
270-
- `config/compliance/`
271-
- `config/thresholds/`
272-
- `config/oscal/`
273-
274-
For any change to these paths, call out in the PR description:
275-
1. Impact on US_FED posture (NIST SP 800-53)
276-
2. Impact on EU_ECB posture (GDPR / EU AI Act / DORA)
277-
3. Impact on APAC_MAS posture (MAS FEAT / MAS Notice 655 / MAS TRM)
278-
4. `CAGE_DEPLOYMENT_REGION` guard placement for any new data path
279-
280263
### Release Versioning
281264

282265
- Releases follow SemVer (`MAJOR.MINOR.PATCH`).
@@ -303,10 +286,6 @@ documents rather than paraphrasing from memory:
303286
| POAM tracking | [`docs/POAM.md`](docs/POAM.md) |
304287

305288
When explaining compliance posture or security controls:
306-
- Distinguish clearly between universal gates (ISO 42001) and regional gates
307-
(US_FED / EU_ECB / APAC_MAS); regional gates block regional deployment only.
308-
- `CAGE_DEPLOYMENT_REGION` guards are required for any new data path in
309-
shared modules (see [Architecture & Design Standards](#architecture--design-standards)).
310289
- CAGE is a reference architecture — clarify that region gates and deployment
311290
promotion rules are illustrative patterns, not operational obligations for
312291
this repository.

CHANGELOG.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,32 +41,62 @@ Versions follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
4141

4242
## [3.0.0] - 2026-08-15
4343

44+
> **Corrected release:** v3.0.0 was initially tagged 2026-08-15 with four
45+
> breaking changes still outstanding. Those changes were completed
46+
> post-tag on branch `fix/v3-breaking-changes-completion` and are now
47+
> reflected below: the `AGWEnvelope`/`AGWEnvelopeBuilder` removal, the
48+
> `sign_archytan_digest()` removal, the `create_ftra_node()` deprecated-kwargs
49+
> removal (kwargs fully removed, not merely deprecated), and the
50+
> `KMS_BATCH_ENABLED` default-value discrepancy (resolved as `"false"`). See
51+
> [`docs/BREAKING_CHANGES_v3.md`](docs/BREAKING_CHANGES_v3.md) for full detail.
52+
4453
### Breaking Changes
4554
- Removed `stpa_validator.py` shim module — use `GeneratedSTPAValidator` directly
4655
- Removed `safety.py` re-export shim — import from `text_filter` and `cbf` directly
4756
- Removed `GovernanceClient`, `RedisClient`, `HybridClient` aliases
4857
- Removed `check_safety_constraints` legacy tool alias — use `simulate_governance_check`
49-
- Removed `create_ftra_node()` deprecated params (`registry_path`, `plan_key`)
58+
- Removed `create_ftra_node()` deprecated params (`registry_path`, `plan_key`) — kwargs no longer accepted; pass a `FtraNodeConfig` instance instead
5059
- Removed `CONTROL_META`, `EVIDENCE_SLA_SECONDS`, `ISO_CONTROL_MAP` aliases — use region-aware accessors
5160
- Removed `config/settings.py` module-level aliases — use `Config.X` class attributes
5261
- Migrated threshold env vars to `config/governance_thresholds.json` (env vars still work as overrides)
5362
- (CR-1) Removed Evidence Stream v1.0 schema support — v1.1 is now the only supported schema
5463
- (CR-2) Removed NeMo auto-apply path (`NEMO_AUTO_APPLY_ENABLED`) — all refinements require human approval
5564
- (CR-3) Renamed `update_state()``_update_state_unsafe()` — use `atomic_verify_and_commit()` instead
65+
- Removed `AGWEnvelope`/`AGWEnvelopeBuilder` backward-compatibility aliases (`src/gateway/governance/agw_envelope.py`, entire file deleted) — use `GovernanceEnvelope`/`GovernanceEnvelopeBuilder` from `src/gateway/governance/governance_envelope.py`
66+
- Removed `sign_archytan_digest()` method from `KMSSigner` (`src/gateway/governance/kms_signer.py`) — use `sign()` instead
5667

5768
### Added
5869
- `config/governance_thresholds.json` v2.0.0 schema with FRIA, confidence, and causal thresholds
5970
- Threshold accessor functions in `src/gateway/governance/schemas/thresholds.py`
6071
- Region-aware control metadata accessors (`get_control_meta()`, `get_sla_seconds()`, `get_iso_control_map()`)
6172

73+
### Removed
74+
- `src/gateway/governance/agw_envelope.py` (entire file) — `AGWEnvelope` and `AGWEnvelopeBuilder` backward-compatibility aliases; use `GovernanceEnvelope`/`GovernanceEnvelopeBuilder` from `src/gateway/governance/governance_envelope.py`
75+
- `tests/test_agw_envelope.py` — backward-compatibility test suite for the removed `AGWEnvelope`/`AGWEnvelopeBuilder` aliases; see `tests/test_governance_envelope.py` for canonical coverage
76+
- `sign_archytan_digest()` method from `KMSSigner` (`src/gateway/governance/kms_signer.py`) — use `sign()` instead
77+
- `create_ftra_node()` deprecated `registry_path`/`plan_key` keyword arguments (`src/gateway/governance/ftra/node_factory.py`) — fully removed, not just deprecated; pass a `FtraNodeConfig` instance instead
78+
6279
### Changed
6380
- `FtraNodeConfig` is now required for `create_ftra_node()` (no fallback extractors)
6481
- Threshold values loaded from config file with env var overrides
6582
- `SafetyBoundaryProtocol` no longer exposes `update_state()` method
6683

84+
### Fixed
85+
- `KMS_BATCH_ENABLED` default-value discrepancy (Wave 0) resolved: confirmed default is `"false"` (disabled), matching `KmsBatchThresholds.enabled` in `src/gateway/governance/schemas/thresholds.py` and `config/governance_thresholds.json`. **Note:** the startup log comment in `src/compliance_bridge/main.py` (near line 213) still states the default is `"true"` and requires a follow-up code fix to align with the verified `"false"` default.
86+
6787
### Migration
6888
See [MIGRATION_GUIDE_v3.md](docs/MIGRATION_GUIDE_v3.md) for detailed upgrade instructions.
6989

90+
Example migration for the `AGWEnvelope` removal:
91+
92+
```python
93+
# Old (removed in v3.0.0):
94+
from src.gateway.governance.agw_envelope import AGWEnvelope
95+
96+
# New (required):
97+
from src.gateway.governance.governance_envelope import GovernanceEnvelope
98+
```
99+
70100
---
71101

72102
## [2.1.2] - 2026-08-13

docs/BREAKING_CHANGES_v3.md

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
11
# CAGE v3.0.0 Breaking Changes
22

3-
> **Status:** Released — v3.0.0 shipped 2026-08-15. See
3+
> **Status:** Corrected release. v3.0.0 was initially tagged 2026-08-15 with
4+
> four breaking changes still outstanding (see below); those changes were
5+
> completed on branch `fix/v3-breaking-changes-completion` and this document
6+
> has been updated to reflect what was actually removed. See
47
> [`CHANGELOG.md`](../CHANGELOG.md) for the full release notes. This document
58
> describes the breaking changes included in this release. Item IDs (`SR-#`,
69
> `MR-#`, `CR-#`, `FF-#`, `EV-#`) match
710
> [`docs/MAJOR_VERSION_CLEANUP_PLAN.md`](MAJOR_VERSION_CLEANUP_PLAN.md) 1:1
811
> so the two documents can be cross-referenced.
12+
>
13+
> **Post-tag corrections (this update):** `AGWEnvelope`/`AGWEnvelopeBuilder`
14+
> removal was missing from this document entirely; `sign_archytan_digest()`
15+
> removal was missing from the Removed Classes/Functions table; the
16+
> `KMS_BATCH_ENABLED` discrepancy flagged in the original release notes is
17+
> now resolved (default confirmed as `"false"`, not `"true"` — see
18+
> [Feature Flags Graduated](#feature-flags-graduated)).
919
1020
## Overview
1121

@@ -49,6 +59,7 @@ behavior change in `v3.0.0`.
4959
|--------|-------------|-----------|
5060
| [`src/gateway/governance/stpa_validator.py`](../src/gateway/governance/stpa_validator.py) (`STPAValidator` class) | [`src/gateway/governance/generated_stpa_validator.py`](../src/gateway/governance/generated_stpa_validator.py:38) (`GeneratedSTPAValidator`) | Replace `from src.gateway.governance.stpa_validator import STPAValidator` with `from src.gateway.governance.generated_stpa_validator import GeneratedSTPAValidator`; replace `.validate(action_name, params)` calls with `.validate_generated(action_name, params)`. |
5161
| [`src/gateway/governance/safety.py`](../src/gateway/governance/safety.py) (entire file) | [`src/gateway/governance/text_filter.py`](../src/gateway/governance/text_filter.py) (`ac_keyword_scan`); [`src/gateway/governance/cbf.py`](../src/gateway/governance/cbf.py) (`ControlBarrierFunction`, `safety_filter`) | Replace `from src.gateway.governance.safety import ac_keyword_scan` with `from src.gateway.governance.text_filter import ac_keyword_scan`; replace `from src.gateway.governance.safety import ControlBarrierFunction, safety_filter` with `from src.gateway.governance.cbf import ControlBarrierFunction, safety_filter`. |
62+
| `src/gateway/governance/agw_envelope.py` (entire file — `AGWEnvelope`, `AGWEnvelopeBuilder` backward-compatibility aliases) | [`src/gateway/governance/governance_envelope.py`](../src/gateway/governance/governance_envelope.py) (`GovernanceEnvelope`, `GovernanceEnvelopeBuilder`) | Replace `from src.gateway.governance.agw_envelope import AGWEnvelope` with `from src.gateway.governance.governance_envelope import GovernanceEnvelope`; replace `AGWEnvelopeBuilder` with `GovernanceEnvelopeBuilder` (same module). `tests/test_agw_envelope.py` (the backward-compatibility test suite for these aliases) is also deleted — see [`tests/test_governance_envelope.py`](../tests/test_governance_envelope.py) for the canonical coverage. **(Completed post-tag, `fix/v3-breaking-changes-completion`.)** |
5263

5364
### Removed Classes/Functions
5465

@@ -63,6 +74,7 @@ behavior change in `v3.0.0`.
6374
| `EVIDENCE_SLA_SECONDS` (module-level dict alias) | [`src/compliance_bridge/types.py:446`](../src/compliance_bridge/types.py:446) | `get_sla_seconds(region)` | Replace direct dict access with `get_sla_seconds(region)`. Same universal-only → region-merged behavior note as `CONTROL_META` applies. |
6475
| `ISO_CONTROL_MAP` (module-level dict alias — **two distinct symbols**) | [`src/compliance_bridge/types.py:512`](../src/compliance_bridge/types.py:512) **and** [`src/gateway/governance/ontology.py:197-234`](../src/gateway/governance/ontology.py:197) (`TradingKnowledgeGraph.ISO_CONTROL_MAP` class attribute) | `get_iso_control_map(region)` (types.py); `get_control_map(region)` (ontology.py) | These are **two unrelated symbols with the same name in two different modules** — migrate each independently. `src/compliance_bridge/types.py` callers use `get_iso_control_map(region)`; `TradingKnowledgeGraph` callers use `get_control_map(region)`. |
6576
| `update_state()` (public API) | [`src/gateway/governance/cbf.py:907-998`](../src/gateway/governance/cbf.py:907) | `atomic_verify_and_commit()` (same module) | **Completed (CR-3)**: `update_state()` was renamed to `_update_state_unsafe()` (internal-only) to eliminate TOCTOU race conditions. External callers must call `atomic_verify_and_commit()`, which performs the CBF safety check and state commit atomically within a single Redis Lua execution. |
77+
| `sign_archytan_digest()` (method) | [`src/gateway/governance/kms_signer.py`](../src/gateway/governance/kms_signer.py) (`KMSSigner` class) | `sign()` (same class) | Replace `kms_signer.sign_archytan_digest(digest)` with `kms_signer.sign(payload)`; `sign()` is the canonical signing entry point and covers the same code path. **(Completed post-tag, `fix/v3-breaking-changes-completion`.)** |
6678

6779
### Removed Endpoints
6880

@@ -118,7 +130,7 @@ corresponding module is migrated; use the config file instead.
118130
| Flag | New Behavior |
119131
|------|--------------|
120132
| `CAGE_DEFER_ENABLED` | **Not graduated in v3.0.0** (explicit recommendation in the cleanup plan §2.4). The flag remains, still defaulting to `"true"`. If your deployment currently sets this to `"false"` to force the DENY-fallback path, that behavior is **unchanged** in v3.0.0. This is a deliberate deviation from the "graduate stable flags" theme of this release — flagged here so consumers do not assume removal. |
121-
| `KMS_BATCH_ENABLED` | **Status uncertain pending Wave 0 discrepancy resolution.** [`kms_batch_signer.py:75`](../src/compliance_bridge/kms_batch_signer.py:75) currently defaults this to `"true"`; [`main.py:211-212`](../src/compliance_bridge/main.py:211)'s comment claims the production default is `"false"`. **Do not assume this flag is graduated to any particular value until the CAGE release notes for your specific `v3.0.0` build confirm the resolved default.** If graduated, the flag is hardcoded and the `KMS_BATCH_ENABLED` env var (see above) is removed. |
133+
| `KMS_BATCH_ENABLED` | **Resolved.** The Wave 0 discrepancy is closed: the confirmed default is `"false"` (disabled), matching [`KmsBatchThresholds.enabled`](../src/gateway/governance/schemas/thresholds.py:277) (`Field(default=False, ...)`) and [`config/governance_thresholds.json`](../config/governance_thresholds.json:56) (`"enabled": false`). The flag is **not graduated**`KMS_BATCH_ENABLED` remains a valid env-var override of the config default via `get_kms_batch_enabled()`. **Known documentation debt (not yet code-fixed):** the startup comment at [`main.py:213`](../src/compliance_bridge/main.py:213) still incorrectly states "The signer is enabled by default (kms_batch.enabled=true..." — this comment is stale and requires a follow-up code change (out of scope for this documentation-only correction) to align with the verified `false` default. |
122134

123135
---
124136

0 commit comments

Comments
 (0)