build(agent): r2d2#deee02 iteration

This commit is contained in:
agent-deee027bb02fa06e 2026-04-26 22:29:15 +02:00
parent 82f5d75778
commit fb9da8a2a6
10 changed files with 229 additions and 105 deletions

View File

@ -1,35 +1,10 @@
ReplicaSurety — idea199-replicasurety-economic-surety
===============================================
ReplicaSurety — minimal reference implementation
This repository implements a focused, production-minded chunk of the ReplicaSurety vision:
This repository provides a focused implementation of core ReplicaSurety primitives:
- PoeticCert and ReplayBundle JSON schemas (Pydantic models)
- A tiny off-chain Surety Ledger (in-memory with JSON persistence)
- A deterministic ReplayBundle verifier that emits a signed verdict (demo)
- FastAPI endpoints to interact with the ledger and verifier
- Tests, README, AGENTS.md, and a test.sh that runs tests and builds the package
- A tiny off-chain Surety Ledger FastAPI service with basic escrow lifecycle endpoints
- A deterministic ReplayBundle verifier (reference behavior)
- Tests and packaging metadata so `bash test.sh` runs pytest and builds the package
This is an intentionally small, well-tested foundation intended for further extension.
Quickstart
----------
Install (editable):
python3 -m pip install -e .
Run tests and build (this repository includes test.sh):
bash test.sh
Run the demo API locally:
uvicorn src.idea199_replicasurety_economic_surety.api:app --reload
Project layout
--------------
- src/idea199_replicasurety_economic_surety: implementation
- tests/: pytest test suite
- AGENTS.md: architecture and rules for contributors
License: MIT
This is intentionally minimal and meant as a starting point for the community PoC.

View File

@ -1,18 +1,20 @@
[build-system]
requires = ["setuptools", "wheel"]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
[project]
name = "idea199-replicasurety-economic-surety"
version = "0.1.0"
description = "ReplicaSurety: PoeticCert, ReplayBundle, and a tiny off-chain surety ledger and verifier"
description = "ReplicaSurety: PoeticCert schemas, ReplayBundle format and a tiny off-chain surety ledger"
readme = "README.md"
requires-python = ">=3.9"
license = {text = "MIT"}
dependencies = [
"fastapi>=0.95",
"pydantic>=1.10",
"uvicorn>=0.18",
"cryptography>=40.0",
"httpx>=0.24",
]
[project.urls]
"Homepage" = "https://example.com/replicasurety"
[tool.setuptools.packages.find]
where = ["src"]

View File

@ -1,2 +1 @@
"""idea199_replicasurety_economic_surety package"""
__version__ = "0.1.0"
__all__ = ["models", "ledger"]

View File

@ -0,0 +1,38 @@
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat, PrivateFormat, NoEncryption
def generate_rsa_keypair(key_size: int = 2048):
private_key = rsa.generate_private_key(public_exponent=65537, key_size=key_size)
public_key = private_key.public_key()
return private_key, public_key
def sign_bytes(private_key, data: bytes) -> bytes:
return private_key.sign(
data,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256(),
)
def verify_bytes(public_key, signature: bytes, data: bytes) -> bool:
try:
public_key.verify(
signature,
data,
padding.PSS(mgf=padding.MGF1(hashes.SHA256()), salt_length=padding.PSS.MAX_LENGTH),
hashes.SHA256(),
)
return True
except Exception:
return False
def serialize_public_key(public_key) -> bytes:
return public_key.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
def serialize_private_key(private_key) -> bytes:
return private_key.private_bytes(Encoding.PEM, PrivateFormat.TraditionalOpenSSL, NoEncryption())

View File

@ -1,57 +1,51 @@
import json
from dataclasses import dataclass, asdict
from typing import Dict, Optional
from pathlib import Path
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] = {}
@dataclass
class Escrow:
escrow_id: str
issuer: str
stake_amount: float
policy_hash: str
ttl: int
status: str = "open"
@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
class SuretyLedger:
"""Tiny JSON-backed off-chain ledger for escrows.
@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
This is intentionally minimal: an in-memory dict persisted to a JSON file for
demo and tests.
"""
def __init__(self, path: Optional[str] = None):
self._path = Path(path) if path else None
self._escrows: Dict[str, Escrow] = {}
if self._path and self._path.exists():
self._load()
@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
def _load(self):
with self._path.open("r", encoding="utf-8") as f:
raw = json.load(f)
for k, v in raw.items():
self._escrows[k] = Escrow(**v)
def _save(self):
if not self._path:
return
serial = {k: asdict(v) for k, v in self._escrows.items()}
with self._path.open("w", encoding="utf-8") as f:
json.dump(serial, f, indent=2)
def create_escrow(self, escrow: Escrow):
if escrow.escrow_id in self._escrows:
raise ValueError("escrow exists")
self._escrows[escrow.escrow_id] = escrow
self._save()
def get_escrow(self, escrow_id: str) -> Optional[Escrow]:
return self._escrows.get(escrow_id)
def settle_escrow(self, escrow_id: str):
e = self._escrows.get(escrow_id)
if not e:
raise KeyError("not found")
e.status = "settled"
self._save()
@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}

View File

@ -0,0 +1,3 @@
from .ledger import app
__all__ = ["app"]

View File

@ -0,0 +1,64 @@
from typing import Dict, List, Optional, Any
from pydantic import BaseModel, Field, constr
from datetime import datetime
class PoeticCert(BaseModel):
"""Compact PoeticCert schema.
Fields:
- invariants: free-form list of invariant descriptors (strings or structured)
- resource_limits: optional resource constraints
- replica_intent_hash: hex string hash of the intent being certified
- expected_receipt: optional acceptance witness
- attester_signatures: mapping signer_id -> signature (base64 or hex)
- issued_at: timestamp
"""
invariants: List[Any]
resource_limits: Optional[Dict[str, Any]] = None
replica_intent_hash: constr(min_length=1)
expected_receipt: Optional[Dict[str, Any]] = None
attester_signatures: Dict[str, str] = Field(default_factory=dict)
issued_at: datetime = Field(default_factory=datetime.utcnow)
class TraceEvent(BaseModel):
seq: int
timestamp: datetime
message: str
meta: Optional[Dict[str, Any]] = None
class ReplayBundle(BaseModel):
"""Deterministic ReplayBundle reference format.
Fields:
- trace: sequence of TraceEvent
- monitors: signed attestations produced by monitors
- evidence_root: a top-level digest (hex) that represents merkle/root of evidence
- artifacts: optional dict of artifact_name -> digest
"""
trace: List[TraceEvent]
monitors: Dict[str, str] = Field(default_factory=dict)
evidence_root: constr(min_length=1)
artifacts: Optional[Dict[str, str]] = None
class BondRecord(BaseModel):
escrow_id: str
issuer: str
stake_amount: float
policy_hash: Optional[str] = None
ttl: Optional[datetime] = None
created_at: datetime = Field(default_factory=datetime.utcnow)
status: str = "active" # active, settled, cancelled
class ClaimSubmission(BaseModel):
claim_id: str
evidence_root: str
claimant: str
timestamp: datetime = Field(default_factory=datetime.utcnow)
details: Optional[Dict[str, Any]] = None

10
test.sh
View File

@ -1,10 +1,10 @@
#!/usr/bin/env bash
set -euo pipefail
echo "Installing test dependencies..."
python3 -m pip install -q --upgrade pip
python3 -m pip install -q pydantic fastapi uvicorn pytest
echo "Running pytest..."
PYTHONPATH=src pytest -q
echo "Running tests..."
pytest -q
echo "Building package..."
python3 -m build
echo "All done."

View File

@ -1,15 +1,33 @@
import tempfile
import os
from idea199_replicasurety_economic_surety.ledger import SuretyLedger, Escrow
from idea199_replicasurety_economic_surety import ledger
from idea199_replicasurety_economic_surety.models import BondRecord, ClaimSubmission, ReplayBundle, TraceEvent
from datetime import datetime
def test_ledger_create_and_get(tmp_path):
path = tmp_path / "ledger.json"
ledger = SuretyLedger(path=str(path))
e = Escrow(escrow_id="e1", issuer="me", stake_amount=10.0, policy_hash="ph", ttl=3600)
ledger.create_escrow(e)
got = ledger.get_escrow("e1")
assert got is not None
assert got.issuer == "me"
ledger.settle_escrow("e1")
assert ledger.get_escrow("e1").status == "settled"
def test_create_and_get_bond():
br = BondRecord(
escrow_id="escrow-1",
issuer="alice",
stake_amount=100.0,
policy_hash="phash",
ttl=None,
)
r = ledger.create_bond(br)
assert r.escrow_id == "escrow-1"
got = ledger.get_bond("escrow-1")
assert got.issuer == "alice"
def test_submit_claim():
claim = ClaimSubmission(claim_id="claim-1", evidence_root="evidence123", claimant="bob")
r = ledger.submit_claim(claim)
assert r.claim_id == "claim-1"
def test_verify_replay():
trace = [
TraceEvent(seq=0, timestamp=datetime.utcnow(), message="a"),
TraceEvent(seq=1, timestamp=datetime.utcnow(), message="b"),
]
rb = ReplayBundle(trace=trace, monitors={}, evidence_root="r")
r = ledger.verify_replay(rb)
assert r["verdict"] == "ok"

31
tests/test_models.py Normal file
View File

@ -0,0 +1,31 @@
import json
from idea199_replicasurety_economic_surety.models import PoeticCert, ReplayBundle, TraceEvent
from idea199_replicasurety_economic_surety import crypto
from datetime import datetime
def test_poeticcert_roundtrip_and_signature():
priv, pub = crypto.generate_rsa_keypair()
cert = PoeticCert(
invariants=["no-privilege-escalation"],
replica_intent_hash="deadbeef",
)
# sign canonical bytes (here simple JSON)
b = cert.json().encode()
sig = crypto.sign_bytes(priv, b)
cert.attester_signatures["test-signer"] = sig.hex()
# verify
sig2 = bytes.fromhex(cert.attester_signatures["test-signer"])
assert crypto.verify_bytes(pub, sig2, b)
def test_replaybundle_structure_and_verifier_input():
trace = [
TraceEvent(seq=0, timestamp=datetime.utcnow(), message="start"),
TraceEvent(seq=1, timestamp=datetime.utcnow(), message="do work"),
]
rb = ReplayBundle(trace=trace, monitors={"m1": "sig"}, evidence_root="roothash")
s = rb.json()
parsed = ReplayBundle.parse_raw(s)
assert parsed.evidence_root == "roothash"