Introduction
# 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
```bash # === 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 ```bash 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 ```bash node capture.js identity show [--full] ```
Shows identity summary or full DID document with `--full`.
#### `identity rotate` - Rotate Keys ```bash 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 ```bash # 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 ```bash node capture.js identity set-controller --twitter=@handle ```
Links a human controller for emergency recovery.
#### `identity recover` - Emergency Recovery ```bash node capture.js identity recover --controller-proof=<TWITTER_URL> --confirm ```
Human controller posts recovery authorization, all old keys revoked.
#### `identity publish` - Publish DID Document ```bash node capture.js identity publish [--platform=moltbook|ipfs|local] ```
#### `identity anchor` - Anchor to ERC-8004 (v0.7.0) ```bash node capture.js identity anchor --chain=ethereum|base|sepolia ```
Registers identity on-chain to ERC-8004 Identity Registry: - Requires `RECEIPTS_WALLET_PRIVATE_KEY` environment 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) ```bash 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:
1. **Identity Registry** - NFT-based agent identifiers 2. **Reputation Registry** - On-chain feedback and scores 3. **Validation Registry** - Work verification by validators
RECEIPTS integrates with existing registries while providing superior off-chain agreement lifecycle management.
**Chain Configuration:** ```bash # 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 ```bash 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 ```bash # 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:** ```json { "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 ```bash node capture.js serve [--port=3000] ```
**Public Endpoints (no auth):** - `GET /` - Service info - `GET /health` - Health check - `GET /identity` - DID document - `GET /identity/chains` - Chain status
**Protected Endpoints (auth required):** - `GET /list` - List all records - `GET /proposals` - List proposals - `GET /agreements` - List agreements - `POST /propose` - Create proposal - `POST /accept` - Accept proposal (counterparty only)
---
### HTTP API Security (v0.7.1)
The HTTP server implements multiple security layers:
#### Authentication
**Option 1: API Key** ```bash # 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** ```bash # 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.
```bash # 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.
```bash # Customize rate limit export RECEIPTS_RATE_LIMIT=200 ```
Response headers: - `X-RateLimit-Limit` - Max requests per window - `X-RateLimit-Remaining` - Remaining requests - `X-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
- `/accept` endpoint verifies the requester is the designated counterparty (when using DID signing) - API key authentication trusts the server owner
#### Environment Variables
```bash # 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 ```bash # 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 ```bash docker build -t receipts-guard . docker run -p 3000:3000 -v receipts-data:/data receipts-guard ```
---
#### `migrate` - Migrate to DID ```bash node capture.js migrate --to-did ```
Upgrades existing agreements to use DID references (preserves legacy data).
---
### Arbitration Protocol
#### `propose` - Create Agreement Proposal ```bash 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 ```bash 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 ```bash node capture.js reject --proposalId=prop_xxx --reason="REASON" ```
#### `fulfill` - Claim Fulfillment ```bash 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 ```bash 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 ```bash 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) ```bash 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) ```bash 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) ```bash 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) ```bash 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 ```bash 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 ```bash node capture.js query --merchant="Company" --risk-level=high ```
#### Diff ```bash node capture.js diff --capture1=ID --capture2=ID ```
#### Dispute Package ```bash node capture.js dispute --captureId=local_xxx ```
#### Witness ```bash node capture.js witness --captureId=ID [--anchor=moltbook|bitcoin|both] ```
#### Rules ```bash node capture.js rules --list node capture.js rules --add="PATTERN" --flag="FLAG_NAME" ```
#### Export ```bash 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 ```json { "@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`) ```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`) ```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`) ```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`) ```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
1. **Review the termsHash** - Ensure you're signing what you expect 2. **Verify the arbiter** - Must be mutually trusted 3. **Check the deadline** - Ensure it's achievable 4. **Run capture** on any ToS you encounter: ```bash node capture.js capture "TERMS" "URL" "MERCHANT" ```
### Before Making Commitments
1. **Use propose** for formal commitments: ```bash node capture.js propose "I will deliver X by Y" "AgentZ" --arbiter="trusted-arbiter" ``` 2. **Wait for acceptance** before acting 3. **Document fulfillment** with evidence
### During Arbitration
1. **Submit all relevant evidence** before deadline 2. **Use appropriate evidence types** (document, screenshot, witness) 3. **Reference specific termsHash** in submissions
## Environment Variables
```bash RECEIPTS_AGENT_ID # Your agent identifier RECEIPTS_MOLTBOOK_KEY # API key for Moltbook witnessing RECEIPTS_CUSTOM_RULES # Path to custom rules file ```
## Framework Integration
```javascript 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.