Ctrl K
ComunidadGuías…

AGENTS.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
# AGENTS.md — Rekey

For AI coding agents (Claude Code, Cursor, Codex, …) working in this repo.
Humans: start with [README.md](README.md) and [CONTRIBUTING.md](CONTRIBUTING.md).

## What this is

A self-hostable, multi-tenant **auth + billing** backend for SaaS / B2C apps.
One deployment serves many Tenants → Applications → EndUsers, behind one API,
in one `docker compose up`. See [ARCHITECTURE.md](ARCHITECTURE.md) for the full
system map.

## Setup

```bash
pnpm install
cp .env.example .env            # fill POSTGRES_PASSWORD, REDIS_PASSWORD, JWT_SECRET,
                                # SUPER_ADMIN_KEY, ENCRYPTION_KEY — then paste the two
                                # datastore passwords into DATABASE_URL / REDIS_URL
docker compose up -d postgres redis
pnpm db:migrate:deploy
pnpm dev                        # API on :3030, panel on :3031
```

Then bootstrap in one call:

```bash
REKEY_URL=http://localhost:3030 SUPER_ADMIN_KEY=<from .env> \
  npx @rekey.dev/cli init --tenant-name Acme --owner-email ops@acme.example \
                          --app-name "Acme Prod" --app-slug acme-prod --json
```

## Commands

| Command | What |
|---|---|
| `pnpm dev` | generate the Prisma client, build workspace deps, run all apps in watch mode (loads `.env`) |
| `pnpm build` | generate the Prisma client, then build every workspace |
| `pnpm test` | run the vitest suites |
| `pnpm lint` / `pnpm typecheck` | lint / typecheck all workspaces |
| `pnpm db:generate` | generate the Prisma client |
| `pnpm db:migrate` | create + apply a dev migration |
| `pnpm db:migrate:deploy` | apply pending migrations (no prompt) |
| `pnpm db:studio` | open Prisma Studio |

The `db:*` scripts run Prisma from the repo root, which is what makes them read
the root `.env`. Running them from `apps/api` reads `apps/api/.env` instead —
a file this repo does not ship.

The API container also runs `prisma migrate deploy` on boot, so a fresh DB is
migrated automatically under `docker compose --profile full up`.

## Conventions (do not violate without explicit instruction)

1. **Multi-tenant from line 1.** Every domain row carries `applicationId`.
   There is no "default" application — operations always name one.
2. **Provider-agnostic billing.** Stripe / PayPal / Razorpay sit behind the
   `BillingProvider` interface. Top-level types express the *intersection*;
   provider-specific data lives in `metadata: Json`.
3. **The two auth stacks are parallel, not shared.** End-user auth
   (`modules/auth`) and operator auth (`modules/tenant-auth`) are physically
   duplicated against different models (`EndUser` vs `TenantUser`). A fix in
   one almost always needs mirroring in the other — see the file map in
   ARCHITECTURE.md §3.
4. **`typ` JWT claim is load-bearing.** End-user and operator JWTs share
   `JWT_SECRET`; the `typ` claim is the only thing stopping cross-tier
   impersonation. Always set and verify it.
5. **Billing state transitions live in webhook handlers only**, never in the
   API request that initiates checkout (which writes a `PENDING` row).
6. **Credentials at rest:** hash-only (SHA-256) for tokens/keys; AES-256-GCM
   (`lib/secrets.ts`) for secrets whose cleartext is needed later.
7. **Side-effects (email, webhooks) are fire-and-forget** and must never block
   the user-facing response.
8. **Name things for what they are, not how they came to be.** A file, a test,
   a `describe` title or an identifier says what it holds or what behaviour it
   covers, never which review, audit, round, phase, fix list, issue or pull
   request produced it: `sign-in-lockout.test.ts`, not `audit-3.test.ts`;
   `provider-amount-scale.test.ts`, not `money-v2-wire-scale.test.ts`. A name
   like `review-fixes` tells the next reader nothing and stops meaning
   anything once the review is forgotten. Split a grab bag by behaviour
   instead of renaming it. `node .github/scripts/check-file-names.mjs` fails
   CI on a process word in a source or test path; real product vocabulary (the
   audit log, the plan review page) goes on its allowlist with a reason.
9. **Rekey is an independent project.** Code, docs, tests and commit messages
   name Rekey and its public pieces only: no employer, hosting account,
   private repository, personal email address or coding-agent attribution.
   The release check rejects them.

## Tests

Vitest, per-workspace. The `apps/api` suite shares one Postgres + Redis in a
single fork — cross-file failures are often transient; re-run before assuming a
regression. Add tests next to the module you touch.
A test is added when a plausible change would break behaviour that nothing else
catches. A new test that duplicates existing cover is not added.