Skip to content

naory/parker-app

Repository files navigation

Parker 🅿️

Decentralized parking management powered by blockchain, the x402 payment protocol (EVM + XRPL rails), and multi-currency Stripe checkout.

Motivation

Most parking lots today are fully automated: they scan license plates at entry and exit and charge the driver's credit card at the gate. Many lots also offer integrated apps to streamline payment. Yet the experience remains fragmented and frustrating. Some lots issue physical cards with barcodes or QR codes; others don't. To pay via app, drivers must scan a QR code — which often fails during peak hours. Some lots still require scanning the card at exit even after the driver has already paid through the app. Parker addresses these broken flows by moving parking onto the blockchain: tickets become NFTs, payments run on-chain via x402, and verification is instant — no cards, no QR scans, no gate confusion.

Overview

Country operator runs one deployment; lots are per-operator configs.

Parker replaces fragmented centralized parking app flows (e.g., municipal/operator apps such as Pango, EasyPark, or RingGo) with a trustless, blockchain-based system. Parking tickets are NFTs, payments happen via x402 (Base or XRPL) or Stripe (credit card) — each lot configures its own local currency and accepted payment methods. Verification is instant — no more "communication errors" at the gate.

For the architectural rationale, see docs/WHY_BLOCKCHAIN.md. For operational and fallback scenarios, see docs/use-cases.md (including §21 Policy & Settlement Enforcement). For policy lifecycle (Grant → Decision → Enforcement), unit conventions, and env vars, see docs/policy-lifecycle.md.

White-Label Deployment Model

Parker is multi-country and currency-agnostic at the platform level. In practice, each operator scopes its own deployment to a target market (single country or region) and configures lots within that deployment.

The DEPLOYMENT_COUNTRIES environment variable controls:

  • Driver registration — only countries in the deployment are shown; single-country deployments auto-select and hide the picker
  • ALPR — plate format validation is restricted to the deployment's country patterns
  • Currency & payments — each lot configures its own currency, but all lots in a deployment typically share the same local currency and FX rate
# Single-country deployment (Israel)
DEPLOYMENT_COUNTRIES=IL

# Regional deployment (EU)
DEPLOYMENT_COUNTRIES=DE,FR,ES,IT,NL,GB,AT,BE

How It Works

                         ┌───────────────────┐
                         │   Hedera (NFTs)   │
                         │   HTS Token Svc   │
                         └────────▲──────────┘
                                  │
┌─────────────┐         ┌────────┴─────────┐         ┌────────────┐
│  Driver App  │◄───────►│   Parker API     │◄───────►│  Gate App  │
│  (Wallet)    │         │  (Express.js)    │         │  (Lot Ops) │
└──────┬──────┘         └───────┬──────────┘         └────────────┘
       │                        │
       │                        ▼
       │              ┌────────────────────┐
       │              │   Policy Layer      │
       │              │  (caps/allowlists)  │
       │              └─────────┬──────────┘
       │                        │
       ▼                        ▼
┌──────────────┐        ┌──────────────┐
│ x402 rail(s) │        │    Stripe    │
│ Base / XRPL  │        │ (Card/local) │
└──────────────┘        └──────────────┘

Hedera-first + dual-rail architecture (with optional Base components):

  • Hedera — Parking session NFTs via native Token Service (mint on entry, burn on exit)
  • x402 crypto rail — settlement can run on Base (EVM) or XRPL (selected via X402_NETWORK)
  • Base Sepolia (optional per deployment) — DriverRegistry sync and optional EVM x402 settlement
  • Stripe — Credit card payments in the lot's local currency (any Stripe-supported currency)

Entry Flow

  1. Car arrives at gate
  2. Gate camera captures plate image, ALPR extracts plate number via Google Vision API
  3. API checks if plate belongs to a registered driver
  4. Parking NFT minted on Hedera via HTS (AES-256-GCM encrypted metadata carrying plateHash, lot ID, entry time) — write-ahead: the on-chain NFT is the authoritative proof of entry
  5. Session created in DB, WebSocket notifies driver app in real-time
  6. Gate opens

Exit Flow

  1. Car approaches exit, plate scanned again
  2. System finds active parking session and calculates fee in the lot's local currency
  3. API returns payment options based on lot config and policy evaluation:
    • Policy decision — evaluates caps (per-tx/session/day in stablecoin minor units), lot/geo/rail/asset allowlists (XRP, IOUs e.g. USDC/RLUSD, EVM ERC20), and risk signals; may require explicit approval. Decision is bound to the payment intent (decisionId).
      • Allowlist semantics are strict: undefined = no restriction, [] = deny-all, [values] = restrict to listed values.
    • x402 (crypto) — fee converted via FX to stablecoin; payment proof verified per selected network (EVM tx hash or XRPL tx hash). On XRPL, after verification the settlement is enforced against the decision (amount ≤ per-tx cap, same rail/asset); if enforcement fails, exit returns 403 and session is not closed. XRPL UX is Xaman-first with manual tx-hash fallback.
    • Stripe (card) — Stripe Checkout session created in the lot's currency; driver redirected to Stripe-hosted page; webhook confirms payment
  4. On payment confirmation (either rail): parking NFT burned on Hedera, session closed in DB
  5. Gate opens automatically, driver app notified via WebSocket

Resilience: On-Chain vs Off-Chain

Following the Hedera pragmatic design patterns and the same hybrid model used by MINGO Tickets, Parker uses a layered resilience strategy:

Layer Source When
1. PostgreSQL Fast path for all operations Default — DB is up
2. Hedera Mirror Node Read-only fallback — verifies NFT exists + reads entry metadata DB unreachable
3. Gate-side cache Local session cache built from WebSocket events Both DB and Mirror Node down

Why not make Hedera the primary? Blockchain consensus is fast (~3-5s on Hedera) but PostgreSQL is faster (~1ms). At a busy parking gate, every second matters. The DB handles the operational speed; Hedera provides the trust guarantee and fallback. This matches how MINGO uses Hedera as an "invisible trust layer" rather than the operational database.

Key design principle: The Hedera NFT is minted before the DB write on entry (write-ahead). This means the on-chain record is always the leading indicator — if the DB loses a record, the NFT on Hedera proves the car is parked. See SPEC.md §11 for the full resilience architecture.

Architecture

The app has three main components:

🚗 Driver App (PWA)

  • Register with license plate, country, car make/model — off-chain via API, with optional on-chain sync to DriverRegistry on Base
  • Coinbase Smart Wallet integration (passkey-based, no seed phrase)
  • Live dashboard with active parking session card (lot name, address with Google Maps link, real-time duration timer + estimated cost)
  • Full parking history with date, lot, duration, fee, NFT token ID
  • Profile page with vehicle details and wallet address
  • Real-time WebSocket updates when sessions start/end

🚧 Gate App (PWA)

  • Camera feed with ALPR overlay — captures frame, sends to scan API, gets plate back
  • Lot name and address displayed in header (fetched from lot status API)
  • Entry/exit mode toggle with manual plate input fallback
  • Live gate status indicator (open/closed) with operation result feedback
  • Session manager — searchable table of active sessions with live duration and estimated fees
  • Operator dashboard — lot occupancy, active session count, average duration
  • Lot settings page — configure pricing (rate/hr, billing increment, daily cap), capacity, address
  • WebSocket connection with live status indicator
  • Offline-capable: local session cache built from WebSocket events — if the API is unreachable, the gate can still validate exits from its cache and open the gate (payment deferred)

🔧 API Server

  • Express.js with PostgreSQL for off-chain indexing
  • ALPR pipeline via @parker/alpr (Google Cloud Vision)
  • Hedera integration via @parker/hedera (@hashgraph/sdk) — mints parking NFTs on entry, burns on exit
  • Optional Base integration via viem — DriverRegistry reads/sync on Base Sepolia
  • Multi-currency payment — each lot defines its own currency (USD, EUR, GBP, etc.) and accepted payment methods
  • Policy layer — entry grant (lot/geo/rail/asset allowlists); payment decision at exit (caps in stablecoin minor, rail/asset); settlement enforcement on XRPL (re-check decision vs verified transfer); policy events stored for audit (policy_events, policy_grants, decision payload by decisionId)
  • x402 payment middleware — returns HTTP 402 with crypto amount (FX-converted from local currency) after policy evaluation; verifies payment proof on retry via network-aware adapters (EVM + XRPL)
  • Stripe Checkout — creates payment sessions in the lot's local currency; webhook-driven session closure
  • Pricing service — currency-agnostic FX conversion via configurable rates (FX_RATE_{FROM}_{TO} env vars)
  • WebSocket server for real-time gate and driver events
  • Full CRUD for drivers, sessions, and lots

Tech Stack

Layer Technology
Monorepo pnpm workspaces + Turborepo
Frontend Next.js 14 (PWA, mobile-first, Tailwind CSS)
Driver Wallet Coinbase Smart Wallet via wagmi
Payments (crypto) x402 protocol (Base EVM and XRPL settlement rails)
Payments (card) Stripe Checkout (any Stripe-supported currency)
Parking NFTs Hedera Token Service (native HTS, @hashgraph/sdk)
Driver Registry (optional) Solidity 0.8.20 + Hardhat (Base Sepolia)
ALPR Google Cloud Vision API
Backend Node.js + Express + TypeScript
Database PostgreSQL 16 (Docker)
Real-time WebSocket (ws)
Blockchain Clients @hashgraph/sdk (Hedera) + viem (Base)

Quick Start

Prerequisites

  • Node.js 20+ (see .nvmrc)
  • pnpm 9+
  • Docker (for PostgreSQL)

Setup

# Install dependencies
pnpm install

# Start PostgreSQL (creates schema + seeds demo data)
docker compose -f infra/docker-compose.yml up -d

# Copy environment files
cp apps/api/.env.example apps/api/.env
cp apps/driver/.env.example apps/driver/.env
cp apps/gate/.env.example apps/gate/.env

# Set deployment country (controls ALPR plate format + driver registration)
# Edit each .env and set DEPLOYMENT_COUNTRIES to your target market, e.g.:
#   DEPLOYMENT_COUNTRIES=IL          (Israel)
#   DEPLOYMENT_COUNTRIES=US          (United States)
#   DEPLOYMENT_COUNTRIES=DE,FR,ES    (EU region)

# Start all apps in dev mode
pnpm dev

This starts:

  • API on http://localhost:3001
  • Driver app on http://localhost:3000
  • Gate app on http://localhost:3002

Secrets & Key Management (Production)

For local development, .env files are convenient. For production, inject secrets at runtime from a managed secret store.

  • HashiCorp Vault (example):
    export HEDERA_PRIVATE_KEY="$(vault kv get -field=HEDERA_PRIVATE_KEY secret/parker/prod)"
    export NFT_ENCRYPTION_KEY="$(vault kv get -field=NFT_ENCRYPTION_KEY secret/parker/prod)"
    pnpm --filter api start
  • AWS Secrets Manager (example):
    export HEDERA_PRIVATE_KEY="$(aws secretsmanager get-secret-value --secret-id parker/prod --query 'SecretString' --output text | jq -r '.HEDERA_PRIVATE_KEY')"
    export NFT_ENCRYPTION_KEY="$(aws secretsmanager get-secret-value --secret-id parker/prod --query 'SecretString' --output text | jq -r '.NFT_ENCRYPTION_KEY')"
    pnpm --filter api start
  • Doppler (example):
    doppler run -- pnpm --filter api start

Never store production private keys on developer laptops, in git, or in plaintext .env files. Rotate keys after any suspected exposure.

Seed Data

The database is auto-seeded with two demo lots and a test driver. Each lot has its own currency, rates, and payment methods — see apps/api/src/db/seed.sql for details.

The system is fully currency-agnostic — each lot configures its own ISO 4217 currency and rates. Seed data uses sample values for demonstration.

Plates are stored in normalized form (alphanumeric, no dashes). The API normalizes all incoming plates automatically, so 12-345-67, 12 345 67, and 1234567 all resolve to the same driver.

Try It Now (Seed Data)

Use the default seeded values:

  • lotId=lot-01
  • plateNumber=1234567
# Entry (starts session + mints Hedera HTS NFT when configured)
curl -X POST http://localhost:3001/api/gate/entry \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: entry-lot01-1234567-001" \
  -d '{"plateNumber":"1234567","lotId":"lot-01"}'

# Exit (returns fee + payment options; session closes after payment confirmation)
curl -X POST http://localhost:3001/api/gate/exit \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: exit-lot01-1234567-001" \
  -d '{"plateNumber":"1234567","lotId":"lot-01"}'

Where to look:

  • Gate UI: http://localhost:3002 (live entry/exit status + cache badge)
  • Driver UI: http://localhost:3000 (active session, payment flow, history)
  • Hedera NFT: in Driver history, click the Hashscan link (set NEXT_PUBLIC_HEDERA_TOKEN_ID in apps/driver/.env to enable links)

Hedera Setup (Parking NFTs)

# 1. Create a Hedera testnet account at https://portal.hedera.com/register
# 2. Add credentials to apps/api/.env:
#      HEDERA_ACCOUNT_ID=0.0.xxxxx
#      HEDERA_PRIVATE_KEY=302e...
#      HEDERA_NETWORK=testnet

# 3. Create the NFT collection on Hedera:
pnpm --filter @parker/hedera setup

# 4. Copy the output HEDERA_TOKEN_ID into apps/api/.env

Payment Configuration

Parker supports two payment rails per lot, both optional:

Stripe (credit card) — charges in the lot's configured currency (USD, EUR, GBP, etc.):

# Add to apps/api/.env:
STRIPE_SECRET_KEY=sk_test_...
STRIPE_WEBHOOK_SECRET=whsec_...
STRIPE_SUCCESS_URL=http://localhost:3000/payment/success
STRIPE_CANCEL_URL=http://localhost:3000/payment/cancel

x402 (crypto rails) — converts the lot's local currency fee via FX and verifies settlement proof on the selected rail:

# Add to apps/api/.env:
X402_STABLECOIN=USDC
X402_NETWORK=base-sepolia
LOT_OPERATOR_WALLET=0x...

# For XRPL settlement (required when X402_NETWORK starts with "xrpl:")
XRPL_RPC_URL=wss://s.altnet.rippletest.net:51233
XAMAN_API_URL=https://xumm.app
XAMAN_API_KEY=...
XAMAN_API_SECRET=...
# Required for non-XRP XRPL assets (e.g., RLUSD IOU):
XRPL_ISSUER=r...

# FX rates (only needed when lot currency differs from stablecoin base):
FX_RATE_EUR_USD=1.08
FX_RATE_GBP_USD=1.27

Supported examples:

  • X402_NETWORK=base-sepolia (EVM, ERC-20 transfer verification)
  • X402_NETWORK=xrpl:testnet (XRPL, tx-hash verification via adapter)

Branding note: Xaman logo assets used in the UI are sourced from the official XRPL Labs branding repository: https://github.com/XRPL-Labs/Xaman-Branding

Branding note: Coinbase wallet branding should be sourced from Coinbase official brand/press assets: https://www.coinbase.com/press

Each lot's currency and paymentMethods are stored in the database and can be updated via PUT /api/gate/lot/:lotId.

Smart Contracts (Base — DriverRegistry)

# Compile contracts
pnpm contracts:compile

# Run tests
pnpm contracts:test

# Deploy DriverRegistry to Base Sepolia (requires PRIVATE_KEY in contracts/.env)
pnpm contracts:deploy

Testing (Vitest)

The workspace uses Vitest as the single test runner for all Node packages and the API app (contracts use Hardhat). Do not mix runners (e.g. no node --test alongside Vitest in the same package).

Test layout:

  • Packages (unit): packages/<name>/test/*.test.ts
  • API (integration): apps/api/test/*.test.ts (with subdirs test/routes/, test/services/, test/middleware/, test/policy/ as needed)

Run tests per package: pnpm --filter <package-name> test, or from repo root pnpm --filter api test, etc.

Project Structure

parker-app/
├── apps/
│   ├── api/             # Express API server
│   │   ├── src/
│   │   │   ├── db/          # PostgreSQL schema, queries, seed data
│   │   │   ├── routes/      # drivers, gate, sessions, webhooks endpoints
│   │   │   ├── services/    # hedera.ts, blockchain.ts, stripe.ts, pricing.ts
│   │   │   ├── middleware/   # wallet auth
│   │   │   └── ws/          # WebSocket server
│   │   └── ...
│   ├── driver/          # Driver PWA (Next.js)
│   │   ├── src/
│   │   │   ├── app/         # pages: dashboard, register, history, profile, session detail
│   │   │   ├── components/  # SessionCard, WalletButton
│   │   │   ├── hooks/       # useDriverProfile, useParkerSocket
│   │   │   ├── lib/         # API client
│   │   │   └── providers/   # WalletProvider (wagmi + Coinbase Smart Wallet)
│   │   └── ...
│   └── gate/            # Gate operator app (Next.js)
│       ├── src/
│       │   ├── app/         # pages: live gate, dashboard, sessions, settings
│       │   ├── components/  # CameraFeed, PlateResult, GateStatus
│       │   ├── hooks/       # useGateSocket, useSessionCache (offline resilience)
│       │   └── lib/         # API client
│       └── ...
├── contracts/           # Solidity smart contracts
│   ├── contracts/       # DriverRegistry.sol (+ legacy ParkingNFT.sol reference contract)
│   ├── test/            # Full test suites for both contracts
│   └── scripts/         # Deploy script
├── packages/
│   ├── core/            # Shared types, utils (calculateFee, formatPlate, hashPlate), contract ABIs
│   ├── hedera/          # Hedera HTS integration (mint/burn NFTs, mirror node queries, setup script)
│   ├── alpr/            # License plate recognition (Google Vision + country-aware plate normalization)
│   ├── x402/            # x402 middleware/client + EVM verification primitives
│   ├── x402-xrpl-settlement-adapter/ # XRPL settlement verification adapter
│   ├── policy-core/      # Pure policy evaluation (entry grant, payment decision) + enforcePayment at settlement
│   ├── settlement-core/ # Rail-agnostic settlement types + XRPL helpers (verification in x402 adapter)
│   ├── observability/   # Structured logging + metrics primitives
│   ├── tsconfig/        # Shared TypeScript configs
│   └── eslint-config/   # Shared ESLint config
├── infra/               # Docker Compose (PostgreSQL)
├── SPEC.md              # Detailed technical specification
└── turbo.json           # Turborepo pipeline config

API Endpoints

Driver API

Method Path Description
POST /api/drivers/register Register new driver + vehicle
GET /api/drivers/wallet/:address Look up driver by wallet address
GET /api/drivers/:plate Get driver profile by plate
PUT /api/drivers/:plate Update driver profile
DELETE /api/drivers/:plate Deactivate driver

Session API

Method Path Description
GET /api/sessions/active/:plate Get active parking session
GET /api/sessions/history/:plate Get session history
GET /api/sessions/:sessionId/timeline Get ordered lifecycle timeline events (x-gate-api-key required when configured)

Timeline response shape:

{
  "sessionId": "11111111-1111-4111-8111-111111111111",
  "state": "payment_required",
  "eventCount": 2,
  "events": [
    {
      "eventType": "SESSION.CREATED",
      "createdAt": "2026-03-08T12:00:00Z",
      "metadata": {
        "lotId": "lot_1"
      }
    }
  ]
}

Gate API

Method Path Description
POST /api/gate/entry Process vehicle entry (plate string or image). Requires Idempotency-Key header
POST /api/gate/exit Process vehicle exit + return payment options (x402 + Stripe). Requires Idempotency-Key header
POST /api/gate/xrpl/xaman-intent Create Xaman payload for pending XRPL payment (Xaman-first flow)
GET /api/gate/xrpl/xaman-status/:payloadUuid Poll Xaman payload resolution and get XRPL tx hash
POST /api/gate/scan ALPR: upload image, get plate number
GET /api/gate/lot/:lotId/status Lot occupancy, config, currency, payment methods
GET /api/gate/lot/:lotId/sessions Active sessions list
PUT /api/gate/lot/:lotId Update lot settings (rates, currency, payment methods)

Webhooks

Method Path Description
POST /api/webhooks/stripe Stripe payment confirmation (closes session + burns NFT)

Health & Observability

Method Path Description
GET /healthz Liveness probe (basic process health)
GET /readyz Readiness probe (DB + Hedera + Mirror Node + payment rail config)
GET /metrics In-memory metrics snapshot (mint/burn latency, mirror lag, failures)

WebSocket

Path Description
/ws/gate/:lotId Real-time gate events (entry/exit)
/ws/driver/:plate Real-time session updates for driver

Privacy & Security

On-chain privacy: Plate numbers are never stored in plaintext on Hedera. Parker hashes the plate (plateHash) and then stores NFT metadata as an AES-256-GCM encrypted binary payload on HTS. Public Mirror Node readers see ciphertext bytes, not readable plate/lot/time fields. The API can decrypt metadata with NFT_ENCRYPTION_KEY for fallback lookups, while plaintext plate data remains only in the access-controlled PostgreSQL database. See SPEC.md §12.1 for the full privacy model.

For a focused adversarial analysis (replay attacks, cloned tickets, plate spoofing, race conditions, gate offline behavior, and payment disputes), see THREAT_MODEL.md.

Observability highlights:

  • Structured JSON logs with request context (request_id, session_id, lot_id)
  • Core metrics for mint/burn latency, mirror lag, failed exits, and payment failures
  • Tracing is intentionally deferred for now (TODO) and will be added in a later phase.

Validation & Safety

The API enforces the following invariants:

  • Plate normalization — all plates are stripped of dashes/spaces before storage and lookup, so format differences never cause mismatches. ALPR plate detection is scoped to the deployment's configured countries (DEPLOYMENT_COUNTRIES) for higher accuracy
  • Lot validation on entry — entry is rejected if the lot doesn't exist, if it's full (capacity check), or if the driver is unregistered
  • Lot mismatch on exit — a car can only exit from the lot it entered; mismatched lotId returns 400
  • One active session per plate — enforced at both application level and via a PostgreSQL partial unique index (WHERE status = 'active')
  • Fee guardrailscalculateFee handles zero/negative duration (minimum 1 billing increment), zero rate (fee = 0), and division-by-zero on billing interval (defaults to 15 min). Fees are rounded to 6 decimal places and capped by maxDailyFee
  • Multi-currency — each lot defines its own currency (ISO 4217); the pricing service converts to stablecoin via configurable FX rates for the x402 rail, while Stripe charges in the lot's native currency directly
  • Payment-before-close — the exit route returns payment options without closing the session; the session is only closed after payment confirmation (X-PAYMENT proof for x402, or Stripe webhook)
  • Policy-gated payments — payment options and settlement constraints come from a policy decision (caps in stablecoin minor, allowlists); on XRPL, settlement is re-checked against the decision before closing (enforcement); policy events are stored for audit
  • Network-aware x402 verificationX-PAYMENT proofs are verified according to X402_NETWORK (EVM receipt parsing or XRPL payment verification)
  • Idempotent webhooks — Stripe webhook handler checks if the session is still active before closing, preventing duplicate closures on retry
  • Idempotent gate mutationsPOST /api/gate/entry and POST /api/gate/exit require an Idempotency-Key; duplicate retries return the cached response without re-running side effects
  • Input validation — required fields are checked on all mutation endpoints; numeric lot settings reject NaN; session history limit/offset are sanitized and capped
  • Duplicate registration — returns 409 with a clear error message instead of a generic 500
  • Status constraintssessions.status is enforced via CHECK constraint (active, completed, cancelled)

Status

🚧 MVP in active development

  • On-chain architecture: Hedera HTS parking NFTs + optional Base DriverRegistry/x402 rail
  • API server with full CRUD, ALPR, blockchain integration
  • Driver app: registration, wallet connect, session view, history, profile
  • Gate app: camera feed, ALPR scan, dashboard, sessions, settings
  • x402 payment flow (middleware + client)
  • x402 XRPL settlement adapter (tx-hash verification path)
  • Multi-currency support: per-lot currency config, FX conversion for x402 rail
  • Stripe Checkout integration: credit card payments in any local currency
  • Dual payment rails: Stripe (card) + x402 (Base/XRPL) per lot config
  • Stripe webhook with idempotent session closure
  • Real-time WebSocket events (gate auto-opens on payment from any rail)
  • Database schema + seed data
  • Input validation, fee guardrails, race-condition guards
  • End-to-end smoke testing
  • Deploy DriverRegistry to Base Sepolia (if Base registry sync is enabled)
  • Create Hedera NFT collection on testnet
  • Write-ahead NFT minting (mint before DB write on entry)
  • Mirror Node fallback for exit when DB is unreachable
  • Gate-side session cache for offline-capable exit validation
  • On-chain payment verification (EVM via viem + XRPL via settlement adapter)
  • XRPL payment verification via x402 settlement adapter (with manual tx-hash UX fallback)
  • Policy layer: policy schema + decision logging (policy_events, policy_grants, decision payload by decisionId)
  • Policy layer: per-tx/per-session/per-day spend caps (stablecoin minor) + lot/geo/rail/asset allowlists
  • Policy layer: rail/asset selection from settlement-verifiable assets (XRPL XRP/IOU, EVM ERC20)
  • Policy layer: bind decision to paymentId and enforce at settlement verification (XRPL path)
  • Live FX rate feed (CoinGecko / Circle API) to replace static env var rates
  • Wallet authentication (SIWE / EIP-4361)
  • Push notifications
  • Physical gate hardware integration (Phase 2)

License

MIT

About

Decentralized parking management powered by blockchain and x402 payment protocol

Resources

License

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors