Skip to content
Merged
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
25 changes: 18 additions & 7 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ Versioning follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [1.2.0] - 2026-03-08

Protocol-first restructure, TypeScript implementation, finalized URI scheme, and full CapsuleType conformance.
Protocol-first restructure, TypeScript implementation, finalized URI scheme, full CapsuleType conformance, Security Considerations in spec, cryptographic chain verification, and 11-framework compliance directory.

### Changed

Expand All @@ -24,19 +24,30 @@ Protocol-first restructure, TypeScript implementation, finalized URI scheme, and
- Protocol documentation at `docs/` (language-agnostic)
- Python-specific docs at `reference/python/docs/`
- No `pyproject.toml` at repo root — the repo is a protocol, not a package
- **Compliance restructured into per-framework directory** — `docs/compliance.md` replaced by `docs/compliance/` with individual documents per framework and a README index.

### Added

- **`capsule://` URI scheme (Active)** — content-addressable references to Capsule records via their SHA3-256 hash. Spec at `spec/uri-scheme.md`, finalized from Draft to Active. Supports hash references (`capsule://sha3_<hash>`), chain references (`capsule://chain/42`), ID references, and fragment syntax into the 6 sections. Includes URI conformance vectors at `conformance/uri-fixtures.json`.
- **TypeScript reference implementation** — full CPS-conformant implementation at `reference/typescript/`: Capsule model with factories, canonical JSON serializer (CPS Section 2 with float-path handling), SHA3-256 hashing, Ed25519 seal/verify, and chain verification. Passes all 16 golden fixtures. 101 tests, 100% coverage (v8). Uses `@noble/hashes` ^2.0.1, `@noble/ed25519` ^3.0.0, vitest ^4.0.0, TypeScript ^5.9.0. Node.js >= 20.19.0.
- **Implementor's Guide** (`docs/implementors-guide.md`) — step-by-step instructions for building a conformant CPS implementation in any language, with language-specific pitfalls for TypeScript, Go, and Rust.
- **Why Capsules** (`docs/why-capsules.md`) — the case for cryptographic AI memory, aimed at decision-makers and architects.
- **URI scheme security considerations** — `spec/uri-scheme.md` includes: URI injection validation, resolution trust model, denial-of-service mitigations, fragment path traversal safety, no ambient authority principle.
- **Security Considerations in CPS spec** (`spec/README.md` Section 7) — documents what CPS provides (integrity, authenticity, non-repudiation, ordering, quantum resistance) and what it does not (confidentiality, truthfulness, availability, identity binding). Covers signer key compromise, chain truncation, verification levels, replay, and timestamp trust.
- **Cryptographic chain verification** — `chain.verify(verify_content=True)` recomputes SHA3-256 from content and compares to stored hash. `chain.verify(seal=seal_instance)` also verifies Ed25519 signatures. Both Python and TypeScript implementations. Default structural-only behavior is unchanged (backward compatible).
- **11-framework compliance directory** (`docs/compliance/`) — per-framework regulatory mappings: NIST SP 800-53, NIST AI RMF, EU AI Act, SOC 2, ISO 27001, HIPAA, GDPR, PCI DSS, FedRAMP, FINRA, CMMC. Each document maps protocol-level capabilities to specific controls and lists complementary controls outside the protocol's scope.
- **NIST RFI submission archive** (`nist-submission/`) — exact artifacts submitted to NIST (Docket NIST-2025-0035), SHA-256 checksums, and README with normative/informative classification.
- **`capsule://` URI scheme (Active)** — content-addressable references to Capsule records via their SHA3-256 hash. Spec at `spec/uri-scheme.md`, finalized from Draft to Active. Supports hash references (`capsule://sha3_<hash>`), chain references (`capsule://chain/42`), ID references, and fragment syntax into the 6 sections.
- **URI conformance vectors** (`conformance/uri-fixtures.json`) — 10 valid and 11 invalid URI parsing test vectors for cross-language URI parser verification.
- **TypeScript reference implementation** — full CPS-conformant implementation at `reference/typescript/`: Capsule model with factories, canonical JSON serializer (CPS Section 2 with float-path handling), SHA3-256 hashing, Ed25519 seal/verify, and chain verification with `verifyContent` option. Passes all 16 golden fixtures. 101 tests, 100% coverage (v8). Uses `@noble/hashes` ^2.0.1, `@noble/ed25519` ^3.0.0, vitest ^4.0.0, TypeScript ^5.9.0. Node.js >= 20.19.0.
- **TypeScript release workflow** (`.github/workflows/typescript-release.yaml`) — npm publish with provenance on version tags, gated by conformance tests.
- **`vault` golden fixture** — conformance suite now covers all 8 CapsuleTypes (16 total fixtures, up from 15). The `vault_secret` fixture tests secret rotation with policy-based authority.
- **Protocol structure tests** (`reference/python/tests/test_protocol_structure.py`) — guards the protocol-first layout, spec completeness, conformance suite integrity, TypeScript type alignment with spec, markdown link resolution, CI configuration, and root-level file requirements.
- **Implementor's Guide** (`docs/implementors-guide.md`) — step-by-step instructions for building a conformant CPS implementation in any language, with URI parsing section and language-specific pitfalls.
- **Why Capsules** (`docs/why-capsules.md`) — the case for cryptographic AI memory.
- **Protocol structure tests** — guards the protocol-first layout, spec completeness (including Security Considerations), conformance suite integrity, URI vectors, compliance directory, TypeScript alignment, markdown links, CI configuration, and root-level files.
- **Dependabot for TypeScript** — npm dependency updates for `reference/typescript/`.

### Security

- `chain.verify()` now supports cryptographic verification (`verify_content=True`, `seal=`) in addition to structural-only checks. Structural verification alone trusts stored hash values; cryptographic verification recomputes from content.
- Hash computation in chain verification uses the canonical `compute_hash()` function (Python) and `computeHash(toDict())` (TypeScript) to prevent divergence from the sealing path.
- Spec Section 7 explicitly documents non-goals: no confidentiality, no content truthfulness, no availability guarantees, no identity binding.

### Updated

- **Python dependencies** — pytest >=9.0.0, pytest-asyncio >=1.0.0, ruff >=0.15.0, mypy >=1.19.0, sqlalchemy >=2.0.48, asyncpg >=0.31.0, liboqs-python >=0.14.1.
Expand Down
11 changes: 10 additions & 1 deletion docs/architecture.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,21 @@ Capsule #0 Capsule #1 Capsule #2

### Chain Verification

`chain.verify()` walks every Capsule in sequence order and checks:
`chain.verify()` supports two verification levels:

**Structural** (default, fast): walks every Capsule in sequence order and checks:

1. Sequence numbers are consecutive: 0, 1, 2, ...
2. Each Capsule's `previous_hash` matches the previous Capsule's `hash`
3. The genesis Capsule (sequence 0) has `previous_hash = None`

**Cryptographic** (`verify_content=True`): everything above, plus:

4. Recomputes SHA3-256 from content and compares to stored hash
5. Optionally verifies Ed25519 signatures (when `seal=` is provided)

Structural verification trusts stored hash values. Cryptographic verification catches storage-level tampering where an attacker modifies content without the signing key. See [CPS Section 7.5](../spec/README.md) for the security rationale.

If any check fails, the result includes the Capsule ID where the chain broke and the number of Capsules verified before the break.

### Multi-Tenant Chains
Expand Down
15 changes: 15 additions & 0 deletions docs/implementors-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,28 @@ Seal fields (`hash`, `signature`, `signature_pq`, `signed_at`, `signed_by`) are

## Step 6: Chain Verification

Implementations SHOULD support two verification levels (see [CPS Section 7.5](../spec/README.md)):

**Structural** (fast):

```
1. Load all Capsules in sequence order
2. Verify sequence numbers are consecutive: 0, 1, 2, ...
3. Verify genesis (sequence 0) has previous_hash = null
4. For each subsequent Capsule, verify previous_hash = hash of previous Capsule
```

**Cryptographic** (thorough):

```
All structural checks, plus:
5. For each Capsule, recompute SHA3-256 from content via to_dict() + canonicalize()
6. Compare recomputed hash to stored hash (detects storage-level tampering)
7. Optionally verify Ed25519 signature on each Capsule
```

Structural verification trusts stored hash values. Cryptographic verification catches content tampering where the attacker does not have the signing key.

---

## Step 7: Conformance Testing
Expand Down
41 changes: 37 additions & 4 deletions reference/python/src/qp_capsule/chain.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
from dataclasses import dataclass
from typing import TYPE_CHECKING

from qp_capsule.seal import compute_hash

if TYPE_CHECKING:
from qp_capsule.capsule import Capsule
from qp_capsule.protocol import CapsuleStorageProtocol
Expand Down Expand Up @@ -88,21 +90,36 @@ async def add(self, capsule: Capsule, tenant_id: str | None = None) -> Capsule:

return capsule

async def verify(self, tenant_id: str | None = None) -> ChainVerificationResult:
async def verify(
self,
tenant_id: str | None = None,
*,
verify_content: bool = False,
seal: Seal | None = None,
) -> ChainVerificationResult:
"""
Verify the entire chain integrity.

Checks:
Structural checks (always):
1. Sequence numbers are consecutive (0, 1, 2, ...)
2. Each Capsule's previous_hash matches the previous Capsule's hash
3. First Capsule has previous_hash = None

Cryptographic checks (when verify_content=True or seal is provided):
4. Recompute SHA3-256 from content and compare to stored hash
5. Verify Ed25519 signature (requires seal)

Args:
tenant_id: If provided, verify only this tenant's chain
verify_content: If True, recompute hashes from content
seal: If provided, also verify Ed25519 signatures (implies verify_content)

Returns:
ChainVerificationResult with validity and error details
"""
if seal is not None:
verify_content = True

capsules = await self.storage.get_all_ordered(tenant_id=tenant_id)

if not capsules:
Expand All @@ -120,7 +137,6 @@ async def verify(self, tenant_id: str | None = None) -> ChainVerificationResult:

# Check previous_hash
if i == 0:
# First Capsule should have no previous
if capsule.previous_hash is not None:
return ChainVerificationResult(
valid=False,
Expand All @@ -129,7 +145,6 @@ async def verify(self, tenant_id: str | None = None) -> ChainVerificationResult:
capsules_verified=0,
)
else:
# Subsequent Capsules should link to previous
expected_prev = capsules[i - 1].hash
if capsule.previous_hash != expected_prev:
return ChainVerificationResult(
Expand All @@ -139,6 +154,24 @@ async def verify(self, tenant_id: str | None = None) -> ChainVerificationResult:
capsules_verified=i,
)

if verify_content:
computed = compute_hash(capsule.to_dict())
if computed != capsule.hash:
return ChainVerificationResult(
valid=False,
error=f"Content hash mismatch at sequence {i}",
broken_at=str(capsule.id),
capsules_verified=i,
)

if seal is not None and not seal.verify(capsule):
return ChainVerificationResult(
valid=False,
error=f"Signature verification failed at sequence {i}",
broken_at=str(capsule.id),
capsules_verified=i,
)

return ChainVerificationResult(
valid=True,
capsules_verified=len(capsules),
Expand Down
Loading