/** * GridStamp — Claude Agent SDK: Proof-of-Presence Example * * What this does (for insurance underwriters reading this file): * 1. A mock camera sensor produces a synthetic HMAC-signed frame. * 2. Claude orchestrates four tools: read_sensor → verify_spatial_proof → * check_antispoofing → write_attestation. * 3. Every attestation is appended to ./proof-audit.ndjson — the audit trail * your claims team reads to establish whether the robot was where it said. * 4. The output is a structured AttestationResult: status, confidence score, * spoofing signals, and a pointer to the immutable audit log. * 5. Run: npm run example:agent (requires ANTHROPIC_API_KEY in env) */ import crypto from 'node:crypto'; import type { CameraFrame, Pose } from '../src/types/index.js'; import { runProofAgent } from '../src/agent/proof-agent.js'; // ── Mock sensor data ────────────────────────────────────────────────────────── const ROBOT_ID = 'DLV-DEMO-001'; const HMAC_SECRET = 'gridstamp-example-secret-min32chars!!'; const FRAME_WIDTH = 64; const FRAME_HEIGHT = 64; /** * Build a synthetic CameraFrame that looks like it came from a real camera. * The HMAC is computed over (id + timestamp + sequenceNumber) to mimic the * production HMAC-signing that happens at capture time in the perception layer. */ function buildMockFrame(sequenceNumber: number): CameraFrame { const id = `frame-${sequenceNumber}-${Date.now()}`; const timestamp = Date.now(); // Synthetic RGB: grey gradient with a per-frame noise seed const pixelCount = FRAME_WIDTH * FRAME_HEIGHT * 3; const rgb = new Uint8Array(pixelCount); for (let i = 0; i < pixelCount; i++) { rgb[i] = (i + sequenceNumber * 7) % 256; } // Synthetic depth map (metres, constant plane at ~2 m) const depth = new Float32Array(FRAME_WIDTH * FRAME_HEIGHT); depth.fill(2.0 + Math.random() * 0.05); const pose: Pose = { position: { x: 37.421998, y: -122.084, z: 0.0 }, orientation: { w: 1, x: 0, y: 0, z: 0 }, timestamp, }; // HMAC-SHA256 over id|timestamp|sequenceNumber — mirrors perception/camera.ts const hmac = crypto .createHmac('sha256', HMAC_SECRET) .update(`${id}|${timestamp}|${sequenceNumber}`) .digest('hex'); return { id, timestamp, rgb, width: FRAME_WIDTH, height: FRAME_HEIGHT, depth, pose, hmac, sequenceNumber }; } // ── Expected pose ───────────────────────────────────────────────────────────── const EXPECTED_POSE: Pose = { position: { x: 37.421998, y: -122.084, z: 0.0 }, orientation: { w: 1, x: 0, y: 0, z: 0 }, timestamp: Date.now(), }; // ── Run the agent ───────────────────────────────────────────────────────────── async function main(): Promise { console.log('GridStamp Proof-of-Presence Agent'); console.log('=================================='); console.log(`Robot: ${ROBOT_ID}`); console.log(`Model: claude-sonnet-4-6`); console.log(`Audit: ./proof-audit.ndjson`); console.log(''); // The agent calls this function when it invokes the read_sensor tool. // In production, replace with your camera driver (e.g. OAK-D, RealSense). let frameSeq = 1; const sensorReader = async (_sensorId: string): Promise => { return buildMockFrame(frameSeq++); }; const result = await runProofAgent({ robotId: ROBOT_ID, hmacSecret: HMAC_SECRET, sensorReader, expectedPose: EXPECTED_POSE, auditLogPath: './proof-audit.ndjson', }); console.log('Attestation Result'); console.log('------------------'); console.log(`Status: ${result.status}`); console.log(`Proof ID: ${result.proofId}`); console.log(`Confidence: ${(result.confidence * 100).toFixed(1)}%`); console.log(`Chain length: ${result.chainLength}`); console.log(`Audit trail: ${result.auditTrailPath}`); if (result.spoofingSignals.length > 0) { console.log(''); console.log('Spoofing signals:'); for (const signal of result.spoofingSignals) { console.log(` • ${signal}`); } } else { console.log('Spoofing signals: none'); } console.log(''); console.log(`Exit: ${result.status === 'pass' ? 0 : 1}`); process.exitCode = result.status === 'pass' ? 0 : 1; } main().catch((err: unknown) => { console.error('Agent error:', err); process.exitCode = 1; });