feat: add draft data, gap analysis report, and workspace config
This commit is contained in:
312
workspace/act/act-implementation-master-prompt.md
Normal file
312
workspace/act/act-implementation-master-prompt.md
Normal file
@@ -0,0 +1,312 @@
|
||||
# Master Prompt: ACT Reference Implementation
|
||||
|
||||
## Context
|
||||
|
||||
You are implementing the reference implementation for the Agent Compact
|
||||
Token (ACT), as defined in `draft-nennemann-act-00`. The full draft is
|
||||
attached or provided in context. Your implementation must be a clean,
|
||||
well-documented Python package that serves as the normative reference
|
||||
for the specification — meaning it is the ground truth for
|
||||
interoperability testing.
|
||||
|
||||
The ACS (Agent Compliance Seal) reference implementation (~1,900 lines,
|
||||
Python) exists as a prior art reference for code style and structure.
|
||||
ACT follows the same philosophy: minimal dependencies, sub-millisecond
|
||||
performance for the hot path, Ed25519 as the primary algorithm.
|
||||
|
||||
---
|
||||
|
||||
## Deliverables
|
||||
|
||||
Produce the following files in a single `act/` package directory:
|
||||
|
||||
```
|
||||
act/
|
||||
├── __init__.py # Public API exports
|
||||
├── token.py # ACTMandate and ACTRecord dataclasses + serialization
|
||||
├── crypto.py # Key management: Tier 1 (pre-shared), Tier 2 (PKI),
|
||||
│ # Tier 3 (DID:key, DID:web); sign/verify primitives
|
||||
├── lifecycle.py # Phase 1 → Phase 2 transition logic (re-signing)
|
||||
├── delegation.py # Delegation chain construction and verification
|
||||
├── dag.py # DAG validation (uniqueness, parent existence,
|
||||
│ # temporal ordering, acyclicity, capability
|
||||
│ # consistency)
|
||||
├── ledger.py # In-memory append-only audit ledger (for testing;
|
||||
│ # interface suitable for external backends)
|
||||
├── verify.py # Unified verification entry point (Phase 1 + Phase 2)
|
||||
├── errors.py # All ACT-specific exception types
|
||||
└── vectors.py # Generates and validates all Appendix B test vectors
|
||||
tests/
|
||||
├── test_token.py
|
||||
├── test_crypto.py
|
||||
├── test_lifecycle.py
|
||||
├── test_delegation.py
|
||||
├── test_dag.py
|
||||
├── test_ledger.py
|
||||
├── test_verify.py
|
||||
└── test_vectors.py # Must pass all vectors defined in vectors.py
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Specification Summary
|
||||
|
||||
### Token Structure
|
||||
|
||||
An ACT is a JWT (JWS Compact Serialization). It has two phases:
|
||||
|
||||
**Phase 1 — Authorization Mandate** (signed by issuing agent):
|
||||
|
||||
JOSE Header:
|
||||
```json
|
||||
{
|
||||
"alg": "EdDSA", // Ed25519; also support ES256
|
||||
"typ": "act+jwt",
|
||||
"kid": "<key-id>"
|
||||
// optional: "x5c" (Tier 2), "did" (Tier 3)
|
||||
}
|
||||
```
|
||||
|
||||
Required JWT claims:
|
||||
- `iss` — issuer agent identifier (opaque string / X.509 DN / DID)
|
||||
- `sub` — target agent identifier (same format as iss)
|
||||
- `aud` — intended recipient(s); string or array
|
||||
- `iat` — issuance time (NumericDate)
|
||||
- `exp` — expiration time (NumericDate); SHOULD be iat + ≤900s for automated flows
|
||||
- `jti` — UUID v4; doubles as task identifier for DAG par references
|
||||
|
||||
Optional:
|
||||
- `wid` — workflow UUID grouping related ACTs
|
||||
|
||||
Required ACT-specific claims:
|
||||
- `task` — object: { purpose (str, REQUIRED), data_sensitivity (str, OPTIONAL),
|
||||
created_by (str, OPTIONAL), expires_at (NumericDate, OPTIONAL) }
|
||||
- `cap` — array of { action (str, REQUIRED), constraints (object, OPTIONAL) }
|
||||
action names conform to ABNF: component *("." component)
|
||||
component = ALPHA *(ALPHA / DIGIT / "-" / "_")
|
||||
- `del` — object: { depth (int), max_depth (int), chain (array) }
|
||||
chain entries: { delegator (str), jti (str), sig (base64url str) }
|
||||
chain is ordered root → immediate parent (chain[0] = root authority)
|
||||
If `del` is absent: treat as root mandate, depth=0, delegation forbidden
|
||||
|
||||
Optional:
|
||||
- `oversight` — { requires_approval_for (array of action strings),
|
||||
approval_ref (str, OPTIONAL) }
|
||||
|
||||
**Phase 2 — Execution Record** (re-signed by executing agent, i.e. `sub`):
|
||||
|
||||
All Phase 1 claims are preserved unchanged. Additional required claims:
|
||||
- `exec_act` — string; MUST match one of the cap[].action values
|
||||
- `par` — array of jti strings (parent task IDs in DAG); [] for root tasks
|
||||
- `exec_ts` — NumericDate; actual execution time; MUST be >= iat; SHOULD be <= exp
|
||||
(if exec_ts > exp: log warning, do NOT reject)
|
||||
- `status` — one of: "completed", "failed", "partial"
|
||||
|
||||
Additional optional claims:
|
||||
- `inp_hash` — base64url(SHA-256(raw input bytes)), no padding
|
||||
- `out_hash` — base64url(SHA-256(raw output bytes)), no padding
|
||||
- `err` — { code (str), detail (str) }; present when status != "completed"
|
||||
|
||||
**Critical**: In Phase 2, the JOSE header `kid` MUST reference the `sub`
|
||||
agent's key (not the `iss` agent's key). The re-signature is produced by
|
||||
the executing agent over the complete Phase 2 payload (all Phase 1 claims
|
||||
+ execution claims combined).
|
||||
|
||||
---
|
||||
|
||||
### Trust Tiers
|
||||
|
||||
**Tier 1 — Pre-Shared Keys (mandatory-to-implement)**
|
||||
- Keys: Ed25519 (primary) or P-256
|
||||
- `kid`: opaque string agreed out-of-band
|
||||
- Key registry: a dict mapping kid → public key bytes, configured at init time
|
||||
- No external resolution needed
|
||||
|
||||
**Tier 2 — PKI / X.509**
|
||||
- `kid`: SHA-256 thumbprint of DER-encoded certificate
|
||||
- `x5c` JOSE header MAY carry the certificate chain
|
||||
- Verification: standard X.509 chain validation against trusted CA store
|
||||
|
||||
**Tier 3 — DID**
|
||||
- Support `did:key` (self-contained, no resolution needed)
|
||||
- Support `did:web` (requires HTTP resolution; cache with configurable TTL)
|
||||
- `kid`: DID key fragment (e.g. `did:key:z6Mk...#key-1`)
|
||||
- `did` JOSE header MAY carry the full DID for resolution
|
||||
|
||||
---
|
||||
|
||||
### Delegation Chain
|
||||
|
||||
When issuing a delegated ACT (Agent A → Agent B):
|
||||
|
||||
1. `del.depth` = parent ACT's `del.depth` + 1
|
||||
2. `del.max_depth` ≤ parent ACT's `del.max_depth`
|
||||
3. `cap` must be a subset of parent ACT's `cap` with constraints at least
|
||||
as restrictive
|
||||
4. Each chain entry `sig` = Sign(A.private_key, SHA-256(parent_act_compact_bytes))
|
||||
where `parent_act_compact_bytes` is the raw bytes of the parent ACT's
|
||||
JWS Compact Serialization (UTF-8 encoded)
|
||||
|
||||
Verification of chain entry:
|
||||
- Retrieve public key for entry.delegator
|
||||
- Recompute SHA-256(parent_act_compact_bytes)
|
||||
- Verify entry.sig against that hash using entry.delegator's public key
|
||||
|
||||
Rejection conditions:
|
||||
- `del.depth` > `del.max_depth`
|
||||
- `del.chain` length != `del.depth`
|
||||
- Any chain entry sig fails verification
|
||||
- `cap` contains actions not in parent ACT's `cap`
|
||||
- Any constraint in `cap` is less restrictive than in parent ACT
|
||||
|
||||
---
|
||||
|
||||
### DAG Validation (Phase 2)
|
||||
|
||||
The ACT ledger (or set of received parent ACTs) is the ECT store.
|
||||
|
||||
Required checks on receiving a Phase 2 ACT:
|
||||
1. `jti` uniqueness within `wid` scope (or globally if `wid` absent)
|
||||
2. Every `jti` in `par` exists in the ledger/store as a verified Phase 2 ACT
|
||||
3. For each parent: `parent.exec_ts < child.exec_ts + 30s` (clock skew tolerance)
|
||||
4. No cycle: following `par` references must not return to current `jti`
|
||||
— enforce max traversal limit of 10,000 nodes
|
||||
5. `exec_act` matches one of the `cap[].action` values in the Phase 1 claims
|
||||
|
||||
---
|
||||
|
||||
### Verification Procedure
|
||||
|
||||
**Phase 1 verification** (ACTVerifier.verify_mandate):
|
||||
1. Parse JWS Compact Serialization
|
||||
2. Check `typ` == "act+jwt"
|
||||
3. Check `alg` in allowlist (must include EdDSA/Ed25519, ES256; MUST NOT include
|
||||
"none" or any HS* algorithm)
|
||||
4. Resolve public key for `kid` per trust tier
|
||||
5. Verify JWS signature
|
||||
6. Check `exp` not passed (clock skew tolerance: ≤300s)
|
||||
7. Check `iat` not unreasonably future (≤30s ahead)
|
||||
8. Check `aud` contains verifier's own identifier
|
||||
9. Check `iss` is trusted per local policy
|
||||
10. Check `sub` matches verifier's own identifier (when verifier is the target)
|
||||
11. Check all required claims present and well-formed
|
||||
12. If `del.chain` non-empty: verify delegation chain
|
||||
|
||||
**Phase 2 verification** (ACTVerifier.verify_record):
|
||||
All Phase 1 steps, plus:
|
||||
13. Check `exec_act` present and matches a `cap[].action`
|
||||
14. Check `par` present; perform DAG validation
|
||||
15. Check `exec_ts` present and >= `iat`; if > `exp` log warning but do NOT reject
|
||||
16. Check `status` present and valid
|
||||
17. Check re-signature was produced by `sub` agent's key (kid in Phase 2
|
||||
header must correspond to sub's public key, not iss's key)
|
||||
18. Optionally verify `inp_hash`/`out_hash` against provided data
|
||||
|
||||
---
|
||||
|
||||
### Audit Ledger Interface
|
||||
|
||||
`ACTLedger` (in-memory reference implementation):
|
||||
- `append(act_record: ACTRecord) -> int` — returns sequence number
|
||||
- `get(jti: str) -> ACTRecord | None`
|
||||
- `list(wid: str | None) -> list[ACTRecord]`
|
||||
- `verify_integrity() -> bool` — verifies no records have been tampered with
|
||||
(hash-chain over sequence-ordered records)
|
||||
|
||||
The ledger must enforce append-only semantics: once appended, a record
|
||||
cannot be modified or deleted. Raise `ACTLedgerImmutabilityError` on
|
||||
any attempt.
|
||||
|
||||
---
|
||||
|
||||
### Error Types
|
||||
|
||||
Define in `errors.py`:
|
||||
```python
|
||||
ACTError # base
|
||||
ACTValidationError # malformed token structure
|
||||
ACTSignatureError # signature verification failed
|
||||
ACTExpiredError # token expired
|
||||
ACTAudienceMismatchError # aud does not contain verifier identity
|
||||
ACTCapabilityError # no matching capability / capability escalation
|
||||
ACTDelegationError # delegation chain invalid
|
||||
ACTDAGError # DAG validation failed (cycle, missing parent, etc.)
|
||||
ACTPhaseError # wrong phase for operation (e.g. mandate used as record)
|
||||
ACTKeyResolutionError # cannot resolve kid to public key
|
||||
ACTLedgerImmutabilityError # attempt to modify ledger
|
||||
ACTPrivilegeEscalationError # delegated cap exceeds parent cap
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Test Vectors (Appendix B)
|
||||
|
||||
`vectors.py` must generate and validate all of the following. Each vector
|
||||
must include: description, input parameters, expected output (encoded token
|
||||
or expected exception class).
|
||||
|
||||
**Valid vectors:**
|
||||
- B.1: Phase 1 ACT — root mandate, Tier 1 (Ed25519 pre-shared key), no delegation
|
||||
- B.2: Phase 2 ACT — completed execution, transition from B.1 mandate
|
||||
- B.3: Phase 2 ACT — fan-in, two parent jti values from parallel branches
|
||||
- B.4: Phase 1 ACT — delegated mandate (depth=1), chain entry with sig
|
||||
- B.5: Phase 2 ACT — delegated execution record
|
||||
|
||||
**Invalid vectors (must raise specified exception):**
|
||||
- B.6: `del.depth` > `del.max_depth` → ACTDelegationError
|
||||
- B.7: `cap` escalation in delegated ACT → ACTPrivilegeEscalationError
|
||||
- B.8: `exec_act` not in `cap` → ACTCapabilityError
|
||||
- B.9: DAG cycle (par references own jti) → ACTDAGError
|
||||
- B.10: Missing parent jti in DAG → ACTDAGError
|
||||
- B.11: Tampered payload (bit flip in claims) → ACTSignatureError
|
||||
- B.12: Expired token → ACTExpiredError
|
||||
- B.13: Wrong audience → ACTAudienceMismatchError
|
||||
- B.14: Phase 2 re-signed by iss key instead of sub → ACTSignatureError
|
||||
- B.15: Algorithm "none" → ACTValidationError
|
||||
|
||||
---
|
||||
|
||||
## Implementation Constraints
|
||||
|
||||
**Dependencies**: use only the Python standard library plus:
|
||||
- `cryptography` (for Ed25519, P-256, X.509)
|
||||
- `pyjwt` OR manual JWS implementation (prefer manual for spec fidelity)
|
||||
- `pytest` (test runner only)
|
||||
|
||||
**Performance target**: Phase 1 creation ≤ 500µs mean on modern hardware.
|
||||
Benchmark in a `bench/` directory.
|
||||
|
||||
**Code style**:
|
||||
- Type-annotated throughout (Python 3.11+)
|
||||
- Dataclasses for token structures
|
||||
- No global mutable state
|
||||
- All public API functions documented with docstrings referencing the
|
||||
relevant draft section (e.g. `# ACT §8.1`)
|
||||
|
||||
**Security constraints**:
|
||||
- MUST NOT use symmetric algorithms (HS256 etc.) anywhere
|
||||
- MUST NOT implement "alg: none" path
|
||||
- Ed25519 signing MUST use bound key-pair APIs (private key object that
|
||||
carries the public key) — never pass raw private key bytes
|
||||
- All secret key material must be zeroed on deletion where the
|
||||
cryptography library supports it
|
||||
|
||||
**What NOT to implement**:
|
||||
- DID:web resolution with live HTTP calls in the reference implementation
|
||||
(stub it with a configurable resolver callback instead)
|
||||
- Token revocation infrastructure
|
||||
- Persistence (ledger is in-memory only)
|
||||
|
||||
---
|
||||
|
||||
## Output Format
|
||||
|
||||
Produce each file completely, in order. After all files, produce a
|
||||
`README.md` for the `act/` package that includes:
|
||||
- Installation instructions
|
||||
- Quick-start example (Phase 1 mandate → Phase 2 record → verify)
|
||||
- Running the test suite
|
||||
- Running the test vectors
|
||||
- Performance benchmark instructions
|
||||
|
||||
At the end, confirm: "All Appendix B test vectors pass."
|
||||
Reference in New Issue
Block a user