# AGENTS.md This file provides guidance to AI agents (Claude Code, Cursor, Copilot, etc.) when working with code in this repository. ## Admin dashboard The admin dashboard lives in [`Cap-go/capgo_admin_dashboard`](https://github.com/Cap-go/capgo_admin_dashboard) and reads the Capgo database read-only; Capgo carries no admin code. ## MUST NOT — never publish private customer data **This repository is public.** Chat, tickets, and internal messages may contain customer emails, names, org IDs, app IDs, API keys, or other private data. Private context in a conversation does **not** authorize putting it in git. ### You MUST NOT - Put customer emails, names, phone numbers, or other PII in source, comments, tests, fixtures, commit messages, PR titles, PR bodies, issue bodies, or review comments. - Copy private details from chat "for context" into a public PR, issue, or commit. - Use a real customer identifier as a seed, example, or reproduction case. Describe the bug in generic terms. If a fixture identity is required, invent a clearly fake one (`customer-onboarding@example.com`). ## MUST NOT — never break already-published CLI versions **We cannot break `@capgo/cli` releases that customers already run in production.** The last published CLI is the newest `cli-` git tag (and the matching `@capgo/cli` version on npm when it exists). Customers do not upgrade the CLI on every backend deploy. ### You MUST NOT - Revoke `GRANT` / `EXECUTE` on an RPC that the last published CLI still calls (for example `.rpc('get_user_id', { apikey })` on the anonymous API-key path). - Change backend identity resolution in ways that break the last published CLI without shipping a CLI release that stops using the old path first. - Make CI pass by **inverting** published-CLI contract tests to expect permission denied (`42501`). Those tests assert **success** — that is the contract. - Test only the PR-branch workspace CLI when validating RPC/grant changes. CI must exercise the **published** npm CLI against the PR schema. ### Before you revoke anon/service access on a CLI-facing RPC 1. Ship a CLI release that no longer calls it. 2. Wait for customers to upgrade (the `cli-*` tag must reflect the new behavior). 3. Only then revoke or harden the RPC. ### Where this is enforced - CI job: **`CRITICAL — Published CLI / do not break old CLI`** - Tests: `tests/published-cli-rpc-contract.test.ts` (live contract; do not invert) - Helpers: `scripts/published-cli-contract.ts` (parses `.rpc('...')` from the last `cli-*` tag) Org-perm / invite **oracle** RPCs (`invite_user_to_org_rbac`, `get_org_perm_for_apikey*`, `get_user_id(text,text)`, …) stay revoked for anonymous callers — see `tests/security-oracle-rpc-hardening.test.ts`. That is separate from the published CLI identity path (`get_user_id(text)` with a valid API key must keep working). ## Essential Development Commands ### Building and Development - `bun serve:dev` - Start local development server with local environment - `bun serve` - Start development server with default configuration - `bun build` - Build production version of the web app - `bun mobile` - Build for mobile and copy to Capacitor platforms - `bun dev-build` - Build with development branch configuration - `bun run cli:build` - Build the CLI workspace in `cli/` - `bun run cli:test` - Run the CLI workspace test suite (the setup steps `test:helper-dce` and `test:version-detection:setup` run first, then the rest of `cli` `test:suite` runs in parallel; `bun run --cwd cli test:serial` runs everything one by one) - `bun run cli:check` - Lint, typecheck, build, and test the CLI workspace ### Testing #### Supabase Edge Functions (Default) - `bun test:all` - Run all backend tests - `bun test:unit` - Run unit tests only (`tests/*.unit.test.ts`, no Supabase or Docker required) - `bun test:db` - Run the DB-only test subset listed in `tests/tinbase-db-tests.txt` against a throwaway Tinbase instance (no Docker; boots in ~5s). Add a test file to that list only if it talks purely to PostgREST/auth via supabase-js — no edge functions, Cloudflare workers, or raw Postgres TCP (`executeSQL`/`getPostgresClient`) - `bun test:backend:integration` - Run backend tests excluding unit and CLI tests (requires running Supabase; this is what CI shards across runners; CLI integration tests run via `bun test:cli`) - `bun test:backend` - Run backend tests excluding CLI tests - `bun test:cli` - Run CLI-specific tests (workspace CLI plus `tests/cli-compat.test.ts`, which pins `@capgo/cli` to `MIN_CLI_VERSION`) - `bun test:local` - Legacy alias for the default monorepo backend test run - `bun test:front` - Run Playwright frontend tests (CI shards spec files by measured duration from `playwright/spec-durations.json`; add slow new specs there) - `bun test:all:local` - Legacy alias for `bun test:all` - `bun test:cli:local` - Legacy alias for `bun test:cli` #### Cloudflare Workers Testing - `bun test:cloudflare:all` - Run all tests against Cloudflare Workers - `bun test:cloudflare:backend` - Run backend tests against Cloudflare Workers - `bun test:cloudflare:updates` - Run update tests against Cloudflare Workers - `./scripts/start-cloudflare-workers.sh` - Start local Cloudflare Workers for testing Note: Prefer Tinbase (`bun test:db` / `tests/tinbase-db-tests.txt`) for PostgREST/auth-only coverage so Docker/Cloudflare shards stay small and can run at high concurrency. CI caps every test job at 5 minutes and shards backend/Cloudflare/Playwright aggressively instead of lowering concurrency. See [CLOUDFLARE_TESTING.md](CLOUDFLARE_TESTING.md) for detailed information on testing against Cloudflare Workers. ### Code Quality - `bun lint` - Lint Vue, TypeScript, and JavaScript files in `src`: oxlint (`.oxlintrc.frontend.json`, the @antfu/eslint-config rule set plus `oxlint-plugin-vize` for templates), then ESLint on `.vue` files only for the template rules oxlint cannot cover yet (allowlist in `eslint.config.js`) - `bun lint:fix` - Auto-fix linting issues - `bun lint:backend` - Lint Supabase backend files - `bun typecheck` - Type-check the CLI and backend with TypeScript 7 `tsc`, and the frontend with vue-tsc - `bun types` - Generate TypeScript types from Supabase ### Database and Backend - `bun run supabase:start` - Start local Supabase instance (worktree-isolated) - `bun run supabase:cleanup` - Stop local Supabase and delete this worktree's Supabase volumes - `bun run supabase:db:reset` - Reset and seed local database - `bun backend` - Start Supabase functions locally - `bun reset` - Reset Supabase database ## Architecture Overview ### Frontend Architecture - **Framework**: Vue 3 with Composition API and `