Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,79 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- **Phase 9.6 — `sovereign-sdk-airlock` outbound governance boundary** (new workspace
member `packages/sovereign-airlock/`): Introduces the model-neutral Airlock
lifecycle boundary that inspects, evaluates, minimises, and records structured
payloads before they cross a sovereign perimeter (SAR-0004).

- **`NormalizedPayload` frozen dataclass** (`payload.py`): Provider-neutral
inspection surface extracted from any transport-specific request format.
Factory functions `normalize_openai()`, `normalize_anthropic()`, and
`normalize_raw()` translate protocol-specific schemas into the stable governance
surface without leaking transport state.

- **`AirlockTelemetry` frozen dataclass** (`telemetry.py`): Four Component C sieve
metrics (`raw_tokens`, `sieved_tokens`, `tax_savings_percentage`, `payload_hash`).
`from_sieve_output()` classmethod includes an explicit `raw_tokens == 0` guard
defaulting `tax_savings_percentage` to `0.0`, preventing ZeroDivisionError on
zero-token or null-pass payloads.

- **`PolicyEngine(config_path)`** (`policy.py`): Deterministic, fully offline YAML
rule evaluator supporting `raw`, `fields`, and `telemetry` evaluation scopes with
`allow`, `warn`, and `deny` actions. Global `max_token_ceiling` and
`prose_tax_warning_threshold` configuration. `AirlockConfigurationError` raised
on malformed, structurally invalid, or regex-invalid configuration. All regex
patterns pre-compiled via `re.compile()` at init time; malformed patterns raise
`AirlockConfigurationError` immediately rather than deferring to a runtime
`re.error`. `_VALID_METRICS` frozenset (`raw_tokens`, `sieved_tokens`,
`tax_savings_percentage`) validated in `_parse_rule` at boot time; unrecognised
metric names (e.g. typo `raw_token`) raise `AirlockConfigurationError` immediately.
`prose_tax_warning_threshold` validated to `[0.0, 1.0]` in `__init__`; values
outside this range raise `AirlockConfigurationError`. `PolicyRule.fields` stored
as `tuple[str, ...]` (immutable; previously `list[str]`). `_POST_SIEVE_METRICS`
frozenset (`sieved_tokens`, `tax_savings_percentage`) guards `_evaluate_telemetry`:
when `telemetry=None`, post-sieve metrics are skipped rather than proxied via
`payload.token_estimate`. `evaluate_post_sieve(telemetry)` evaluates post-sieve-only
telemetry rules and the prose tax threshold; returns a `PolicyVerdict` that may carry
`deny` violations.

- **`NormalizedPayload` deep immutability** (`payload.py`): `__post_init__` converts
`content` to `tuple[str, ...]`, `metadata` to `types.MappingProxyType[str, Any]`,
and each `tools` entry to `types.MappingProxyType[str, Any]`. Constructor still
accepts mutable `list`/`dict` equivalents; conversion is transparent to all
factory functions.

- **`ReceiptBuilder(key_manager, ledger)`** (`receipt.py`): Assembles boundary
crossing metadata and produces a signed `ForensicReceipt` via
`SovereignKeyManager.generate_receipt()`. Ledger write failure is non-fatal —
a `WARNING` log is emitted and the receipt is returned regardless, so outbound
transmission is never blocked by a storage-tier anomaly.

- **`AirlockBoundary(policy_path, signing_key, ledger)`** (`boundary.py`):
Async orchestrator implementing the four-component transaction lifecycle. `deny`
verdict raises `AirlockPolicyViolation` before any sieve or ledger operation.
Post-sieve evaluation via `PolicyEngine.evaluate_post_sieve(telemetry)`: deny verdicts
raise `AirlockPolicyViolation`; warn verdicts are appended to `verdict.warnings` and
sealed in receipt metadata.

- **76-case test suite** across `test_policy.py` (29), `test_telemetry.py` (12),
`test_receipts.py` (10), and `test_boundary.py` (25). Round 1 PR remediation adds
7 cases: `test_raises_on_malformed_regex_pattern` (`TestPolicyLoading`),
`TestProseTaxThreshold` (2 cases), and `TestNormalizedPayloadImmutability` (4 cases).
Round 3 PR remediation adds 7 cases: `test_sieved_tokens_rule_skipped_when_telemetry_absent`,
`test_tax_savings_rule_skipped_when_telemetry_absent`, `test_evaluate_post_sieve_fires_sieved_tokens_warn_rule`,
`test_evaluate_post_sieve_deny_rule_returns_violation`, `test_policy_rule_fields_is_immutable_tuple`,
`test_negative_savings_clamped_to_zero`, and `test_post_sieve_telemetry_deny_raises_policy_violation`.
Round 4 PR remediation adds 3 cases: `test_raises_on_unknown_telemetry_metric`,
`test_raises_on_out_of_bounds_prose_tax_threshold`, and
`test_over_optimized_savings_clamped_to_hundred`.
**76 passed, 0 failed (airlock); 486 passed, 1 skipped (workspace).**

- **`AirlockTelemetry.tax_savings_percentage` full clamp** (`telemetry.py`):
`max(0.0, min(100.0, round(...)))` applied to the savings calculation in
`from_sieve_output()`. Content expansion (sieved > raw) clamps to `0.0`; impossible
inversion (negative `optimized_token_count`) clamps to `100.0`.

- **Phase 9.5 — `sovereign-edge` sensor ingestion bridge** (new workspace member
`packages/sovereign-edge/`): Introduces the middleware pipeline that intercepts
sealed sensor wire frames from `sovereign-sensor`, applies the `sovereign-sieve`
Expand Down
14 changes: 14 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,17 @@ Before declaring an engineering task or phase update complete, you must execute

- `commit-message.txt` generation: At the conclusion of a successful test execution pass, generate a pristine, technical Git commit message following Conventional Commits (e.g., `feat(ledger): implement hash-chained append-only storage engine`). Write this text directly into `commit-message.txt` at the root directory. Do not execute the git commit command yourself.
- `uv` Workspace Compliance: After altering dependencies or adding new workspace members, always run `uv lock` to keep the monorepo's dependency layout completely verified and synchronized.


## Architectural Governance & Spec Invariants (SAR)

All code generations, component implementations, and workspace modifications must strictly conform to the Sovereign Systems Specification Architecture Records (SARs) located under `architecture/receipts/`.

### Core Technical Constraints:
1. **SAR-0004 (Containment Boundaries):** Components sitting at perimeter intersections (e.g., `sovereign-airlock`) must act as strict, deliberate inspection and containment zones—never transparent or routing proxies.
2. **SAR-0007 (Zero External Network Footprint):** Third-party runtime dependencies must be lightweight, non-ML, and non-transitive. Execution must be locked entirely to local machine silicon with zero cloud-mediated API requirements for validation.
3. **SAR-0009 (Fault-Tolerant Logging):** Ledger writes, signature logging, and evidence commits are explicitly non-fatal to outbound communication lifecycles. Storage-tier faults must emit a warning locally and fail open safely to prevent crashing agent runtimes.
4. **SAR-0010 (Vocabulary Mapping):** All exposed classes, errors, objects, and types must mapped strictly from terms declared in the established Specification Glossary (`AirlockBoundary`, `NormalizedPayload`, etc.).

### Pre-Flight Verification Rule:
Before initiating code modifications for any core module, the model must read `planning_docs/active_plans` for active blueprints, verify its execution loop against the relevant governing SAR files, and trace the directional dependency graph (upstream packages must remain entirely isolated from downstream orchestrators).
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,21 @@ This repository is managed as an integrated `uv` workspace separating the crypto
│ │ └── tests/
│ │ └── test_edge.py
│ │
│ ├── sovereign-airlock/ # Outbound governance boundary (SAR-0004)
│ │ ├── src/sovereign_airlock/
│ │ │ ├── boundary.py # AirlockBoundary — async 4-component orchestrator
│ │ │ ├── payload.py # NormalizedPayload — provider-neutral inspection surface
│ │ │ ├── policy.py # PolicyEngine — YAML rule evaluation (raw/fields/telemetry)
│ │ │ ├── telemetry.py # AirlockTelemetry — sieve convergence metrics
│ │ │ ├── receipt.py # ReceiptBuilder — evidence assembly and ledger commit
│ │ │ ├── exception.py # AirlockPolicyViolation, AirlockConfigurationError
│ │ │ └── __init__.py
│ │ └── tests/
│ │ ├── test_boundary.py
│ │ ├── test_policy.py
│ │ ├── test_receipts.py
│ │ └── test_telemetry.py
│ │
│ ├── sovereign-runtime/ # Compute/Execution tier (tool & model isolation)
│ │ └── src/sovereign_runtime/
│ │ ├── router.py # Intent-based pre-flight namespace exposure
Expand Down Expand Up @@ -215,6 +230,44 @@ Three fortification properties are enforced at the architecture level:

---

## `sovereign-sdk-airlock` — Outbound Governance Boundary

For applications and agentic runtimes that must govern what leaves the sovereign perimeter,
`sovereign-sdk-airlock` provides the deliberate inspection and containment boundary defined
by SAR-0004 (Airlock, Not Gateway):

```python
import asyncio
from sovereign_ledger import SovereignLedger
from sovereign_airlock import AirlockBoundary, AirlockPolicyViolation, normalize_openai

ledger = SovereignLedger(".keys/sovereign_audit.db")
boundary = AirlockBoundary(
policy_path="policy.yaml",
signing_key=".keys/",
ledger=ledger,
)

try:
result = await boundary.process(normalize_openai(request))
# result.sieved_content — minimised payload ready for transmission
# result.telemetry.payload_hash — SHA-256 of the raw pre-sieve content
# result.receipt["signature"] — Ed25519 boundary crossing evidence
# result.policy_warnings — non-fatal warn-rule messages
except AirlockPolicyViolation as exc:
# Payload blocked by a deny rule — do not transmit
raise
```

Policy rules are declared in a local YAML file and evaluated in three scopes:
- `raw` — regex pattern matched against the flat combined content string
- `fields` — pattern matched against named structured fields (`messages.content`, `tools.description`, etc.)
- `telemetry` — numeric threshold applied to `raw_tokens`, `sieved_tokens`, or `tax_savings_percentage`

Airlock is transport-agnostic. `normalize_openai()`, `normalize_anthropic()`, and `normalize_raw()` convert any request format into the provider-neutral `NormalizedPayload` before governance evaluation begins.

---

## `sovereign-sensor` — Bare-Metal Write-Side Custody

For IoT and embedded systems where data must be sealed cryptographically at the exact point of genesis — before any network hop or cloud ingestion — `sovereign-sensor` provides a MicroPython-compatible Hardware Abstraction Layer that runs on ESP32 and Raspberry Pi Pico with zero external dependencies:
Expand Down
92 changes: 92 additions & 0 deletions ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -1225,6 +1225,98 @@ committed = pipeline.drain_buffer()

---

## Phase 9.6 — Outbound Governance Boundary (`sovereign-sdk-airlock`) — Shipped ✓

**Target:** Introduce the model-neutral outbound governance boundary that inspects,
evaluates, minimises, and records structured payloads before they cross a sovereign
perimeter and enter an external computational system. Implements the four-component
Airlock lifecycle defined in SAR-0004 (Airlock, Not Gateway).

```python
import asyncio
from sovereign_ledger import SovereignLedger
from sovereign_airlock import AirlockBoundary, normalize_openai

ledger = SovereignLedger(".keys/sovereign_audit.db")
boundary = AirlockBoundary(
policy_path="policy.yaml",
signing_key=".keys/",
ledger=ledger,
)

result = await boundary.process(normalize_openai(request))
# result.sieved_content — Prose-Tax-minimised payload for transmission
# result.telemetry.payload_hash — SHA-256 of the raw pre-sieve content
# result.receipt["signature"] — Ed25519 boundary crossing evidence
# result.policy_warnings — non-fatal warn-rule messages
```

**Delivered:**

* [x] `NormalizedPayload` frozen dataclass (`payload.py`) — provider-neutral inspection
surface with `source`, `content`, `metadata`, `tools`, and `token_estimate` fields;
factory functions `normalize_openai()`, `normalize_anthropic()`, and `normalize_raw()`
translate transport-specific request schemas to the common governance surface
* [x] `AirlockTelemetry` frozen dataclass (`telemetry.py`) — four Component C sieve
metrics (`raw_tokens`, `sieved_tokens`, `tax_savings_percentage`, `payload_hash`);
`from_sieve_output()` classmethod re-derives `tax_savings_percentage` independently
of `SieveOutput` with an explicit `raw_tokens == 0` guard and full
`max(0.0, min(100.0, ...))` clamp enforcing the documented `[0.0, 100.0]` range
* [x] `PolicyEngine(config_path)` (`policy.py`) — deterministic, offline YAML rule
evaluator supporting `raw` (regex over flat content), `fields` (dot-notation field
extraction), and `telemetry` (numeric metric threshold) scopes; actions `allow`,
`warn`, `deny`; global `max_token_ceiling` check; `AirlockConfigurationError` on
invalid YAML, unrecognised scope/action values, unrecognised telemetry metric names
(validated at boot against `_VALID_METRICS`), or `prose_tax_warning_threshold` outside
`[0.0, 1.0]`; `_POST_SIEVE_METRICS` frozenset gates pre-sieve evaluation so
`sieved_tokens` and `tax_savings_percentage` rules are never proxied against
`token_estimate`; `evaluate_post_sieve(telemetry)` evaluates those metrics against
actual sieve output and applies the prose tax threshold check, returning a
`PolicyVerdict` that can carry `deny` violations
* [x] `PolicyRule` and `PolicyVerdict` frozen and mutable dataclasses (`policy.py`) —
immutable rule descriptor (`fields` stored as `tuple[str, ...]`) and mutable evaluation
result carrying `allowed`, `violations`, and `warnings` lists
* [x] `ReceiptBuilder(key_manager, ledger)` (`receipt.py`) — assembles boundary
crossing metadata (`boundary`, `source_transport`, `prose_tax_summary`,
`policy_warnings`), signs via `SovereignKeyManager.generate_receipt()`, and commits
to `SovereignLedger.append_receipt()`; ledger write failure emits `WARNING`-level
log and returns the receipt regardless — outbound transmission is never blocked
* [x] `AirlockBoundary(policy_path, signing_key, ledger)` (`boundary.py`) — async
orchestrator implementing the four-component transaction lifecycle: policy evaluation
→ sieve convergence → post-sieve telemetry evaluation → evidence generation; pre-sieve
`deny` verdict raises `AirlockPolicyViolation` immediately; post-sieve
`evaluate_post_sieve()` deny verdict also raises `AirlockPolicyViolation`; receipt
generation failure is non-fatal (logged, `receipt=None` in result)
* [x] `AirlockResult` dataclass (`boundary.py`) — structured result carrying
`sieved_content`, `telemetry`, `receipt`, and `policy_warnings`
* [x] `AirlockPolicyViolation(RuntimeError)` and `AirlockConfigurationError(ValueError)`
(`exception.py`) — domain exceptions for deny-action enforcement and configuration
invariant violations respectively
* [x] `packages/sovereign-airlock/pyproject.toml` — workspace member at version
`1.4.0`; runtime dependencies: `sovereign-sdk-core>=1.3.0`,
`sovereign-sdk-ledger>=1.3.0`, `sovereign-sdk-sieve>=1.3.0`, `pyyaml>=6.0`
* [x] 76-case test suite across four files (`TestAirlockTelemetry`: 12;
`TestPolicyLoading` + `TestRawScopeEvaluation` + `TestFieldsScopeEvaluation` +
`TestTelemetryScopeEvaluation` + `TestGlobalCeiling`: 29; `TestReceiptBuilder`: 10;
`TestAirlockBoundaryHappyPath` + `TestAirlockBoundaryPolicyDenial` +
`TestAirlockBoundaryPolicyWarning` + `TestAirlockBoundaryTransportNeutrality` +
`TestAirlockBoundaryResiliency` + `TestProseTaxThreshold` +
`TestNormalizedPayloadImmutability`: 25) covering frozen telemetry dataclass
immutability, zero-token ZeroDivisionError guard, full `[0.0, 100.0]` savings clamp,
payload hash derivation, YAML config loading, all three rule scopes, all three
policy actions, global ceiling enforcement, regex boot-time compilation with
`AirlockConfigurationError` on malformed patterns, boot-time telemetry metric name
validation, `prose_tax_warning_threshold` range validation `[0.0, 1.0]`, pre-sieve
metric skip guard, post-sieve `evaluate_post_sieve()` deny/warn evaluation,
`PolicyRule.fields` tuple immutability, prose tax threshold warning lifecycle,
deep payload immutability (`tuple` + `MappingProxyType`), receipt metadata invariants,
cryptographic verifiability, non-fatal ledger write failure, transport-neutral
normalisation (OpenAI, Anthropic, raw), deny/warn/allow lifecycle correctness, and
full async `AirlockBoundary.process()` transaction lifecycle end-to-end.
**76 passed, 0 failed (airlock); 486 passed, 1 skipped (workspace).**

---

## Phase 10 — Isolated Context Vault & Governance Server (`sovereign-vault`)

**Target:** Implement the "Sovereign Vault" architecture as an isolated local orchestration
Expand Down
Loading
Loading