from fastapi import FastAPI, HTTPException from typing import Dict from .models import BondRecord, ClaimSubmission, ReplayBundle from uuid import uuid4 from datetime import datetime app = FastAPI(title="ReplicaSurety - Surety Ledger") # Simple in-memory store. This is intentionally minimal and pluggable. _BONDS: Dict[str, BondRecord] = {} _CLAIMS: Dict[str, ClaimSubmission] = {} @app.post("/bonds", response_model=BondRecord) def create_bond(record: BondRecord): if record.escrow_id in _BONDS: raise HTTPException(status_code=400, detail="escrow_id already exists") _BONDS[record.escrow_id] = record return record @app.get("/bonds/{escrow_id}", response_model=BondRecord) def get_bond(escrow_id: str): r = _BONDS.get(escrow_id) if not r: raise HTTPException(status_code=404, detail="not found") return r @app.post("/claims", response_model=ClaimSubmission) def submit_claim(claim: ClaimSubmission): if claim.claim_id in _CLAIMS: raise HTTPException(status_code=400, detail="claim_id already submitted") # Minimal validation: evidence_root looks present if not claim.evidence_root: raise HTTPException(status_code=400, detail="evidence_root required") _CLAIMS[claim.claim_id] = claim # In a real system: dispatch to verifier/adjudicator plugins return claim @app.post("/verify_replay") def verify_replay(bundle: ReplayBundle): # Minimal deterministic verifier: ensure trace seq monotonic and evidence root present last_seq = -1 for ev in bundle.trace: if ev.seq <= last_seq: raise HTTPException(status_code=400, detail="non-monotonic trace sequence") last_seq = ev.seq # In a real verifier we'd replay deterministically and compute a DamageScore return {"verdict": "ok", "evidence_root": bundle.evidence_root}