# Admission Control (The Shield) Phase 7A introduces graduated proof-of-work admission control to defend against spam, Sybil attacks, and knowledge poisoning when Episteme is open to millions of agents. ## Overview New or untrusted agents must solve BLAKE3-based proof-of-work puzzles before their assertions are accepted. As agents demonstrate good behavior, they graduate to higher trust tiers with reduced PoW requirements and increased quotas. ## Key Concepts ### Trust Tiers | Trust Range | Tier | Quota Multiplier | PoW Required | |-------------|------------|------------------|--------------| | 0.0-0.3 | Untrusted | 0.1x (1,000/hr) | Yes | | 0.3-0.5 | Limited | 0.5x (5,000/hr) | Yes | | 0.5-0.7 | Verified | 1.0x (10,000/hr) | No | | 0.7-0.9 | Trusted | 2.0x (20,000/hr) | No | | 0.9-1.0 | Authority | 10.0x (100k/hr) | No | ### PoW Graduation | Assertions | Trust Score | Difficulty | Approximate Effort | |------------|-------------|------------|-------------------| | 0-9 | < 0.6 | 16 bits | ~16 seconds | | 10-49 | < 0.6 | 1 bit | Trivial | | 50+ | any | 0 bits | Exempt | | any | >= 0.6 | 0 bits | Exempt | ## HTTP API ### GET /v1/admission/status Get admission status for an agent. **Query Parameters:** - `agent_id` (required): Agent's Ed25519 public key (hex, 64 chars) **Response:** ```json { "agent_id": "abc123...", "tier": "Verified", "trust_score": 0.55, "assertions_count": 42, "pow_difficulty": 0, "pow_required": false, "base_quota_limit": 10000, "effective_quota_limit": 10000, "quota_multiplier": 1.0, "assertions_until_reduced_difficulty": null, "assertions_until_exemption": null } ``` ### Request Flow 1. Agent submits assertion with `X-Agent-Id` header 2. AdmissionLayer checks trust tier and assertion count 3. If PoW required: - Return HTTP 428 with difficulty in response body - Agent solves `BLAKE3(nonce || agent_id || timestamp)` with required leading zeros - Agent resubmits with `X-PoW-Nonce` and `X-PoW-Timestamp` headers 4. PoW verified, request proceeds to MeterLayer 5. On success, assertion count increments ### HTTP 428 Response (PoW Required) ```json { "error": "Proof-of-Work required", "code": "POW_REQUIRED", "required_difficulty": 16, "pow_required": true, "agent_assertions": 3, "agent_trust_score": 0.5 } ``` ## Headers ### Request Headers | Header | Description | |--------|-------------| | `X-Agent-Id` | Agent's Ed25519 public key (hex, 64 chars) | | `X-PoW-Nonce` | PoW solution nonce (decimal) | | `X-PoW-Timestamp` | PoW solution timestamp (Unix seconds) | ### Response Headers | Header | Description | |--------|-------------| | `X-Trust-Tier` | Agent's trust tier name | | `X-PoW-Required` | "true" or "false" | | `X-PoW-Difficulty` | Required difficulty in bits | | `X-Quota-Multiplier` | Tier quota multiplier | ## Implementation Details ### Core Types **TrustTier** (`stemedb-core/src/types/trust_tier.rs`): - Enum with 5 tiers: Untrusted, Limited, Verified, Trusted, Authority - Methods: `from_score()`, `quota_multiplier()`, `requires_pow()` **PowProof** (`stemedb-core/src/types/pow.rs`): - Struct with `nonce`, `agent_id`, `timestamp` - Methods: `verify()`, `compute_hash()`, `leading_zeros()`, `solve()` **AdmissionConfig** (`stemedb-core/src/types/pow.rs`): - Configurable thresholds and difficulties - Default: 16-bit initial, 10 assertions reduced, 50 graduated ### Storage **AdmissionStore** (`stemedb-storage/src/admission_store/`): - Wraps TrustRankStore (reuses existing trust score + assertion count) - No new storage keys needed - Methods: `get_admission_status()`, `verify_pow()`, `record_assertion()` ### Middleware **AdmissionLayer** (`stemedb-api/src/middleware/admission.rs`): - Tower middleware applied before MeterLayer - Extracts PoW headers, verifies proofs, returns 428 on failure - Bypasses health checks and admission status endpoint ## Client Implementation Guide To solve a PoW puzzle: ```rust use stemedb_core::types::PowProof; // Get your agent's Ed25519 public key let agent_id: [u8; 32] = ...; let timestamp = SystemTime::now().duration_since(UNIX_EPOCH)?.as_secs(); let difficulty = 16; // From 428 response // Brute-force search for valid nonce let proof = PowProof::solve(agent_id, timestamp, difficulty); // Submit with headers // X-Agent-Id: {hex(agent_id)} // X-PoW-Nonce: {proof.nonce} // X-PoW-Timestamp: {proof.timestamp} ``` ## Router Functions Three router variants are available: 1. `create_router()` - No admission control or metering 2. `create_router_with_meter()` - Metering only (quotas) 3. `create_router_with_admission()` - Full protection (PoW + quotas) ## Security Properties - **Replay Prevention**: Proofs expire after 5 minutes - **Agent Binding**: Proof includes agent_id, cannot be reused by others - **Asymmetric Cost**: O(2^difficulty) to solve, O(1) to verify - **Fail Open**: On store errors, requests are allowed (availability > strictness) - **Defense in Depth**: API layer primary, ingestion layer secondary ## Future: Phase 7B (EigenTrust) Phase 7B will build on this foundation: - Peer-to-peer trust propagation (trust agents you trust) - Network-wide reputation scores - Dynamic tier adjustments based on global consensus