chore: scaffold PYRE MVP monorepo (structure + docs)

pnpm + TypeScript workspace per design doc §13:
- apps/{web,api,worker} skeletons (Next.js 16, Fastify 5, BullMQ)
- packages/{core,solana,prometheus,db,config} (core has real types/DTOs;
  solana/prometheus are stubs)
- programs/pyre-core placeholder (future Anchor, v1.0)
- docs/: PYRE_MVP_DESIGN (canonical), ARCHITECTURE, SECURITY, TOKEN_CLASSIFICATION
- CLAUDE.md, README, .env.example (no private-key var by design)

Skeleton + docs only — no Solana/business logic yet. All workspaces typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-31 02:20:55 +00:00
parent e86b57e00f
commit c20094ab56
65 changed files with 13834 additions and 1 deletions

489
docs/ARCHITECTURE.md Normal file
View File

@@ -0,0 +1,489 @@
# PYRE — Engineering Architecture
> Companion to [`PYRE_MVP_DESIGN.md`](./PYRE_MVP_DESIGN.md). The design document is
> the canonical source of truth; this file describes *how the system is wired
> together*. Where they appear to disagree, the design document wins.
**Tagline:** *Burn the dead. Feed the PYRE. Claim the Spawn.*
---
## 1. System Overview
PYRE is a Solana wallet-cleanup and ritual meme-rebirth protocol. The MVP runs as
three runtime services backed by two stateful stores, and it depends on two
classes of external service: a Solana RPC provider and AI APIs.
Runtime services:
- **`apps/web`** (`pyre-web`) — Next.js frontend. Wallet connect, scanner UI,
cleanup preview, signing, receipt rendering, Prometheus review, admin pages.
- **`apps/api`** (`pyre-api`) — Node.js/Fastify (or Express) HTTP API. Scan
coordination, classification, **unsigned** transaction building, receipt
storage, AI orchestration, admin API. The only service the browser talks to.
- **`apps/worker`** (`pyre-worker`) — Node.js BullMQ worker. Slow/async jobs:
metadata enrichment, AI generation, image prompts, safety/collision checks,
confirmation tracking, receipt enrichment.
Stateful stores:
- **PostgreSQL** — durable record of scans, classifications, receipts,
generations, and Spawn records.
- **Redis** — BullMQ job queue, scan cache, rate limiting, quote cache,
generation status.
External dependencies (never self-hosted on the MVP VPS):
- **Solana RPC** — external provider only. No validator/RPC node on the VPS.
- **AI APIs** — text, image, and moderation APIs only. No local LLM/image models.
### Component / Data-Flow Diagram
```
┌──────────────┐
│ Wallet │ (Phantom / Solflare via Wallet Adapter)
│ (browser) │ signs locally — keys never leave the client
└──────┬───────┘
│ connect / sign / send
┌──────────────┐ static assets / SSR
│ apps/web │◀───────────────────────────┐
│ (Next.js) │ │
└──────┬───────┘ │
│ HTTPS (JSON) │
▼ │
┌───────────────────────────────────────────────┐ │
│ apps/api │ │
│ scan · classify · build (UNSIGNED) · receipt │ │
│ prometheus/generate · admin │ │
└───┬─────────────┬──────────────┬────────────────┘ │
│ │ │ │
│ SQL │ cache/queue │ getAccounts / simulate / │
▼ ▼ │ sendTx / confirm │
┌──────────┐ ┌──────────┐ ▼ │
│ Postgres │ │ Redis │ ┌──────────────┐ │
│ │ │ (BullMQ) │ │ Solana RPC │ (external) │
└──────────┘ └────┬─────┘ └──────────────┘ │
│ │
│ jobs pulled from queue │
▼ │
┌──────────────┐ ┌──────────────┐ │
│ apps/worker │───▶│ AI APIs │ (external) │
│ (BullMQ) │ │ text/image/ │ │
│ │ │ moderation │ │
└──────┬───────┘ └──────────────┘ │
│ writes results / status │
├───────────────▶ Postgres │
└───────────────▶ Redis ────────────────────┘
(generation status read back by web/api)
```
The browser only ever talks to `apps/web` and `apps/api`. The worker is not
network-exposed; it consumes jobs from Redis and writes results back to Postgres
and Redis. RPC and AI calls flow outbound only.
---
## 2. Component Responsibilities
### `apps/web` — User-facing frontend
Next.js + TypeScript + Tailwind + Solana Wallet Adapter, with React Query or
Zustand for state. Responsibilities (§11):
- Wallet connect via Solana Wallet Adapter.
- Token-account display and classification grouping (closeable / burnable /
transmutable / protected / unsupported).
- User confirmations and **transaction preview** UI.
- Transaction **signing** (client-side, via the connected wallet only).
- Receipt rendering and optional share image.
- Prometheus Spawn-package review and public round/Spawn pages.
- Admin / generation review UI.
### `apps/api` — Backend HTTP API
Node.js + Fastify/Express + TypeScript, fronting PostgreSQL, Redis, BullMQ.
Responsibilities (§11):
- Token-scan coordination (calls RPC, persists results).
- Classification helpers and route evaluation.
- **Builds UNSIGNED Solana transactions** — never signs, never holds keys.
- Metadata preparation and AI generation orchestration (enqueues worker jobs).
- Receipt storage and Spawn-record storage.
- Public API and protected admin API.
### `apps/worker` — Background worker
Node.js worker process driven by BullMQ over Redis, with AI API clients.
Responsibilities (§11):
- Slow token-metadata enrichment.
- AI generation jobs (Prometheus).
- Image-prompt generation.
- Safety checks and ticker/name collision checks.
- Background confirmation tracking.
- Receipt enrichment.
### `packages/core` — Shared types & business logic
The single home for cross-service domain definitions (§13):
- Classification **enums**: `EMPTY_CLOSE_ONLY`, `INCINERATE_ONLY`,
`TRANSMUTABLE`, `PROTECTED_SKIP`, `UNSUPPORTED`.
- Conservative **risk rules** (the §7 safety rules: classic SPL only, skip
Token-2022/NFTs/LP/frozen/delegated, USD threshold, price-impact and stale-quote
guards).
- Shared **DTOs** for the API request/response shapes.
- **Receipt schema**.
- **Prometheus input/output schema**.
### `packages/solana` — Solana transaction helpers
Everything that touches the chain at the instruction level (§13):
- Token-account **parsing** (decode raw account state into the scan model).
- **Close-account** transaction builder.
- **Burn** transaction builder.
- **Simulation** helpers (simulate before signing — §7).
- **Transaction decoder** (decode the built tx so it can be matched against the
preview — §8 step 5, §16).
### `packages/prometheus` — AI generation logic
The creative engine's code (§13), invoked by the worker:
- Prompt **templates**.
- The **meta mixer** (probabilistic influence blend — §9).
- Output **parser**.
- **Safety checks** (blocked terms, scam/impersonation/copyright filters).
- **Image-prompt generator**.
### `packages/db` — Database layer
Schema, migrations, and table definitions (§13/§15). Owns the canonical SQL and
migration history; `apps/api` and `apps/worker` depend on it for data access.
### `packages/config` — Shared config
Shared configuration and environment loading (§13). Centralizes reading
`.env`-supplied secrets (RPC URL, AI keys, DB/Redis connection strings) so no
secret is hard-coded.
### `programs/pyre-core` — Future Anchor program
NOT part of the first burner MVP. The future on-chain trust core (rounds, Essence
vault, claims, refunds) — built only at Phase 7 / v1.0.
---
## 3. Request / Data Flow — The Burner Journey
The core flow is the 8-step burner sequence from §8. The critical trust property:
**the server builds an UNSIGNED transaction, the client signs it, and the decoded
transaction is matched against the preview before signing.**
```
1. Connect ──▶ 2. Scan ──▶ 3. Classify ──▶ 4. Preview ──▶ 5. Build (UNSIGNED)
8. Receipt ◀── 7. Confirm ◀── 6. Sign (client) ◀── decode & match against preview
```
1. **Wallet Connect** — user connects via Solana Wallet Adapter (`apps/web`).
No keys leave the browser.
2. **Account Scan**`apps/web` calls `POST /api/scan`. `apps/api` queries token
accounts via the external RPC, capturing for each: owner, ATA address, mint,
token program, balance, decimals, rent estimate, metadata (if available),
token-program type, frozen/delegated state. Results persist to
`wallet_scans` / `token_accounts`; slow metadata enrichment may be deferred to
a worker job. Scan results are cached in Redis.
3. **Classification** — each account is classified server-side into the §6
categories and grouped for the UI. **Client-submitted classifications are not
trusted** — the server recomputes where needed (§16).
4. **Preview** — before any signing the user sees: accounts to close, tokens to
burn, accounts skipped, estimated rent returned, transaction fees, warnings,
and the destination wallet for recovered rent (which is the user's own wallet).
5. **Build Transaction**`apps/web` calls `POST /api/build/close-empty` (and/or
`/api/build/burn`). `apps/api` uses `packages/solana` to build an **unsigned**
transaction and returns it base64-encoded plus the preview. The client decodes
the transaction (`packages/solana` decoder) and **matches it against the
preview**; any mismatch aborts before signing.
6. **User Signs** — locally, with the connected wallet. PYRE never requests
private keys and never performs custodial signing.
7. **Confirmation** — the signed transaction is sent and confirmed via RPC. A
worker confirmation-tracking job may follow the signature to durable finality.
8. **Receipt**`apps/web` calls `POST /api/receipt`; `apps/api` records and
returns the receipt: tx signature, accounts closed, tokens burned, rent
returned, accounts skipped, warnings, timestamp, optional share image. A worker
receipt-enrichment job may backfill metadata.
All transactions are simulated before final signing (§7), and all build requests
are logged (§16).
---
## 4. API Surface
Reproduced from §14. All endpoints are served by `apps/api`. Admin endpoints are
authenticated and protected separately (§16).
### `POST /api/scan`
```jsonc
// in:
{ "wallet": "wallet_pubkey" }
// out:
{
"scanId": "uuid",
"wallet": "wallet_pubkey",
"summary": {
"totalAccounts": 0,
"emptyCloseOnly": 0,
"incinerateOnly": 0,
"transmutable": 0,
"protectedSkip": 0,
"unsupported": 0,
"estimatedRentLamports": 0
},
"accounts": []
}
```
### `POST /api/build/close-empty`
```jsonc
// in:
{ "wallet": "...", "accountAddresses": ["ata1", "ata2"] }
// out:
{
"transactionBase64": "...",
"preview": {
"accountsToClose": [],
"estimatedRentReturnedLamports": 0,
"rentDestination": "user_wallet_pubkey"
}
}
```
### `POST /api/build/burn`
```jsonc
// in:
{ "wallet": "...", "items": [{ "tokenAccount": "...", "mint": "...", "amount": "..." }] }
// out:
{
"transactionBase64": "...",
"preview": {
"tokensToBurn": [],
"accountsPotentiallyClosable": []
}
}
```
### `POST /api/receipt`
```jsonc
// in:
{ "wallet": "...", "txSignature": "...", "scanId": "uuid" }
// out:
{
"receiptId": "uuid",
"txSignature": "...",
"rentReturnedLamports": 0,
"closedAccounts": [],
"burnedTokens": [],
"skippedTokens": []
}
```
### `POST /api/prometheus/generate`
```jsonc
// in:
{ "receiptId": "uuid", "chaos": 0.25, "operatorSeed": "optional" }
// out:
{
"generationId": "uuid",
"spawnName": "...",
"ticker": "...",
"lore": "...",
"imagePrompt": "...",
"metadata": {},
"riskFlags": []
}
```
### Admin endpoints
Admin / generation-review endpoints (approve/reject generations, record Pump.fun
launches, view system events) are protected and not part of the public surface.
They back the admin review UI and the Spawn-record workflow (§10, §16).
---
## 5. Data Model
### Initial PostgreSQL tables (§15)
```
wallet_scans: id, wallet, status, created_at, completed_at, summary_json
token_accounts: id, scan_id, wallet, ata, mint, token_program,
raw_balance, ui_balance, decimals, symbol, name,
classification, warnings_json, estimated_rent_lamports,
created_at
cleanup_receipts: id, wallet, scan_id, tx_signature, rent_returned_lamports,
closed_accounts_count, burned_tokens_count, status,
created_at, receipt_json
prometheus_generations: id, receipt_id, input_json, output_json, status,
risk_flags_json, created_at, approved_at, rejected_at
spawn_records: id, generation_id, spawn_name, ticker, mint, metadata_uri,
pumpfun_url, launch_tx, status, created_at
```
Additional initial tables called out in §11/§15: `token_classifications`,
`burn_events`, `close_account_events`, `spawn_candidates`, and `system_events`
(audit/event log).
### Future tables (NOT in the burner MVP)
These arrive with the Essence ledger and PYRE Core program (Phases 67):
- `pyre_rounds` — round state machine.
- `essence_contributions` — recorded Essence per wallet per round.
- `claim_records` — Spawn claim accounting.
- `refund_records` — refunds for failed rounds.
- `influence_fields` — meta-influence inputs for Prometheus weighting.
> Per §5/§15: Essence may start in the database, but it must not be called a
> deposit until an on-chain custody model exists, and claims must not be promised
> until claim logic exists.
---
## 6. Redis Usage
Redis serves five roles (§11):
- **Job queue** — backs BullMQ; `apps/api` enqueues, `apps/worker` consumes.
- **Scan cache** — caches scan results so repeat views don't re-hit RPC.
- **Rate limiting** — throttles scan and build endpoints (§16).
- **Temporary quote cache** — short-lived swap/route quotes; stale quotes are
rejected by classification (§7).
- **Generation status** — live status of in-flight Prometheus jobs, read back by
`apps/web` / `apps/api`.
### BullMQ Worker Jobs
`apps/worker` processes these job types (§11):
- **Metadata enrichment** — slow token name/symbol/metadata lookups.
- **AI generation** — Prometheus Spawn generation.
- **Image prompts** — image-prompt generation for the Spawn.
- **Safety checks** — moderation of generated names/tickers/lore.
- **Collision checks** — ticker/name duplicate detection.
- **Confirmation tracking** — follow tx signatures to finality in the background.
- **Receipt enrichment** — backfill receipt detail after confirmation.
---
## 7. Solana RPC Requirements
PYRE uses an **external RPC provider only**. Per §11/§12, the MVP VPS must **not**
run a Solana validator or RPC node.
Required RPC capabilities (§11):
- Get token accounts by owner.
- Get account info.
- Simulate transactions.
- Send transactions.
- Confirm transactions.
- Parse token-account state.
The RPC endpoint URL is supplied via environment config (`packages/config`) and
treated as a secret. All chain access flows through `packages/solana`.
---
## 8. AI Services
AI is **API-based only** (§11/§12). The MVP server must **not** run local LLMs or
local image-generation models.
Service classes used:
- **Text generation** — Spawn name, ticker, lore, tagline, description, launch
copy (§9 outputs).
- **Image generation** — from the generated image prompt.
- **Moderation / safety** — filtering hate/explicit/extremist/copyrighted/
impersonation/scam-like output (§16).
All AI calls are made from `apps/worker` using clients configured via secrets in
`packages/config`. Prometheus generates a *candidate package for human review*
it never launches tokens or controls funds (§9).
---
## 9. Infrastructure & Deployment
A single **8GB VPS** is sufficient for the MVP (§12). It runs:
- `pyre-web`, `pyre-api`, `pyre-worker`
- PostgreSQL
- Redis
- **nginx** (reverse proxy / TLS termination in front of web + api)
- **PM2 or systemd** (process supervision for the three Node services)
- logs / log rotation
- admin dashboard
The VPS must **NOT** run (§12):
- a Solana validator,
- a Solana RPC node,
- a large local LLM,
- local image generation,
- heavy indexing at scale.
**Base setup already completed (§12/§19):** `pyre` user created, root login
disabled, SSH key auth, UFW firewall, Fail2ban, basic hardening.
**Next setup (§12/§19):** Node.js 22, pnpm, Git, nginx, PostgreSQL, Redis, PM2,
Claude Code, project repo, environment files, backup script, log rotation.
**External accounts required (§19):** Solana RPC provider, OpenAI/Anthropic API
key, image-generation provider, domain name, GitHub repo, Pump.fun creator
wallet, optional IPFS/Arweave metadata service.
---
## 10. Build-Order Note (Phased Roadmap)
Components map to the §18 development phases so a reader knows *what gets built
when*:
| Phase | Focus | Components touched |
|-------|-------|--------------------|
| **0 — Server & Repo Setup** | VPS, pnpm workspace, web/api/worker skeletons, Postgres + Redis, nginx, env templates | all apps (skeleton), `packages/config`, `infra/` |
| **1 — Wallet Scanner** | Wallet connect, scan endpoint, token-account fetch, basic classification, results + protected/skipped UI | `apps/web`, `apps/api`, `packages/solana` (parsing), `packages/core` (enums/rules), `packages/db` (`wallet_scans`, `token_accounts`) |
| **2 — Close Empty ATAs** | Build close-account tx, decode/preview, signing, confirmation tracking, receipt page | `packages/solana` (close builder + decoder + simulation), `apps/api` (`/build/close-empty`, `/receipt`), `apps/worker` (confirmation tracking), `packages/db` (`cleanup_receipts`, `close_account_events`) |
| **3 — Burn Junk** | `INCINERATE_ONLY` classification, burn builder, burn-then-close, stronger confirmations, receipt update | `packages/solana` (burn builder), `apps/api` (`/build/burn`), `packages/db` (`burn_events`) |
| **4 — Prometheus Generator** | Generation input from receipt, meta mixer, name/ticker/lore + image prompt, safety checks, admin approval UI | `packages/prometheus`, `apps/worker` (AI/safety/collision jobs), `apps/api` (`/prometheus/generate`, admin), `apps/web` (review UI), `packages/db` (`prometheus_generations`, `spawn_candidates`) |
| **5 — Manual Pump.fun Launch** | Approved package, metadata JSON, operator checklist, record mint/url/tx, public Spawn page | `apps/web` (public Spawn page), `apps/api` (admin record endpoints), `packages/db` (`spawn_records`) |
| **6 — Essence / Round Prototype** | Swap-candidate detection, route quote preview, net Essence estimate, round dashboard, DB-only contribution record (no claim promises) | `packages/solana` (route eval), `apps/api`, `packages/db` (future `pyre_rounds`, `essence_contributions`, `influence_fields`) |
| **7 — PYRE Core Program** | Anchor program: create round, contribute Essence, contribution-receipt PDA, lock round, register Spawn, claim, refund, tests | `programs/pyre-core`, future tables `claim_records`, `refund_records` |
The first three phases deliver the trust-building burner (v0.1). The Anchor
program in `programs/pyre-core` is explicitly **not** needed until Phase 7 / v1.0.
---
> **PYRE returns your rent. The scraps feed the fire.**