Policy-bound agent wallets between ERC-8004 identity, ENSIP-25 discovery, and x402 payments. Spending rules live on IPFS and ENS; services call canAgentSpend() before authorizing a transfer.
| Service | URL |
|---|---|
| API | https://api.vcrprotocol.xyz |
| Health | https://api.vcrprotocol.xyz/api/health |
| VM IP | 20.219.105.217 (DNS: api → A record) |
| Frontend | Vercel — VITE_API_URL=https://api.vcrprotocol.xyz |
Expected health response:
{ "status": "ok", "db": "connected", "service": "VCR Protocol API" }flowchart LR
subgraph clients [Clients]
UI[Vercel React UI]
SVC[Integrator / x402 service]
end
subgraph azure [Azure South India]
API[API :3001]
WK[register-worker]
end
subgraph data [Managed data]
Atlas[(MongoDB Atlas)]
Upstash[(Upstash Redis)]
end
subgraph chain [Ethereum Sepolia]
ENS[ENS text records]
ERC[ERC-8004 registry]
end
subgraph external [External APIs]
IPFS[Pinata IPFS]
BG[BitGo]
RPC[Alchemy RPC]
end
UI --> API
SVC --> API
API --> Atlas
API --> Upstash
WK --> Upstash
API --> ENS
API --> ERC
API --> IPFS
API --> BG
API --> RPC
Policy flow: Owner publishes policy JSON → Pinata CID → ENS vcr.policy → verifier reads ENS + IPFS → canAgentSpend() → allow/deny.
| Item | Value |
|---|---|
| Cloud | Microsoft Azure |
| Region | southindia (South India) |
| Resource group | rg-vcr-protocol-prod-in |
| VM | vcr-api-prod |
| SKU | Standard_B2als_v2 (4 GiB RAM + 4 GiB swap) |
| Public IP | 20.219.105.217 |
| OS | Ubuntu 22.04, Docker Compose |
| Containers | api, register-worker, caddy (TLS) |
| Domain | api.vcrprotocol.xyz (Let's Encrypt via Caddy) |
MongoDB and Redis are not run on the VM in production. They are provided by MongoDB Atlas and Upstash via server/.env.
Use this before calling production “live”:
-
server/.envfilled andnpm run validate-envpasses -
curl https://api.vcrprotocol.xyz/api/healthreturnsdb: connected - Vercel has
VITE_API_URL=https://api.vcrprotocol.xyz - GitHub production environment secrets configured (see below)
-
PRIVATE_KEYEOA ownsENS_BASE_DOMAIN(e.g.vcrtcorp.eth) - BitGo enterprise + Pinata keys are production-capable
-
.envandserver/agents/*.jsonare never committed
Production runs on Azure Kubernetes Service in South India. API: https://api.vcrprotocol.xyz
Details: infra/azure/README.md
| Workflow | Trigger | Purpose |
|---|---|---|
| Deploy Production (AKS) | Push main |
ACR build, Key Vault sync, Helm (atomic), health check, Trivy |
| Bootstrap AKS Platform | Manual | ingress, cert-manager, ESO (new cluster only) |
| Terraform Plan | PR | Infra change review |
| Security | Weekly + PR | CodeQL, npm audit |
| CI | PR / push | Lint, test, client build, Docker build |
Secrets: Settings → Environments → production → Environment secrets
AZURE_CLIENT_ID, AZURE_TENANT_ID, AZURE_SUBSCRIPTION_ID (from Terraform outputs — OIDC, no client secret).
See docs/PRODUCTION.md and infra/azure/README.md.
| Secret | Description |
|---|---|
MONGODB_URI |
MongoDB Atlas connection string |
REDIS_URL |
Upstash Redis URL (rediss://...) |
PRIVATE_KEY |
0x… ENS owner / signer EOA |
SEPOLIA_RPC_URL |
Sepolia HTTPS RPC (e.g. Alchemy) |
PINATA_JWT |
Pinata API JWT |
PINATA_GATEWAY |
Gateway host only, no https:// |
PINATA_KEY |
Pinata scoped key |
PINATA_SECRET |
Pinata scoped secret |
BITGO_ACCESS_TOKEN |
BitGo v2x… token |
BITGO_ENTERPRISE_ID |
BitGo enterprise ID |
BITGO_WALLET_PASSPHRASE |
BitGo wallet passphrase |
PIMLICO_API_KEY |
Pimlico API key |
| Secret | Description |
|---|---|
VCR_REGISTRY_ADDRESS |
On-chain registry contract |
ENS_BASE_DOMAIN |
e.g. vcrtcorp.eth |
ALCHEMY_API_KEY |
Alchemy key |
MAINNET_RPC_URL |
Mainnet RPC |
ENS_NAME |
Default ENS name |
BITGO_WALLET_ID |
Pre-created wallet |
FILEVERSE_API_URL / FILEVERSE_API_KEY |
Fileverse integration |
DEMO_RECIPIENT_ADDRESS |
Demo paywall recipient |
ENS_HANDOFF_WAIT_TIMEOUT_MS |
Registration timeout (ms) |
Re-run: Actions → Deploy Production (AKS) → Run workflow.
cd client
cp .env.example .env.local # or set in Vercel dashboard| Variable | Production value |
|---|---|
VITE_API_URL |
https://api.vcrprotocol.xyz |
npm install
npm run buildDeploy client/dist to Vercel (or any static host). client/vercel.json includes SPA rewrites.
API base URL is centralized in client/src/config.ts (dev defaults to http://localhost:3001).
Copy from server/.env.example. Validate:
cd server && npm run validate-envRequired: BITGO_ACCESS_TOKEN, BITGO_ENTERPRISE_ID, PINATA_JWT, PINATA_GATEWAY, PIMLICO_API_KEY, PRIVATE_KEY, SEPOLIA_RPC_URL, MONGODB_URI
Production data stores: set MONGODB_URI (Atlas) and REDIS_URL (Upstash). Do not rely on local Docker mongo/redis in prod.
Per-agent data (BITGO_WALLET_ID, AGENT_ID, POLICY_CID, etc.) belongs in server/agents/<name>.json, not in .env.
| Variable | Purpose |
|---|---|
VITE_API_URL |
Backend base URL, no trailing slash |
- Never commit
.env, private keys, orserver/agents/*.json/server/creds/* - Rotate credentials if they were exposed in chat or logs
- API is served over HTTPS (nginx ingress + Let's Encrypt on AKS)
- Secrets live in Azure Key Vault; pods load them via External Secrets Operator
- BitGo wallet policies lock after 48 hours — plan recipient/token lists carefully
curl -s https://api.vcrprotocol.xyz/api/health | jq .
kubectl get pods -n vcr-protocol
kubectl logs -n vcr-protocol deploy/vcr-api --tail=50# Terminal 1 — API
cd server && cp .env.example .env && npm install && npm run dev
# Terminal 2 — UI
cd client && cp .env.example .env.local && npm install && npm run devOptional Docker stack with local Mongo + Redis:
docker compose -f docker-compose.local.yml --env-file server/.env up -d| Endpoint | Method | Description |
|---|---|---|
/api/health |
GET | Health + database status |
/api/policy |
POST | Create and pin policy to IPFS |
/api/policy/:ensName |
GET | Resolve policy via ENS |
/api/verify |
POST | Run canAgentSpend() |
/api/verify/record |
POST | Record an allowed spend |
/api/register |
POST | Register agent (ERC-8004) |
/api/wallet |
POST | Create BitGo wallet |
/api/documents |
POST | Create versioned dDoc |
/api/demo/* |
* | Paywall / simulation demos |
Route implementations: server/src/routes/.
├── client/ React + Vite dashboard
├── server/ Express API, workers, Mongoose models
├── sdk/ @vcrprotocol/vcrsdk-2
├── contracts/ VCRPolicyRegistry (Hardhat / Sepolia)
├── infra/azure/ Azure ops docs
├── infra/helm/ Production Helm chart (AKS)
├── infra/platform/ ingress / cert-manager / ESO config
├── infra/terraform/ Key Vault + identity (Terraform)
├── docker-compose.local.yml Local Mongo + Redis + API
├── docs/PRODUCTION.md Ops runbook, OIDC, rollback, alerts
└── .github/workflows/ CI, deploy, bootstrap, security, terraform
| Layer | Stack |
|---|---|
| API | Express 5, TypeScript, Mongoose, BullMQ, viem |
| Storage | MongoDB Atlas, Upstash Redis, Pinata IPFS |
| Wallets | BitGo v3, Pimlico |
| Chain | Sepolia, ENS, ERC-8004 |
| UI | React 19, Vite, Tailwind |
| Infra | Azure VM, Docker Compose, GitHub Actions |
MIT