SPB Git
2.3 KB · 19 lines markdown
1# CLAUDE.md — tools.spboucher.ai23Curated encyclopedia of tools (public) + owner inventory (private). Stack: Next.js 16 App Router, React 19, Tailwind 4, PostgreSQL 17, Drizzle (snake_case casing), postgres-js, Vitest, Playwright. Port 8540.45## Non-negotiables6- **Public ≠ private at the DB layer.** Public code uses `sqlPublic` (role `tools_reader`, SELECT on `public_tools` view only). Never import `sql`/`db` from `src/db` into anything under `src/lib/public` or public routes. Owner tables (`owner_notes`, `projects`) are never joined into public queries.7- **Every admin mutation** goes through `requireUser(req)` (session + MFA + same-origin + `x-csrf-token`) and writes `audit_log` (+ `tool_revisions` for records). Never add client-only protection.8- **Evidence rules** (`docs/editorial-guide.md`, `docs/source-policy.md`): no prices, no certifications without a policy source, no benchmark claims, no copied vendor text, `checked_at` only for pages actually loaded. Run `pnpm content:validate` after editing `content/`.9- **Outbound HTTP only via `safeFetch`** (SSRF guard). Fetched text is untrusted; AI output must be zod-validated and never auto-saved.10- **Secrets** only in `.env` on the node (600) and `~/Desktop/Cluster/secrets/tools-spboucher-ai/`. Never in git, manifests, logs or chat.11- **Migrations**: add a new `drizzle/NNNN_*.sql`; never edit applied files (checksums). Mirror changes in `src/db/schema.ts`. Recreating the `public_tools` view requires re-granting to `tools_reader`.12- Drizzle hijacks postgres-js serializers → the raw `sql` clients use their own pools (see `src/db/index.ts`). Use `sql.json(x)` for jsonb params.1314## Workflow15`pnpm typecheck && pnpm test && pnpm content:validate` before committing. E2E/a11y/security scripts need a running server (`pnpm dev` or production). Remote-first after deploy: edit on `M2M32c:~/apps/tools-spboucher-ai`, `pnpm build && pm2 restart tools-web tools-worker`, commit/push there (`docs/deployment.md`).1617## Content authoring18One JSON per tool in `content/tools/<slug>.json` matching `src/lib/content/schema.ts`; deep records 100–300 words, ≥3 sources, ≥2 alternatives, comparison notes. Categories are leaf slugs from `content/categories.json`; alternatives are existing slugs. Private records → `content/private/` with `visibility: private`. Owner relevance → `content/owner/relevance.json`.19
Files · f05ed656dfb02e05e9363ab635689d5774c375f6
Menu

Theme