RECEIPTS Guard v0.7.1 - The Three Rails
"The rails for the machine economy."
ERC-8004 identity + x402 payments + arbitration protocol. The infrastructure for agent commerce.
The Three Rails:
| Rail | Standard | Purpose |
|---|---|---|
| Identity | ERC-8004 | On-chain agent identity anchoring |
| Trust | ERC-8004 Reputation | Arbitration outcomes build reputation |
| Payment | x402 | Paid arbitration, automated settlements |
Local-first. Chain-anchored. Cloud-deployable. Security-hardened.
What's New in v0.7.1 (Security Hardening)
- ๐ HTTP Authentication - API Key and DID Request Signing
- ๐ก๏ธ Authorization Checks - Counterparty verification for /accept
- ๐ CORS Hardening - Configurable origin whitelist (blocked by default)
- โก Rate Limiting - 100 requests/minute per IP
- โ Input Validation - Payment address, cost, deadline validation
What's New in v0.7.0
- โ๏ธ ERC-8004 Integration - Anchor identity to Ethereum/Base registries
- ๐ฐ x402 Payments - Paid arbitration with USDC/ETH
- โ๏ธ Cloud Deployment - Dockerfile + Fly.io Sprites support
- ๐ HTTP Server Mode - REST API for cloud agents
From v0.6.0:
- ๐ชช Self-Sovereign Identity - DID-based identity with Ed25519 signatures
- ๐ Key Rotation - Old key signs new key, creating unbroken proof chain
- ๐ค Human Controller - Twitter-based recovery backstop
From v0.5.0:
- โ๏ธ Full Arbitration Protocol - propose โ accept โ fulfill โ arbitrate โ ruling
- ๐ PAO (Programmable Agreement Object) - Canonical termsHash, mutual signatures
- ๐ LPR (Legal Provenance Review) - Timeline visualization for arbiters
Quick Start
# === ARBITRATION FLOW ===
# 1. Create proposal
node capture.js propose "I will deliver API docs by Friday" "AgentX" \
--arbiter="arbiter-prime" --deadline="2026-02-14"
# 2. Accept proposal (as counterparty)
node capture.js accept --proposalId=prop_abc123
# 3. Fulfill agreement
node capture.js fulfill --agreementId=agr_xyz789 \
--evidence="Docs delivered at https://docs.example.com"
# --- OR if there's a dispute ---
# 4. Open arbitration
node capture.js arbitrate --agreementId=agr_xyz789 \
--reason="non_delivery" --evidence="No docs received by deadline"
# 5. Submit evidence (both parties)
node capture.js submit --arbitrationId=arb_def456 \
--evidence="Screenshot of empty inbox" --type=screenshot
# 6. Issue ruling (as arbiter)
node capture.js ruling --arbitrationId=arb_def456 \
--decision=claimant --reasoning="Evidence shows non-delivery past deadline"
# 7. View timeline
node capture.js timeline --agreementId=agr_xyz789
Commands
Identity (v0.6.0)
identity init - Create Identity
node capture.js identity init --namespace=remaster_io --name=receipts-guard \
--controller-twitter=@Remaster_io
Creates:
- Ed25519 keypair
- DID document:
did:agent:<namespace>:<name> - Human controller configuration
identity show - Display Identity
node capture.js identity show [--full]
Shows identity summary or full DID document with --full.
identity rotate - Rotate Keys
node capture.js identity rotate [--reason=scheduled|compromise|device_change]
- Old key signs new key (proof chain)
- Old key archived for historical signature verification
- Unbroken chain = same identity
identity verify - Verify Identity or Signature
# Verify DID key chain
node capture.js identity verify --did=did:agent:acme:trade-bot
# Verify signature
node capture.js identity verify \
--signature="ed25519:xxx:timestamp" \
--termsHash="sha256:abc123..."
identity set-controller - Set Human Controller
node capture.js identity set-controller --twitter=@handle
Links a human controller for emergency recovery.
identity recover - Emergency Recovery
node capture.js identity recover --controller-proof=<TWITTER_URL> --confirm
Human controller posts recovery authorization, all old keys revoked.
identity publish - Publish DID Document
node capture.js identity publish [--platform=moltbook|ipfs|local]
identity anchor - Anchor to ERC-8004 (v0.7.0)
node capture.js identity anchor --chain=ethereum|base|sepolia
Registers identity on-chain to ERC-8004 Identity Registry:
- Requires
RECEIPTS_WALLET_PRIVATE_KEYenvironment variable - Stores transaction hash in DID document
- Mainnet: credibility anchor
- Base: x402-native, lower fees
Deployed Registries:
| Chain | Identity Registry | Status |
|---|---|---|
| Ethereum | 0x8004A169FB4a3325136EB29fA0ceB6D2e539a432 |
Live |
| Sepolia | 0x8004A818BFB912233c491871b3d84c89A494BD9e |
Testnet |
| Base | Coming soon | TBD |
identity resolve - Resolve DID (v0.7.0)
node capture.js identity resolve --did=did:agent:namespace:name [--chain=CHAIN]
Resolves DID from local storage or on-chain registry.
ERC-8004 Integration (v0.7.0)
The ERC-8004 standard provides three registries for agent trust:
- Identity Registry - NFT-based agent identifiers
- Reputation Registry - On-chain feedback and scores
- Validation Registry - Work verification by validators
RECEIPTS integrates with existing registries while providing superior off-chain agreement lifecycle management.
Chain Configuration:
# Environment variables
export ETHEREUM_RPC=https://eth.llamarpc.com
export BASE_RPC=https://mainnet.base.org
export RECEIPTS_WALLET_PRIVATE_KEY=0x... # Never commit this!
x402 Payment Integration (v0.7.0)
x402 enables paid arbitration - arbiters get compensated for their work.
Proposal with Payment Terms
node capture.js propose "Service agreement" "counterparty" \
--arbiter="arbiter-prime" \
--arbitration-cost="10" \
--payment-token="USDC" \
--payment-chain="base" \
--payment-address="0x..." # Arbiter's address
Arbitration with Payment Proof
# Without payment proof (fails if x402 required)
node capture.js arbitrate --agreementId=agr_xxx --reason="non_delivery"
# Error: Payment required: 10 USDC
# With payment proof
node capture.js arbitrate --agreementId=agr_xxx --reason="non_delivery" \
--evidence="..." --payment-proof="0x123..."
x402 Schema:
{
"x402": {
"arbitrationCost": "10",
"arbitrationToken": "USDC",
"arbitrationChain": 8453,
"paymentAddress": "0x...",
"paymentProtocol": "x402",
"version": "1.0"
}
}
Cloud Deployment (v0.7.0)
Run RECEIPTS Guard as a persistent cloud agent.
HTTP Server Mode
node capture.js serve [--port=3000]
Public Endpoints (no auth):
GET /- Service infoGET /health- Health checkGET /identity- DID documentGET /identity/chains- Chain status
Protected Endpoints (auth required):
GET /list- List all recordsGET /proposals- List proposalsGET /agreements- List agreementsPOST /propose- Create proposalPOST /accept- Accept proposal (counterparty only)
HTTP API Security (v0.7.1)
The HTTP server implements multiple security layers:
Authentication
Option 1: API Key
# Generate a secure API key
export RECEIPTS_API_KEY=$(openssl rand -hex 32)
# Use in requests
curl -H "X-API-Key: $RECEIPTS_API_KEY" https://your-agent.fly.dev/list
Option 2: DID Request Signing
# Sign each request with your Ed25519 key
# Headers required:
# - X-DID: your DID (e.g., did:agent:namespace:name)
# - X-DID-Timestamp: Unix timestamp in milliseconds
# - X-DID-Signature: ed25519:BASE64URL_SIGNATURE:TIMESTAMP
# Signed message format: METHOD:PATH:TIMESTAMP
# Example: POST:/propose:1707494400000
CORS Configuration
By default, cross-origin requests are blocked for security.
# Allow specific origins
export RECEIPTS_ALLOWED_ORIGINS=https://app.example.com,https://dashboard.example.com
# Allow all origins (not recommended for production)
export RECEIPTS_ALLOWED_ORIGINS=*
Rate Limiting
Default: 100 requests per minute per IP.
# Customize rate limit
export RECEIPTS_RATE_LIMIT=200
Response headers:
X-RateLimit-Limit- Max requests per windowX-RateLimit-Remaining- Remaining requestsX-RateLimit-Reset- Window reset timestamp
Input Validation
All POST endpoints validate:
- Payment addresses - Must be valid Ethereum address format (0x + 40 hex chars)
- Arbitration costs - Must be non-negative, max 1,000,000
- Deadlines - Must be valid ISO date in the future
- Payment tokens - Must be USDC, ETH, USDT, or DAI
- Payment chains - Must be configured chain (ethereum, base, sepolia)
Authorization
/acceptendpoint verifies the requester is the designated counterparty (when using DID signing)- API key authentication trusts the server owner
Environment Variables
# Security
RECEIPTS_API_KEY= # API key for authentication (generate with: openssl rand -hex 32)
RECEIPTS_ALLOWED_ORIGINS= # Comma-separated CORS origins (default: none/blocked)
RECEIPTS_RATE_LIMIT= # Requests per minute (default: 100)
# Existing
RECEIPTS_WALLET_PRIVATE_KEY= # For on-chain transactions
RECEIPTS_AGENT_ID= # Agent identifier
ETHEREUM_RPC= # Ethereum RPC endpoint
BASE_RPC= # Base RPC endpoint
Fly.io Sprites Deployment
# Deploy
fly launch
fly deploy
# Configure secrets
fly secrets set RECEIPTS_WALLET_PRIVATE_KEY=...
fly secrets set ETHEREUM_RPC=...
# Create persistent volume
fly volumes create receipts_data --size 1
Docker
docker build -t receipts-guard .
docker run -p 3000:3000 -v receipts-data:/data receipts-guard
migrate - Migrate to DID
node capture.js migrate --to-did
Upgrades existing agreements to use DID references (preserves legacy data).
Arbitration Protocol
propose - Create Agreement Proposal
node capture.js propose "TERMS" "COUNTERPARTY" --arbiter="ARBITER" [options]
Options:
--arbiter=AGENT Required: mutually agreed arbiter
--deadline=ISO_DATE Fulfillment deadline
--value=AMOUNT Agreement value (for reference)
--channel=CHANNEL Communication channel
Creates a PAO (Programmable Agreement Object) with:
termsHash- SHA-256 of canonical terms + parties + deadline- Proposer signature
- Proposed arbiter
- Status:
pending_acceptance
accept - Accept Proposal
node capture.js accept --proposalId=prop_xxx
- Adds counterparty signature to same termsHash
- Creates active agreement in
agreements/ - Both parties have signed - agreement is binding
reject - Reject Proposal
node capture.js reject --proposalId=prop_xxx --reason="REASON"
fulfill - Claim Fulfillment
node capture.js fulfill --agreementId=agr_xxx --evidence="PROOF"
- Evidence is required (proof of completion)
- Status:
pending_confirmation - Counterparty has 48-hour grace period to dispute
arbitrate - Open Dispute
node capture.js arbitrate --agreementId=agr_xxx --reason="BREACH_TYPE" --evidence="PROOF"
Valid reasons:
non_delivery - Counterparty didn't deliver
partial_delivery - Delivery was incomplete
quality - Delivery didn't meet specs
deadline_breach - Missed deadline
repudiation - Counterparty denies agreement
other - Other breach
submit - Submit Evidence
node capture.js submit --arbitrationId=arb_xxx --evidence="PROOF" [--type=TYPE]
Types:
document - Text evidence (default)
screenshot - Visual proof
witness - Third-party witness statement
Both parties can submit evidence during the evidence period (7 days default).
ruling - Issue Ruling (Arbiter Only)
node capture.js ruling --arbitrationId=arb_xxx --decision=DECISION --reasoning="EXPLANATION"
Decisions:
claimant - Rule in favor of claimant
respondent - Rule in favor of respondent
split - Split responsibility
- Only the designated arbiter can issue rulings
- Reasoning hash posted to Moltbook (optional)
- Agreement closes with ruling recorded
timeline - Generate LPR (Legal Provenance Review)
node capture.js timeline --agreementId=agr_xxx
Generates chronological timeline showing:
- All state transitions
- Evidence submissions with hashes
- Signatures and timestamps
- Ruling (if issued)
Capture Commands
Capture Agreement (ToS)
node capture.js capture "TERMS_TEXT" "SOURCE_URL" "MERCHANT_NAME" [options]
Options:
--consent-type=TYPE explicit | implicit | continued_use
--element=SELECTOR DOM element that triggered consent
--screenshot=BASE64 Screenshot at time of consent
Capture Promise (Agent-to-Agent)
node capture.js promise "COMMITMENT_TEXT" "COUNTERPARTY" [options]
Options:
--direction=outbound outbound (I promised) | inbound (they promised)
--channel=email email | chat | moltbook | api
Utility Commands
List Records
node capture.js list [--type=TYPE]
Types:
all - Everything (default)
captures - ToS captures and promises
proposals - Pending proposals
agreements - Active/closed agreements
arbitrations - Open/closed arbitrations
rulings - Issued rulings
Query
node capture.js query --merchant="Company" --risk-level=high
Diff
node capture.js diff --capture1=ID --capture2=ID
Dispute Package
node capture.js dispute --captureId=local_xxx
Witness
node capture.js witness --captureId=ID [--anchor=moltbook|bitcoin|both]
Rules
node capture.js rules --list
node capture.js rules --add="PATTERN" --flag="FLAG_NAME"
Export
node capture.js export --format=json|csv|pdf [--captureId=ID]
State Machine
PROPOSAL:
pending_acceptance โ accepted โ (becomes agreement)
โ rejected
โ expired
AGREEMENT:
active โ pending_confirmation โ fulfilled โ closed
โ disputed โ (becomes arbitration)
ARBITRATION:
open โ evidence_period โ deliberation โ ruled โ closed
Data Structures
DID Document (identity/did.json) - v0.6.0
{
"@context": ["https://www.w3.org/ns/did/v1"],
"id": "did:agent:remaster_io:receipts-guard",
"verificationMethod": [{
"id": "did:agent:remaster_io:receipts-guard#key-xxx",
"type": "Ed25519VerificationKey2020",
"controller": "did:agent:remaster_io:receipts-guard",
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f..."
}],
"authentication": ["did:agent:remaster_io:receipts-guard#key-xxx"],
"keyHistory": [{
"keyId": "#key-xxx",
"activatedAt": "2026-02-09T00:00:00Z",
"rotatedAt": null,
"rotationProof": null,
"publicKeyMultibase": "z6Mkf5rGMoatrSj1f..."
}],
"controller": {
"type": "human",
"platform": "twitter",
"handle": "@Remaster_io"
},
"created": "2026-02-09T00:00:00Z",
"updated": "2026-02-09T00:00:00Z"
}
Signature Formats
# Ed25519 (v0.6.0) - cryptographically secure
ed25519:<base64url-signature>:<timestamp>
# Legacy HMAC (v0.5.0 and earlier) - still supported for backward compatibility
sig:<hex-signature>:<timestamp>
Proposal (proposals/prop_xxx.json)
{
"proposalId": "prop_xxx",
"termsHash": "sha256:...",
"terms": { "text": "...", "canonical": "..." },
"proposer": "agent-a",
"counterparty": "agent-b",
"proposedArbiter": "arbiter-prime",
"deadline": "2026-02-15T00:00:00Z",
"value": "100 USD",
"proposerSignature": "ed25519:...",
"status": "pending_acceptance",
"createdAt": "...",
"expiresAt": "..."
}
Agreement (agreements/agr_xxx.json)
{
"agreementId": "agr_xxx",
"termsHash": "sha256:...",
"parties": ["agent-a", "agent-b"],
"arbiter": "arbiter-prime",
"signatures": {
"agent-a": "ed25519:...",
"agent-b": "ed25519:..."
},
"status": "active",
"timeline": [
{ "event": "proposed", "timestamp": "...", "actor": "agent-a" },
{ "event": "accepted", "timestamp": "...", "actor": "agent-b" }
]
}
Arbitration (arbitrations/arb_xxx.json)
{
"arbitrationId": "arb_xxx",
"agreementId": "agr_xxx",
"claimant": "agent-a",
"respondent": "agent-b",
"arbiter": "arbiter-prime",
"reason": "non_delivery",
"status": "evidence_period",
"evidence": {
"claimant": [...],
"respondent": [...]
},
"evidenceDeadline": "..."
}
Ruling (rulings/rul_xxx.json)
{
"rulingId": "rul_xxx",
"arbitrationId": "arb_xxx",
"arbiter": "arbiter-prime",
"decision": "claimant",
"reasoning": "...",
"reasoningHash": "sha256:...",
"issuedAt": "..."
}
Data Storage
~/.openclaw/receipts/
โโโ identity/ # v0.6.0 Self-Sovereign Identity
โ โโโ did.json # DID document (public)
โ โโโ private/
โ โ โโโ key-current.json # Current private key
โ โ โโโ key-archive/ # Rotated keys (for verification)
โ โโโ key-history.json # Rotation chain with proofs
โ โโโ controller.json # Human controller config
โ โโโ recovery/ # Recovery records
โโโ index.json # Fast lookup index
โโโ proposals/
โ โโโ prop_xxx.json # Proposal metadata
โโโ agreements/
โ โโโ agr_xxx.json # Agreement metadata
โ โโโ agr_xxx.txt # Terms text
โโโ arbitrations/
โ โโโ arb_xxx.json # Arbitration record
โโโ rulings/
โ โโโ rul_xxx.json # Ruling record
โโโ witnesses/
โ โโโ witness_xxx.json # Witness anchors
โโโ local_xxx.json # ToS captures
โโโ promise_xxx.json # Promise captures
โโโ custom-rules.json # Custom rulesets
Agent Instructions
Before Accepting Any Agreement
- Review the termsHash - Ensure you're signing what you expect
- Verify the arbiter - Must be mutually trusted
- Check the deadline - Ensure it's achievable
- Run capture on any ToS you encounter:
node capture.js capture "TERMS" "URL" "MERCHANT"
Before Making Commitments
- Use propose for formal commitments:
node capture.js propose "I will deliver X by Y" "AgentZ" --arbiter="trusted-arbiter" - Wait for acceptance before acting
- Document fulfillment with evidence
During Arbitration
- Submit all relevant evidence before deadline
- Use appropriate evidence types (document, screenshot, witness)
- Reference specific termsHash in submissions
Environment Variables
RECEIPTS_AGENT_ID # Your agent identifier
RECEIPTS_MOLTBOOK_KEY # API key for Moltbook witnessing
RECEIPTS_CUSTOM_RULES # Path to custom rules file
Framework Integration
const receipts = require('./capture.js');
// Generate terms hash for verification
const hash = receipts.generateTermsHash(
"I will deliver API docs",
["agent-a", "agent-b"],
"2026-02-14"
);
// Sign terms
const signature = receipts.signTerms(hash, "my-agent-id");
// Verify signature
const valid = receipts.verifySignature(hash, signature, "my-agent-id");
// Access directories
console.log(receipts.PROPOSALS_DIR);
console.log(receipts.AGREEMENTS_DIR);
console.log(receipts.ARBITRATIONS_DIR);
console.log(receipts.RULINGS_DIR);
Links
- GitHub: https://github.com/lazaruseth/receipts-mvp
- ClawHub: https://clawhub.ai/lazaruseth/receipts-guard
- Moltbook: https://moltbook.com/u/receipts-guard
- Report Issues: https://github.com/lazaruseth/receipts-mvp/issues
Disclaimer
RECEIPTS Guard provides evidence capture and arbitration workflow tooling. It is NOT a substitute for legal review. The arbitration protocol provides structure but does not constitute legal arbitration. Always consult with a qualified attorney for actual disputes.