Skip to content

Latest commit

 

History

History
67 lines (56 loc) · 3.47 KB

File metadata and controls

67 lines (56 loc) · 3.47 KB

Tack — Agent Context

IPFS pinning & retrieval service with x402 payments. TypeScript, Hono, Kubo IPFS, SQLite.

Project Structure

src/
  index.ts                    # Entry point: wiring, config, process lifecycle
  app.ts                      # Hono routes, middleware, request validation, A2A agent card
  config.ts                   # Env-driven config with production validation
  db.ts                       # SQLite setup (better-sqlite3)
  types.ts                    # Shared types (Pin, PinStatus, etc.)
  lib/errors.ts               # Typed error classes (ValidationError, NotFoundError, etc.)
  services/
    pinning-service.ts        # Core business logic: pin CRUD + upload + replication
    ipfs-rpc-client.ts        # Kubo RPC client (pin/add/cat/unpin)
    x402.ts                   # x402 middleware, wallet extraction, price calculation
    rate-limiter.ts           # Per-wallet/IP rate limiting
    content-cache.ts          # In-memory LRU cache for gateway responses
    content-type.ts           # MIME type detection
    logger.ts                 # Pino structured logging
  repositories/
    pin-repository.ts         # SQLite persistence, query filtering, owner isolation
tests/
  unit/                       # Unit tests
  integration/                # Integration tests
docs/
  railway-deployment.md       # Railway deployment runbook
  deployment-smoke.md         # x402 smoke test runbook
scripts/
  backup-db.sh                # SQLite backup script

Tech Stack

  • Runtime: Node.js 20+, TypeScript, pnpm
  • Framework: Hono (@hono/node-server)
  • IPFS: Kubo via HTTP RPC
  • Database: SQLite via better-sqlite3
  • Payments: x402 protocol (@x402/core, @x402/evm, @x402/hono), USDC on Taiko Alethia
  • Testing: Vitest
  • Logging: Pino

Standards & Protocols

Deployment

  • Production: Railway (API + Kubo as separate services, persistent volumes)
  • Config: Entirely env-driven. See .env.example
  • Docker: docker compose up --build for local full stack
  • Build: pnpm build compiles to dist/, node dist/index.js to run

Non-Obvious Things

  • Wallet = identity: There are no user accounts. The wallet that pays via x402 owns the pin. Owner endpoints enforce wallet isolation at the repository level.
  • Production startup validation: config.ts rejects placeholder EVM addresses and requires X402_ENABLED=true when NODE_ENV=production. The app will crash on boot if misconfigured.
  • Price is dynamic: x402.ts calculates price as base + (size_mb * per_mb), capped at max. The 402 response includes the exact amount.
  • Replication is best-effort: Primary pin must succeed. Replica failures are recorded in PinStatus.info.replication but don't fail the request.
  • Gateway is optional paywall: Content retrieval is free by default; owners can set meta.retrievalPrice to gate content behind x402.
  • SQLite single-writer: Only 1 API replica in production. No WAL mode tricks — just one process.
  • Rate limiter is in-memory: Resets on restart. Keyed by wallet address (authenticated) or IP (unauthenticated).