feat(casan): establish assurance kernel and harden control plane
This commit is contained in:
@@ -0,0 +1,141 @@
|
||||
# CASAN Assurance Kernel
|
||||
|
||||
Status: implemented contract layer, version `1.0.0` (2026-08-02).
|
||||
|
||||
## Purpose and maturity
|
||||
|
||||
CASAN now has a framework-independent wire contract and deterministic policy
|
||||
primitives outside the native Bash topology. The native harness remains
|
||||
operational and is the first compatibility adapter; the Agentic Bridge is the
|
||||
second adapter. This is an incremental extraction, not a rewrite of H1–H7.
|
||||
|
||||
CASAN may describe this layer as an **Assurance Kernel contract and policy
|
||||
foundation with two conforming adapters**. It must not claim that every legacy
|
||||
loop, graph, report, or third-party runtime has migrated to the kernel.
|
||||
|
||||
## Boundary
|
||||
|
||||
```text
|
||||
Execution runtime
|
||||
-> runtime adapter
|
||||
-> canonical Assurance Kernel envelope
|
||||
-> deterministic policy / verification / evidence services
|
||||
-> runtime-specific enforcement mechanisms
|
||||
```
|
||||
|
||||
The kernel does not execute models. It does not infer security decisions from
|
||||
model output. Runtime-specific data is allowed only under a namespace such as
|
||||
`casan.runtime.casan-native-harness` or `casan.runtime.agentic-bridge`.
|
||||
|
||||
## Canonical contract
|
||||
|
||||
The canonical source is
|
||||
`packages/casan-harness/schemas/assurance-kernel.schema.json`. It is JSON Schema
|
||||
Draft 2020-12 and uses `schema_version: 1.0.0`.
|
||||
|
||||
The envelope defines:
|
||||
|
||||
- `ExecutionRun`: identity, parent, scope, environment, runtime, mode, goal,
|
||||
timestamps, status, risk summary, evidence manifest and correlation.
|
||||
- `ExecutionStep`: causal position, actor/action/resource, context references,
|
||||
policy decisions, tool invocation, verification, evidence and outcome.
|
||||
- `Actor`: human, agent, child agent, model, tool, service account, runtime,
|
||||
approver or policy engine with issuer, trust and authentication evidence.
|
||||
- `Delegation`: authority, resource scope, expiry, maximum depth, parent,
|
||||
revocation and approval.
|
||||
- `ContextItem`: origin, trust, content hash, transforms, compression lineage,
|
||||
instruction/data classification and injection scan.
|
||||
- `Action` and `ResourceAccess`: canonical class, operation, authority,
|
||||
side-effect level, resource and environment.
|
||||
- `PolicyDecision`: versioned policy, structured decision, reason codes, risk
|
||||
facts, enforcement point, engine identity, time and evidence reference.
|
||||
- `RuntimeConstraint` and `RuntimeCapabilities`: honest limits and supported
|
||||
cancellation/intervention mechanisms.
|
||||
- `VerificationRequirement` and `VerificationResult`: expected versus actual
|
||||
result, evidence, independence and failure severity.
|
||||
- `Claim`, `EvidenceItem` and `TraceLink`: bidirectional claim support,
|
||||
integrity metadata, producer, artifact, validation, retention and typed links.
|
||||
- `Approval` and `Intervention`: explicit decisions and runtime support status.
|
||||
- `Outcome`: four independent results for execution, assurance,
|
||||
certification and business effect.
|
||||
|
||||
## Deterministic kernel services
|
||||
|
||||
The stdlib-only Python implementation is under
|
||||
`packages/casan-harness/kernel/`.
|
||||
|
||||
`policy.py` provides:
|
||||
|
||||
- Machine-readable action classification from
|
||||
`config/action-classes.json`.
|
||||
- Effective risk as the maximum of content, action, resource, identity and
|
||||
environment risk.
|
||||
- H2 registry configuration validation and fail-closed dependency decisions.
|
||||
- Single-step failure-policy selection with `halt`, `quarantine`,
|
||||
`require_approval` and `record_only`.
|
||||
- Production trust capability evaluation.
|
||||
|
||||
`contracts.py` provides builders and an enforcement-boundary verifier. The
|
||||
verifier rejects unsupported schema versions, invalid actor/step references,
|
||||
observed-only certification, broken claim/evidence links, evidence digest
|
||||
tampering, delegation cycles and excess delegation depth.
|
||||
|
||||
`taxonomy.py` separates `RuntimeControl.Hn`, `ReadinessCheck.Hn`,
|
||||
`ReportDimension.Hn` and `CertificationClaim.Hn`. A legacy `Hn` remains a
|
||||
display alias only and never authorizes cross-category interpretation.
|
||||
|
||||
`supervision.py` negotiates interventions against declared runtime
|
||||
capabilities. Unsupported pause, rollback, cancellation, authority reduction
|
||||
or quarantine returns `unsupported`; it never reports a fictitious success.
|
||||
|
||||
## Action policy
|
||||
|
||||
The action registry includes read, write, delete, database mutation,
|
||||
migration, deployment, release, credential access, identity/permission change,
|
||||
external network side effect, infrastructure modification and unknown actions.
|
||||
|
||||
High-impact actions have a high minimum risk, require an identified actor,
|
||||
explicit approval and evidence. Benign text cannot reduce that floor. Unknown
|
||||
shell operations also fail toward high risk. H2 registry enforcement and H5
|
||||
approval remain separate defense-in-depth decisions.
|
||||
|
||||
## Outcome semantics
|
||||
|
||||
The following states are deliberately distinct:
|
||||
|
||||
```text
|
||||
execution_result = success | failed | cancelled | quarantined | ...
|
||||
assurance_result = passed | failed | degraded | not_evaluated | ...
|
||||
certification_result = certified | non_certified | ineligible | ...
|
||||
business_result = achieved | not_achieved | partial | not_evaluated | ...
|
||||
```
|
||||
|
||||
A telemetry append can succeed while `execution_result=failed`. A failed
|
||||
side-effecting command defaults to `halt` in enforce/production mode and cannot
|
||||
produce a successful completion or normal certification.
|
||||
|
||||
## Evidence integrity and trust
|
||||
|
||||
Canonical evidence metadata is linked to claims and carries a SHA-256 digest.
|
||||
This detects local mutation and broken references. It is not, by itself, an
|
||||
external trust root or WORM guarantee. Production certification separately
|
||||
requires external signing and an external immutable anchor.
|
||||
|
||||
## Compatibility rules
|
||||
|
||||
- New envelopes use semantic version `1.0.0`; incompatible schema changes
|
||||
require a new major version.
|
||||
- Additive runtime fields belong under a namespaced `extensions` object.
|
||||
- The native and Agentic Bridge formats remain readable and are dual-emitted
|
||||
with canonical envelopes during migration.
|
||||
- Legacy evidence is not silently reinterpreted as kernel-validated evidence.
|
||||
- Observe-mode and unsafe-development-bypass runs are never certified.
|
||||
- Audit chain format v1 remains verifiable while new records use v2 fields.
|
||||
|
||||
## Claims and residual limits
|
||||
|
||||
CASAN can claim deterministic shared action policy, canonical execution and
|
||||
evidence contracts, and cross-runtime conformance for the native harness and
|
||||
Agentic Bridge. It cannot yet claim universal runtime adoption, complete
|
||||
multi-runtime supervision, external infrastructure availability, or
|
||||
data-backed H1–H7 dossiers beyond the reports actually backed by evidence.
|
||||
@@ -0,0 +1,113 @@
|
||||
# CASAN Control Plane
|
||||
|
||||
Status: production-capable packaged authentication and trust configuration;
|
||||
external infrastructure remains operator-provisioned.
|
||||
|
||||
## Deployment modes
|
||||
|
||||
### Local development
|
||||
|
||||
- Default bind: `127.0.0.1`.
|
||||
- `CASAN_CP_AUTH_MODE=local` is allowed only on loopback and outside production.
|
||||
- Local actor headers are explicitly development identity and are not a
|
||||
production authentication claim.
|
||||
|
||||
### Networked or production
|
||||
|
||||
- `CASAN_CP_AUTH_MODE=jwt` is mandatory.
|
||||
- Production requires RS256 verification, a mounted public key, exact issuer
|
||||
and audience, and a clock skew from 0 through 300 seconds.
|
||||
- Missing or invalid configuration refuses startup before NestJS listens.
|
||||
- HS256 is retained only for deterministic non-production tests.
|
||||
|
||||
## Packaged identity boundary
|
||||
|
||||
```text
|
||||
Browser
|
||||
-> enterprise OIDC
|
||||
-> oauth2-proxy session
|
||||
-> Nginx auth_request
|
||||
removes X-CASAN-* and forwarded identity headers
|
||||
forwards signed Bearer access token
|
||||
-> NestJS AuthProvider
|
||||
verifies RS256 signature, iss, aud, sub, exp, nbf and iat
|
||||
-> VerifiedClaims
|
||||
-> CASAN RBAC role mapping and scoped request identity
|
||||
```
|
||||
|
||||
Nginx is a TLS/session boundary, not the identity authority for the API. The
|
||||
API ignores caller-supplied identity assertions and derives actor, role,
|
||||
tenant and project only after token verification.
|
||||
|
||||
## Authentication implementation
|
||||
|
||||
`backend/src/common/auth-provider.ts` defines:
|
||||
|
||||
- `AuthProvider` and `JwtAuthProvider`.
|
||||
- Typed `VerifiedClaims` and `AuthenticationDecision`.
|
||||
- RS256/HS256 signature verification using Node's standard crypto APIs.
|
||||
- Issuer, audience, expiry, not-before, issued-at and bounded-skew checks.
|
||||
- Safe tenant/project syntax validation.
|
||||
- Structured authentication audit evidence without raw tokens.
|
||||
- Middleware that overwrites request identity only from verified claims.
|
||||
|
||||
`auth-context.ts` refuses direct header use in JWT mode unless the middleware
|
||||
has marked the identity verified. Existing RBAC services then map verified
|
||||
groups and continue to produce governance/authorization evidence.
|
||||
|
||||
## Production configuration
|
||||
|
||||
Required runtime variables:
|
||||
|
||||
```text
|
||||
CASAN_PROFILE=prod
|
||||
CASAN_CP_AUTH_MODE=jwt
|
||||
CASAN_CP_JWT_ISSUER=https://...
|
||||
CASAN_CP_JWT_AUDIENCE=...
|
||||
CASAN_CP_JWT_PUBLIC_KEY_FILE=/run/casan-idp/idp-public.pem
|
||||
CASAN_CP_JWT_ROLE_CLAIM=groups
|
||||
CASAN_CP_JWT_TENANT_CLAIM=casan_tenant
|
||||
CASAN_CP_JWT_PROJECT_CLAIM=casan_project
|
||||
CASAN_CP_JWT_CLOCK_SKEW_SECONDS=60
|
||||
```
|
||||
|
||||
The host path is configured as `CASAN_CP_IDP_PUBLIC_KEY` and mounted read-only.
|
||||
oauth2-proxy must set xauthrequest output and pass the access token. Images for
|
||||
API, UI and oauth2-proxy must be digest-pinned.
|
||||
|
||||
`production-preflight.sh` validates:
|
||||
|
||||
- TLS hostname, expiry and matching private key.
|
||||
- IdP public key readability and RSA public-key format.
|
||||
- HTTPS OIDC issuer, secure cookies and token forwarding.
|
||||
- Matching oauth2-proxy client ID and API audience.
|
||||
- Matching issuer and bounded JWT clock skew.
|
||||
- External Vault/KMS signing and S3 Object Lock provider selection.
|
||||
- Live short-lived non-root Vault token lookup.
|
||||
- A real Object Lock COMPLIANCE anchor write.
|
||||
- Digest-pinned images and valid Compose/Nginx configuration.
|
||||
|
||||
## Authentication evidence
|
||||
|
||||
Each production authentication decision appends a JSONL record under
|
||||
`CASAN_STATE_ROOT/logs/auth/decisions.jsonl` with category, policy, decision,
|
||||
reason, actor, issuer, scope and request method/path. Tokens and secrets are
|
||||
never written. A failure to authenticate returns HTTP 401 with a stable reason
|
||||
code; it is not converted to viewer access.
|
||||
|
||||
## Local production-like smoke
|
||||
|
||||
`docker-compose.control-panel.local.yml` uses the same bearer-token path. The
|
||||
smoke script generates an ephemeral RSA keypair, mounts the private key into
|
||||
the mock IdP and the public key into the API, and enables token forwarding.
|
||||
This validates the boundary without treating the mock IdP as production.
|
||||
|
||||
## Residual limitations
|
||||
|
||||
- Public-key rotation currently requires replacing the mounted key and
|
||||
restarting the API; automated JWKS discovery and rollover are not present.
|
||||
- Enterprise IdP, managed TLS, Vault and S3 are not provisioned by the repo.
|
||||
- Local tests validate crypto and provider contracts, but do not prove a real
|
||||
tenant's claim mapping, token lifecycle, network policy or key rotation.
|
||||
- The Control Plane is production-capable for this packaged deployment model;
|
||||
it is not yet a universal multi-runtime scheduler or supervisor.
|
||||
@@ -0,0 +1,95 @@
|
||||
# CASAN Execution Adapters
|
||||
|
||||
## Adapter contract
|
||||
|
||||
An execution adapter translates runtime events into the canonical Assurance
|
||||
Kernel envelope without replacing H2, H4, H5 or other existing controls.
|
||||
|
||||
```text
|
||||
runtime event
|
||||
-> adapter mapping
|
||||
-> ExecutionRun / ExecutionStep / Actor / Action
|
||||
-> PolicyDecision / VerificationResult / EvidenceItem / Outcome
|
||||
-> common verifier
|
||||
```
|
||||
|
||||
Adapter code lives in `packages/casan-harness/kernel/adapters.py`. The canonical
|
||||
schema and policy code must not import a native runtime.
|
||||
|
||||
## Native harness adapter
|
||||
|
||||
`NativeHarnessAdapter` maps the Bash harness execution identity, action,
|
||||
command, actor, environment, policy decisions, evidence and final outcome. The
|
||||
native entrypoint in `scripts/bash/casan-harness.sh` continues to emit its
|
||||
existing metrics and completion protocol while atomically writing a canonical
|
||||
bundle to `CASAN_STATE_ROOT/logs/kernel/`.
|
||||
|
||||
If a phase exits non-zero, the harness best-effort emits a canonical failed
|
||||
bundle before propagating the original exit code. This emission never masks
|
||||
the command failure. A successful run reports execution, assurance and
|
||||
certification separately.
|
||||
|
||||
The adapter is compatibility code: existing H gates remain the enforcement
|
||||
implementation. The kernel does not duplicate them.
|
||||
|
||||
## Agentic Bridge adapter
|
||||
|
||||
`AgenticBridgeAdapter` maps lifecycle admission, pre-tool, post-tool, telemetry
|
||||
and finalize events. The bridge now:
|
||||
|
||||
- Uses the shared action classifier and risk floors.
|
||||
- Defaults H2 registry enforcement on in enforce mode.
|
||||
- Converts missing, unreadable, timed-out, malformed or failed H2 dependencies
|
||||
into structured policy decisions.
|
||||
- Distinguishes failed tool outcome from successful telemetry recording.
|
||||
- Applies the single-step failure policy.
|
||||
- Restricts certification using enforcement mode, assurance strength and trust
|
||||
capability.
|
||||
- Dual-emits the canonical bundle alongside its v20 lifecycle records.
|
||||
|
||||
The Agentic Bridge remains a single-model integration: it performs admission,
|
||||
policy, evidence and finalization but does not invoke a model itself.
|
||||
|
||||
## Cross-runtime conformance
|
||||
|
||||
`tests/assurance-kernel-tests.py` runs the same invariants through both
|
||||
adapters. It proves:
|
||||
|
||||
1. Dangerous action classification is identical.
|
||||
2. Missing actor identity denies the same high-impact action.
|
||||
3. Missing H2 enforcement denies in enforce mode.
|
||||
4. Approval and evidence requirements are identical.
|
||||
5. Claim/evidence relationships use the same contract.
|
||||
6. Observed-only execution cannot be certified.
|
||||
7. Execution, assurance and certification outcomes remain distinct.
|
||||
8. Correlation and parent causation are preserved.
|
||||
9. The same verifier detects evidence tampering.
|
||||
10. Runtime details are namespaced extensions rather than kernel assumptions.
|
||||
|
||||
The conformance suite currently covers two paths. A future adapter must pass
|
||||
the same suite before being described as kernel-conforming.
|
||||
|
||||
## Capability negotiation
|
||||
|
||||
Adapters declare `canCancel`, `canPause`, `canResume`, `canRollback`,
|
||||
`canReduceAuthority` and `canQuarantine`. These are conservative. The native
|
||||
harness currently declares no general asynchronous intervention capability;
|
||||
the Agentic Bridge declares quarantine support only where its lifecycle can
|
||||
represent it. Unsupported interventions return an explicit result.
|
||||
|
||||
## Adding an adapter
|
||||
|
||||
1. Preserve the runtime's existing security controls.
|
||||
2. Map stable run, step, actor, correlation and causation identities.
|
||||
3. Use the shared action policy; do not create a weaker parallel classifier.
|
||||
4. Emit policy decisions and evidence references, not boolean-only results.
|
||||
5. Put runtime-only fields in `casan.runtime.<adapter>` extensions.
|
||||
6. Validate with `validate_bundle` and the JSON Schema.
|
||||
7. Add the full cross-runtime invariant matrix.
|
||||
8. Do not mark legacy or observe-only records certified.
|
||||
|
||||
## Residual migration scope
|
||||
|
||||
Custom loop runners, graphs and every historical event producer have not been
|
||||
rewritten. They may continue using legacy formats, but they cannot inherit
|
||||
kernel-conformance claims until they receive an adapter and pass conformance.
|
||||
@@ -0,0 +1,109 @@
|
||||
# CASAN Trust Boundaries
|
||||
|
||||
## Trust model
|
||||
|
||||
CASAN separates enforcement, evidence, identity, execution isolation and
|
||||
external trust. Passing one boundary never implies that another passed.
|
||||
|
||||
| Boundary | Development/local | Production/strict |
|
||||
|---|---|---|
|
||||
| Control Plane identity | Explicit loopback local identity | In-process RS256 JWT verification required |
|
||||
| H2 tool authority | Enforce defaults on; explicit bypass is high-severity/non-certifiable | Enforce on; bypass configuration rejected |
|
||||
| H5 high-impact action | Approval and actor required by action floor | Strict signed approval plus external trust requirements |
|
||||
| Tool isolation | Static fallback only when explicitly enabled in dev/test | Container isolation required; unavailable backend denies |
|
||||
| Audit signing | Local OpenSSL permitted and labelled local | Vault/KMS external signing required |
|
||||
| Immutable anchor | Local hash chain permitted and labelled local | External Object Lock/WORM provider required |
|
||||
| Certification | Local/observed limitations disclosed | Unsafe fallback or emergency override cannot normally certify |
|
||||
|
||||
## H2 enforcement dependency
|
||||
|
||||
H2 returns a structured `PolicyDecision`, never a boolean-only decision. Missing
|
||||
file, unreadable file, timeout, malformed protocol, missing runtime and internal
|
||||
execution errors have stable reason codes. In enforce mode all dependency
|
||||
errors deny. In observe mode the operation may be observed, but assurance is
|
||||
degraded and certification is forbidden.
|
||||
|
||||
Registry enforcement defaults on for side-effecting native and Agentic Bridge
|
||||
paths. `CASAN_H2_REGISTRY=0` or `CASAN_AGENTIC_H2_REGISTRY=0` is an explicit
|
||||
unsafe development/test bypass. Production treats the bypass as invalid.
|
||||
|
||||
## H5 governance and action risk
|
||||
|
||||
`config/action-classes.json` is the common policy source. Effective risk is the
|
||||
maximum of content, action, resource, identity and environment factors.
|
||||
Deployment, release, migration, database mutation, delete,
|
||||
identity/permission modification and infrastructure modification cannot be
|
||||
downgraded by benign wording. Credential access and unknown commands are also
|
||||
high-risk. High-impact operations require actor identity, approval and
|
||||
evidence.
|
||||
|
||||
Production governance requires strict approval and external signing/anchor
|
||||
capability. Governance audit format v2 binds action class, risk factors and
|
||||
evidence requirements into the hash. The verifier continues to recognize
|
||||
legacy v1 records without upgrading their claims.
|
||||
|
||||
## Execution isolation
|
||||
|
||||
`sandbox-run.sh` detects its selected capability and writes structured sandbox
|
||||
evidence. In enforce/production mode a side-effecting path requires the
|
||||
container backend. If Docker or the required backend is unavailable, execution
|
||||
is denied with `sandbox_isolation_backend_unavailable`; there is no silent
|
||||
timeout/static fallback.
|
||||
|
||||
The implemented container contract uses:
|
||||
|
||||
- Read-only root filesystem.
|
||||
- Explicit workspace bind mount as the writable scope.
|
||||
- Network disabled by default.
|
||||
- Non-root container user.
|
||||
- Dropped Linux capabilities and `no-new-privileges`.
|
||||
- PID, memory, CPU and timeout limits.
|
||||
- Restricted working directory and filtered environment.
|
||||
- Output-size and exit-code capture at the harness boundary.
|
||||
- Rootless Docker requirement in production.
|
||||
|
||||
CASAN does not claim AppArmor, SELinux, a custom seccomp profile, per-domain
|
||||
network allowlisting or complete host isolation where those mechanisms are not
|
||||
configured. Development static fallback is policy filtering, not isolation.
|
||||
|
||||
## Control Plane identity boundary
|
||||
|
||||
Arbitrary `X-CASAN-*`, `X-Forwarded-User` and similar headers are untrusted.
|
||||
Nginx removes them, oauth2-proxy provides a signed access token, and the API
|
||||
verifies the token before creating `VerifiedClaims`. A non-loopback local mode
|
||||
or an invalid production verifier refuses startup.
|
||||
|
||||
## Signing and immutable evidence boundary
|
||||
|
||||
Local SHA-256 chains and evidence digests provide tamper detection under the
|
||||
local host's trust. They are not externally trusted immutability. Normal
|
||||
production certification requires both:
|
||||
|
||||
1. `CASAN_SIGNING_PROVIDER=vault_kms` (or another explicitly supported external
|
||||
trust provider) with an HTTPS endpoint and short-lived credential.
|
||||
2. `CASAN_IMMUTABLE_ANCHOR_PROVIDER=s3_object_lock` (or an explicitly supported
|
||||
external WORM provider) with bucket and KMS configuration.
|
||||
|
||||
The packaged production path verifies Vault Transit readiness and performs an
|
||||
S3 Object Lock COMPLIANCE anchor write. It does not provision either service.
|
||||
|
||||
`CASAN_TRUST_EMERGENCY_OVERRIDE=1` is break-glass behavior. It emits critical
|
||||
evidence, keeps readiness failed and makes the run non-certifiable. It is not a
|
||||
normal production fallback.
|
||||
|
||||
## Secret and evidence handling
|
||||
|
||||
- Raw JWTs and authentication secrets are not logged.
|
||||
- Tool and prompt evidence remains subject to existing redaction/scanning.
|
||||
- Authentication evidence records identity metadata and stable reason codes.
|
||||
- Canonical evidence digests detect local metadata tampering, while external
|
||||
signing/anchoring supplies production trust.
|
||||
- A successful evidence append never changes a failed execution into success.
|
||||
|
||||
## Infrastructure not proven by repository tests
|
||||
|
||||
Repository-local tests use cryptographic fixtures and narrow service stubs.
|
||||
Docker isolation tests are skip-aware when Docker is absent. Real enterprise
|
||||
OIDC traffic, Vault policy enforcement, KMS/HSM custody, S3 retention policy,
|
||||
rootless Docker host hardening and managed network controls require deployment
|
||||
evidence before production claims are made.
|
||||
@@ -0,0 +1,221 @@
|
||||
# Assurance Kernel and Control Plane Upgrade — Implementation Log
|
||||
|
||||
Date: 2026-08-02
|
||||
|
||||
## Executive implementation result
|
||||
|
||||
All seven P0 items and all five requested P1 items were implemented with
|
||||
targeted regression coverage. The native harness remains operational. The
|
||||
Assurance Kernel now has a versioned canonical contract, deterministic shared
|
||||
policy, a native adapter, an Agentic Bridge adapter and a 10-invariant
|
||||
cross-runtime conformance suite. The Control Plane packages in-process RS256
|
||||
identity verification and refuses unsafe network startup.
|
||||
|
||||
P2 was intentionally limited: taxonomy and runtime capability negotiation were
|
||||
implemented, but new H4/H5/H2 report dossiers were not represented as
|
||||
data-backed because the shared evidence-query migration was not safe to finish
|
||||
within this change.
|
||||
|
||||
## Verified pre-existing behavior
|
||||
|
||||
- H4 already blocked injection/secrets before model execution.
|
||||
- The agent bridge already denied sensitive pre-tool adapter failures in many
|
||||
paths and disclosed observed-only degradation.
|
||||
- The native harness already propagated command exit status; the misleading
|
||||
completion gap was primarily in Agentic Bridge finalize semantics, where a
|
||||
later `Stop(completed)` could obscure a failed tool.
|
||||
- Container isolation already implemented read-only root, no network,
|
||||
non-root execution, capability dropping and resource bounds.
|
||||
- Production preflight already checked live Vault/S3 prerequisites, and
|
||||
`sign-audit-head.sh` already refused local fallback for `CASAN_PROFILE=prod`.
|
||||
- H6 already had a data-backed report and operational test suite; other report
|
||||
dimensions remained `contract_ready`.
|
||||
- H5 strict signed approval, separation of duties and OIDC approval fixtures
|
||||
already existed.
|
||||
|
||||
## Verified gaps
|
||||
|
||||
- Agentic H2 returned allow when the gate script was absent.
|
||||
- Agentic registry enforcement defaulted off.
|
||||
- H5 risk followed text risk, allowing benign deployment text to avoid the
|
||||
inherent action floor.
|
||||
- Agentic telemetry and finalization did not model failed execution separately
|
||||
enough to prevent misleading successful completion.
|
||||
- `sandbox-run.sh` could silently fall back to weaker timeout/static behavior.
|
||||
- Control Plane identity trusted forwarded identity headers when a flag was set.
|
||||
- Production governance/certification did not uniformly require both external
|
||||
signing and immutable anchoring capabilities.
|
||||
- No stable canonical execution contract or two-runtime conformance suite
|
||||
existed.
|
||||
- H1–H7 categories were structurally ambiguous.
|
||||
|
||||
## Code changed in this task
|
||||
|
||||
### P0.1 — H2 missing-gate behavior
|
||||
|
||||
Selected implementation: `evaluate_h2_gate` returns a structured
|
||||
`PolicyDecision` with stable reason codes. Missing file, permission denial,
|
||||
timeout, malformed response and internal exception deny in enforce mode.
|
||||
Observe mode yields `observe_only`, degraded and non-certifiable evidence.
|
||||
|
||||
Proof: kernel unit tests and Agentic Bridge integration tests cover every error
|
||||
class and both modes.
|
||||
|
||||
Residual: external shell gates remain a runtime dependency; the change makes
|
||||
dependency failure honest and safe rather than eliminating it.
|
||||
|
||||
### P0.2 — registry defaults
|
||||
|
||||
Selected implementation: both side-effecting native and Agentic Bridge paths
|
||||
use shared configuration validation and default registry enforcement on.
|
||||
Development/test bypass is explicit, high-severity and non-certifiable;
|
||||
production bypass is invalid.
|
||||
|
||||
Proof: unit, bridge integration and legacy Agentic Bridge suites.
|
||||
|
||||
### P0.3 — action-class risk floors
|
||||
|
||||
Selected implementation: `config/action-classes.json` is the deterministic
|
||||
source. Effective risk is the maximum of five factors. H5 governance and both
|
||||
adapters consume it; high-impact actions require actor, approval and evidence.
|
||||
|
||||
Proof: benign deployment regression in unit, bridge and shell integration
|
||||
tests. Existing H5 strict approval remains 12/12.
|
||||
|
||||
### P0.4 — single-step failure semantics
|
||||
|
||||
Selected implementation: kernel failure-policy selection plus bridge
|
||||
post-tool/finalize changes. Execution failure, telemetry recording, assurance
|
||||
continuation and certification are separate. Production side-effect
|
||||
`record_only` is rejected. Native phase failure emits a failed canonical bundle
|
||||
and preserves the original non-zero exit.
|
||||
|
||||
Proof: all four policy values, invalid/production configuration, Agentic failed
|
||||
write and native exit-7 regressions.
|
||||
|
||||
### P0.5 — isolation fallback
|
||||
|
||||
Selected implementation: enforce/production chooses container isolation and
|
||||
denies when unavailable. Static fallback requires an explicit dev/test flag.
|
||||
Capability evidence discloses the actual backend. Production requires a
|
||||
digest-pinned image and rootless Docker.
|
||||
|
||||
Proof: unavailable-backend and explicit-development-fallback tests. Existing
|
||||
container escape tests are present but were skipped locally because Docker was
|
||||
unavailable.
|
||||
|
||||
### P0.6 — Control Plane identity
|
||||
|
||||
Selected implementation: typed `AuthProvider`, RS256 JWT verification,
|
||||
`VerifiedClaims`, safe scope checks, audit evidence, header overwrite and
|
||||
startup validation. Nginx passes only the access token after removing identity
|
||||
headers. Production preflight verifies the packaged boundary.
|
||||
|
||||
Proof: missing/invalid/expired/wrong-audience/wrong-issuer tests, valid RS256,
|
||||
header spoofing and production startup refusal. Backend has 57 passing tests.
|
||||
|
||||
Residual: mounted static public key requires coordinated restart for rotation;
|
||||
JWKS discovery/automatic rollover is not yet implemented.
|
||||
|
||||
### P0.7 — trust-root enforcement
|
||||
|
||||
Selected implementation: shared capability evaluation, governance enforcement,
|
||||
Vault signing, Object Lock anchoring and certification restrictions. Production
|
||||
local fallback is refused. Emergency override is critical, readiness-failing
|
||||
and non-certifiable.
|
||||
|
||||
Proof: unit, bridge, shell and production configuration tests.
|
||||
|
||||
Residual: real Vault/KMS and S3 are customer infrastructure and were not
|
||||
provisioned or contacted in this local run.
|
||||
|
||||
### P1 — contract and adapters
|
||||
|
||||
Selected implementation: JSON Schema `1.0.0`, Python builders/verifier,
|
||||
namespaced extensions, dual emission, native compatibility adapter and Agentic
|
||||
Bridge adapter. Evidence integrity and bidirectional claim links use one
|
||||
verifier. Delegation depth/cycles are validated.
|
||||
|
||||
Proof: 30 kernel/unit/conformance tests, including the exact 10 cross-runtime
|
||||
invariants and evidence tampering.
|
||||
|
||||
### P1 — H taxonomy
|
||||
|
||||
Selected implementation: separate typed namespaces for runtime controls,
|
||||
readiness checks, report dimensions and certification claims. Structured
|
||||
readiness, report and certification evidence now includes a category/type.
|
||||
Legacy `Hn` remains a display mapping only.
|
||||
|
||||
Proof: cross-category unit test and additive Control Plane report tests.
|
||||
|
||||
### Limited P2 — runtime supervision
|
||||
|
||||
Selected implementation: conservative runtime capabilities and intervention
|
||||
negotiation. Unsupported actions are explicit, not silently successful.
|
||||
|
||||
Residual: no general scheduler, durable supervisor state, cross-process cancel,
|
||||
pause/resume implementation, budget service or rollback engine was added.
|
||||
|
||||
## Tests added
|
||||
|
||||
- `assurance-kernel-tests.py`: 30 unit and conformance tests.
|
||||
- `assurance-upgrade-integration-tests.py`: 7 Agentic Bridge integration tests.
|
||||
- `phase-assurance-upgrade-tests.sh`: 11 shell integration groups.
|
||||
- `auth-provider.test.ts`: JWT and production identity tests.
|
||||
- Existing auth-context/report tests extended for spoofing and taxonomy.
|
||||
- Production preflight tests extended to a full valid contract plus audience,
|
||||
local trust and missing-key failures.
|
||||
|
||||
## Verification results
|
||||
|
||||
| Suite | Result |
|
||||
|---|---:|
|
||||
| Kernel unit + two-adapter conformance | 30/30 pass |
|
||||
| Draft 2020-12 JSON Schema validation | pass for both adapters |
|
||||
| Agentic upgrade integration | 7/7 pass |
|
||||
| Assurance upgrade shell integration | 11/11 pass |
|
||||
| Existing Agentic Bridge acceptance/threat suite | 42/42 pass |
|
||||
| Control Plane backend | 57/57 pass |
|
||||
| Control Plane backend TypeScript build | pass |
|
||||
| Control Plane frontend typecheck/Vite build | pass |
|
||||
| Existing H5 approval identity | 12/12 pass |
|
||||
| Sandbox isolation suite | 8/8 accounted; live Docker cases skipped |
|
||||
| Production handoff | 8/8 pass |
|
||||
| Existing H6 AgentOps | 20/20 pass |
|
||||
| Readiness compatibility | 5/5 pass |
|
||||
| Production and local Compose config | pass |
|
||||
|
||||
Legacy suites that generated tracked audit/dashboard output were run with
|
||||
temporary state where supported; known generated artifacts were restored after
|
||||
verification. Existing user-owned `docs/evidence/` was not modified.
|
||||
|
||||
## Infrastructure-dependent work not possible locally
|
||||
|
||||
- Live rootless Docker isolation and network/filesystem escape tests.
|
||||
- Enterprise IdP login and real key-rotation behavior.
|
||||
- Live Vault Transit signing against a managed policy/token.
|
||||
- Live S3 Object Lock retention and organization SCP/IAM enforcement.
|
||||
- Managed TLS/DNS and external endpoint smoke.
|
||||
|
||||
The provider interfaces, fail-closed validation and deterministic local
|
||||
contract tests are implemented for each missing dependency.
|
||||
|
||||
## Remaining gaps
|
||||
|
||||
- H4/H5/H2 and remaining H1/H3/H7 dossiers still need a shared canonical
|
||||
evidence-query implementation before `contract_ready` can be removed.
|
||||
- Static RS256 key mount lacks JWKS rollover.
|
||||
- Kernel adoption is proven for two adapters, not every loop/graph/runtime.
|
||||
- Runtime supervision is capability negotiation, not a full durable supervisor.
|
||||
- External trust and production host hardening require deployment evidence.
|
||||
- Cross-runtime policy-bundle distribution and remote adapter admission are not
|
||||
yet centralized by the Control Plane.
|
||||
|
||||
## Current maturity and honest claims
|
||||
|
||||
After this change, CASAN is a strong assurance-enabled harness with an
|
||||
implemented framework-independent Assurance Kernel foundation and a packaged,
|
||||
production-capable Control Plane boundary. Framework independence is proven for
|
||||
two adapters under the canonical contract. Full platform-wide kernel adoption,
|
||||
universal supervision, complete dossiers and provisioned external trust remain
|
||||
future work.
|
||||
@@ -0,0 +1,126 @@
|
||||
# CASAN Assurance Kernel Migration
|
||||
|
||||
## Scope
|
||||
|
||||
This migration preserves existing native and Agentic Bridge protocols while
|
||||
adding canonical kernel envelopes and changing unsafe defaults. It is designed
|
||||
for incremental adoption; no big-bang H1–H7 rewrite is required.
|
||||
|
||||
## Behavior changes
|
||||
|
||||
1. H2 registry enforcement defaults on in enforce mode.
|
||||
2. A missing or failed H2 dependency denies in enforce mode.
|
||||
3. High-impact action classes use deterministic risk floors and require actor,
|
||||
approval and evidence.
|
||||
4. Failed side-effecting single-step execution defaults to halt in enforce or
|
||||
production mode.
|
||||
5. Enforce/production sandbox execution refuses timeout/static-only fallback.
|
||||
6. Networked/production Control Plane startup requires verified JWT identity;
|
||||
`CASAN_CP_TRUST_AUTH_PROXY` no longer authorizes header trust.
|
||||
7. Production certification requires an external signing provider and external
|
||||
immutable anchor.
|
||||
8. Canonical schema `1.0.0` is dual-emitted with legacy runtime records.
|
||||
|
||||
## Development migration
|
||||
|
||||
Existing loopback development works with:
|
||||
|
||||
```text
|
||||
CASAN_PROFILE=development
|
||||
CASAN_CP_AUTH_MODE=local
|
||||
CP_BIND=127.0.0.1
|
||||
```
|
||||
|
||||
For short-lived compatibility testing only, H2 can be bypassed explicitly:
|
||||
|
||||
```text
|
||||
CASAN_H2_REGISTRY=0
|
||||
CASAN_AGENTIC_H2_REGISTRY=0
|
||||
```
|
||||
|
||||
The bypass is high-severity, observe-only/non-certifiable and rejected in
|
||||
production. Prefer registering the tool instead of retaining this setting.
|
||||
|
||||
Failure handling can be selected with
|
||||
`CASAN_SINGLE_STEP_FAILURE_POLICY=halt|quarantine|require_approval|record_only`.
|
||||
Production side effects reject `record_only` and fail closed to `halt`.
|
||||
|
||||
## Production Control Plane migration
|
||||
|
||||
1. Export the enterprise IdP's RS256 public key.
|
||||
2. Configure issuer, audience, claim names and bounded clock skew in
|
||||
`runtime.env` using `infra/production/runtime.env.example`.
|
||||
3. Configure oauth2-proxy to pass access tokens and authorization headers.
|
||||
4. Set `CASAN_CP_IDP_PUBLIC_KEY` in `casan-prod.env` for the read-only mount.
|
||||
5. Add a digest-pinned `CASAN_CP_OAUTH2_PROXY_IMAGE`.
|
||||
6. Remove `CASAN_CP_TRUST_AUTH_PROXY` from every environment.
|
||||
7. Configure Vault/KMS and Object Lock provider variables.
|
||||
8. Run `production-preflight.sh` before starting Compose.
|
||||
9. Run managed endpoint smoke with an authenticated enterprise session.
|
||||
|
||||
The current API loads a static public key at startup. Coordinate IdP rotation by
|
||||
installing the next public key and restarting the API after token overlap has
|
||||
been handled operationally. Automated JWKS rollover is not yet implemented.
|
||||
|
||||
## Adapter migration
|
||||
|
||||
The native harness and Agentic Bridge already dual-emit to
|
||||
`CASAN_STATE_ROOT/logs/kernel/`. Existing consumers can keep reading legacy
|
||||
records. New consumers should:
|
||||
|
||||
1. Require `schema_version=1.0.0`.
|
||||
2. Run the common verifier.
|
||||
3. Respect the four separate outcome fields.
|
||||
4. Reject observed-only certification.
|
||||
5. Treat runtime extensions as optional namespaced data.
|
||||
6. Avoid certifying legacy runs that have no canonical evidence.
|
||||
|
||||
For a new runtime, implement an adapter and pass the complete 10-invariant
|
||||
conformance matrix before advertising kernel conformance.
|
||||
|
||||
## Audit compatibility
|
||||
|
||||
New H5 audit records use v2 hashing with action class and risk factors. The
|
||||
audit verifier and head signer support v1 and v2 records. This is compatibility,
|
||||
not claim upgrading: v1 records do not gain v2 risk evidence retroactively.
|
||||
|
||||
## Verification commands
|
||||
|
||||
```bash
|
||||
python3 packages/casan-harness/tests/assurance-kernel-tests.py
|
||||
python3 packages/casan-harness/tests/assurance-upgrade-integration-tests.py
|
||||
bash packages/casan-harness/tests/phase-assurance-upgrade-tests.sh
|
||||
bash packages/casan-harness/tests/phase-agentic-bridge-tests.sh
|
||||
npm --workspace packages/casan-control-panel/backend test
|
||||
npm --workspace packages/casan-control-panel/backend run build
|
||||
npm --workspace packages/casan-control-panel/frontend run build
|
||||
bash packages/casan-harness/tests/phase-production-preflight-tests.sh
|
||||
```
|
||||
|
||||
Redirect `CASAN_STATE_ROOT` to a temporary directory for legacy suites that
|
||||
write runtime evidence.
|
||||
|
||||
## Rollback
|
||||
|
||||
Code rollback can restore the previous adapters because legacy emission remains
|
||||
present. Before rollback:
|
||||
|
||||
1. Stop new runs and preserve canonical/audit evidence.
|
||||
2. Record the last v2 audit head and external anchor.
|
||||
3. Roll back API, UI, Nginx and oauth2-proxy as one deployment unit.
|
||||
4. Do not restore trusted-header identity on a networked deployment.
|
||||
5. Do not disable production registry, isolation or trust-root requirements.
|
||||
6. If operational continuity requires emergency local trust, use the explicit
|
||||
break-glass override, retain the critical evidence and do not certify runs.
|
||||
|
||||
A rollback that reintroduces production header trust, missing-gate allow, or
|
||||
silent sandbox/trust fallback is not a safe compatibility rollback.
|
||||
|
||||
## Expected warnings
|
||||
|
||||
- Development registry bypass: high severity and non-certifiable.
|
||||
- Missing H2 in observe mode: degraded assurance.
|
||||
- Local signer/local ledger: permitted locally, untrusted for production.
|
||||
- Unsupported runtime intervention: explicit `unsupported`.
|
||||
- Legacy evidence without kernel envelope: compatibility-readable but not
|
||||
kernel-validated.
|
||||
@@ -10,20 +10,26 @@ This document defines the boundary between the local workstation experience and
|
||||
flowchart LR
|
||||
B["Browser"] -->|TLS + OIDC cookie| N["Nginx"]
|
||||
N -->|auth_request| O["oauth2-proxy"]
|
||||
N -->|overwritten identity headers| A["Control Panel API"]
|
||||
N -->|signed bearer token; identity headers removed| A["Control Panel API"]
|
||||
A -->|verify RS256 + issuer + audience + time claims| I["VerifiedClaims"]
|
||||
A -->|tenant-scoped encrypted store| S["CASAN state"]
|
||||
A -->|random bridge token, local only| H["Mac host bridge"]
|
||||
H -->|official CLI auth| P["Codex / Claude"]
|
||||
```
|
||||
|
||||
The API must not be published directly. Nginx is the only ingress and overwrites `X-CASAN-Actor`, `X-CASAN-Groups`, and `X-CASAN-Role`. The API refuses a non-loopback strict bind unless `CASAN_CP_TRUST_AUTH_PROXY=1` is explicit.
|
||||
The API must not be published directly. Nginx is the only ingress and removes
|
||||
`X-CASAN-*` and forwarded identity headers. The API refuses every production or
|
||||
non-loopback bind unless `CASAN_CP_AUTH_MODE=jwt` has a valid cryptographic
|
||||
verifier. Proxy headers alone are never authenticated identity.
|
||||
|
||||
## Implemented controls
|
||||
|
||||
- TLS at Nginx; production accepts only TLS 1.2/1.3.
|
||||
- OIDC authentication through oauth2-proxy.
|
||||
- Secure, HttpOnly, SameSite=Lax session cookies with bounded expiry/refresh.
|
||||
- Browser-supplied identity headers are overwritten at Nginx.
|
||||
- Browser-supplied identity headers are removed at Nginx.
|
||||
- The API verifies RS256 signature, issuer, audience, subject, expiry,
|
||||
not-before/issued-at bounds and clock skew before deriving request identity.
|
||||
- CSP, frame denial, MIME sniffing protection, referrer and browser permission restrictions.
|
||||
- API request body capped at 1 MiB.
|
||||
- SSE buffering disabled for trace streams; no intermediate proxy cache.
|
||||
@@ -53,21 +59,26 @@ Before production deployment:
|
||||
2. Do not deploy `provider-auth-bridge.py`.
|
||||
3. Use managed OpenAI/Anthropic credentials from Vault/KMS or workload identity.
|
||||
4. Use an enterprise IdP and explicit group-to-role mapping.
|
||||
5. Use a CA-issued certificate and a fixed production hostname.
|
||||
6. Set a digest-pinned `CASAN_CP_API_IMAGE`, `CASAN_CP_UI_IMAGE`, and `CASAN_CP_OAUTH2_PROXY_IMAGE`.
|
||||
7. Keep the API on a private container/network segment with Nginx as its only caller.
|
||||
8. Restrict egress from the API to allowlisted model providers, Vault/KMS, object storage and required observability endpoints.
|
||||
9. Store state on encrypted storage; send audit heads to KMS/WORM/Object Lock.
|
||||
10. Export rate-limit, auth failure, bridge-disabled and audit-chain metrics to alerting.
|
||||
11. Back up and restore-test tenant state before enabling write actions.
|
||||
12. Run the production preflight and security suites against the exact deployment images.
|
||||
5. Mount the IdP RS256 public key and configure exact issuer/audience; coordinate
|
||||
key rotation with an API restart until JWKS rollover is implemented.
|
||||
6. Use a CA-issued certificate and a fixed production hostname.
|
||||
7. Set a digest-pinned `CASAN_CP_API_IMAGE`, `CASAN_CP_UI_IMAGE`, and `CASAN_CP_OAUTH2_PROXY_IMAGE`.
|
||||
8. Keep the API on a private container/network segment with Nginx as its only caller.
|
||||
9. Restrict egress from the API to allowlisted model providers, Vault/KMS, object storage and required observability endpoints.
|
||||
10. Store state on encrypted storage; send audit heads to KMS/WORM/Object Lock.
|
||||
11. Export rate-limit, auth failure, bridge-disabled and audit-chain metrics to alerting.
|
||||
12. Back up and restore-test tenant state before enabling write actions.
|
||||
13. Run the production preflight and security suites against the exact deployment images.
|
||||
|
||||
## Known residual risks
|
||||
|
||||
- Local bridge authorization is bearer-token based; a process with access to the token file can call it.
|
||||
- In-memory rate windows reset when the API or bridge restarts. Production should also rate-limit at ingress.
|
||||
- Goal output is stored in tenant-scoped local state but is not currently envelope-encrypted as a whole.
|
||||
- A compromised container on the private Control Panel network may attempt to forge proxy headers. Production network policy must keep unrelated workloads off that network.
|
||||
- Static public-key rotation requires a coordinated file replacement and API
|
||||
restart; automated JWKS rollover is not implemented.
|
||||
- A compromised ingress container can interfere with availability or bearer
|
||||
forwarding, but cannot mint a valid IdP signature without the IdP key.
|
||||
- Developer account subscriptions have provider-specific quotas and are not an availability SLA.
|
||||
- The local mock IdP and self-signed TLS do not prove enterprise SSO readiness.
|
||||
|
||||
@@ -83,4 +94,3 @@ packages/casan-harness/scripts/bash/local-full.sh start
|
||||
This terminates the bridge, deletes the old token and creates a new one. Then inspect `tmp/control-panel-local/auth-bridge/model-audit.jsonl` for unexpected provider/status/hash activity. The log contains no raw prompts.
|
||||
|
||||
If a goal audit chain is suspected of tampering, stop new goal submissions, preserve `.specify/logs/audit/goal-orchestrator.jsonl` and its head, and compare each `prev_hash`/`record_hash` before restoring service.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user