{"owner":"unkeyed","repo":"unkey","hasSkills":true,"hasMcp":false,"mcpConfig":null,"found":["AGENTS.md"],"skills":{"AGENTS.md":"# AGENTS.md - Unkey agent guide\n\nThis file is the first stop for agents working in this repo. Keep changes small,\ntyped, verified, and routed through `mise`.\n\n## Communication\n\n- Be concise.\n- Say what changed and how you verified it.\n- If you provide a plan, end with unresolved questions, if any.\n- Do not revert or rewrite work you did not make unless explicitly asked.\n\n## Source of truth\n\n- Tooling and task runner: `mise.toml`, `mise.lock`, and `.mise/tasks/*`.\n- Engineering docs: `docs/engineering/contributing/`.\n- Product docs: `docs/product/`.\n- Go tooling: `go.mod`, `go.sum`, `rask.toml`, and `.golangci.yaml`.\n- Web workspace: `web/package.json`, `web/pnpm-workspace.yaml`, and\n  `web/pnpm-lock.yaml`.\n\n## Repository map\n\n- `cmd/`: Unkey CLI commands and service entrypoints.\n- `svc/`: Go services (`api`, `ctrl`, `frontline`, `heimdall`, `krane`, `vault`).\n- `pkg/`: shared Go libraries.\n- `internal/`: shared internal Go services.\n- `proto/` and `gen/`: protobuf definitions and generated code.\n- `web/`: TypeScript apps, packages, database schema, and tooling.\n- `docs/`: Mintlify product and engineering documentation.\n- `dev/`: local development, Tilt, Kubernetes, and formatting config.\n\n## Tooling rules\n\nUse `mise` for all installs, tasks, and direct tool execution. Makefiles are\nlegacy and should not be used.\n\n```bash\n# Install pinned toolchain\n./dev/install-mise\nmise install\n\n# Discover tasks\nmise tasks\nmise run help\n```\n\nPrefer `mise run <task>` when a task exists. Use `mise exec -- <tool>` only for\ndirect commands without a task.\n\n### Common tasks\n\n```bash\nmise run build          # Go build, writes ./bin/unkey\nmise run lint           # golangci-lint checks\nmise run test           # run Go test suite through Rask\nmise run fmt            # dprint, go fmt, buf format, pnpm fmt\nmise run generate       # SQL, protobuf, Go generators, fmt\nmise run generate-bpf   # heimdall eBPF bindings\nmise run dev            # local Kubernetes/Tilt dev environment\nmise run dashboard      # dashboard-focused local setup\nmise run down           # stop Tilt and delete minikube cluster\nmise run tunnel         # port-forward 80/443 for *.unkey.local\nmise run unkey -- ...   # run the Unkey CLI\n```\n\n### Direct tool examples\n\n```bash\nmise exec -- rask ./pkg/cache\nmise exec -- go test -run TestCacheName ./pkg/cache\nmise exec -- pnpm --dir=web test\nmise exec -- pnpm --dir=web/apps/api vitest run -c vitest.integration.ts\nmise exec -- go test -fuzz=FuzzParseConfig -fuzztime=30s ./pkg/config/\n```\n\n## Code standards\n\n- Make minimal, surgical changes.\n- Preserve type safety. Do not add TypeScript `any`, non-null assertions, or\n  unsafe casts.\n- Model domain states explicitly. Parse untyped input at boundaries.\n- Prefer existing packages, helpers, and patterns before adding new ones.\n- Avoid new dependencies unless the local implementation would be worse.\n- Keep variable scope small. Use clear names with units or bounds where useful.\n- Handle every error. If a state is impossible, assert it rather than ignoring it.\n- Document why non-obvious code exists, not what each line does.\n\n## Go conventions\n\n- Build Go through `mise run build` and test Go through Rask with\n  `mise run test` or `mise exec -- rask ./path`.\n- Use `github.com/stretchr/testify/require` in tests.\n- Use `t.Helper()` in test helpers.\n- Use `t.Cleanup()` for resources.\n- Prefer `fault` for contextual errors and `assert` for invariants.\n- After changing generated inputs, run `mise run generate`.\n\n## TypeScript conventions\n\n- Run pnpm through mise: `mise exec -- pnpm --dir=web ...`.\n- Keep package manager changes scoped to `web/` unless a repo task says\n  otherwise.\n- Do not bypass formatter or type checks by weakening types.\n- Use the local app/package patterns in `web/` before introducing abstractions.\n\n## Documentation conventions\n\n- Follow `docs/engineering/contributing/quality/documentation.mdx`.\n- Product docs live in `docs/product/` and need `docs/product/docs.json` nav\n  entries when adding pages.\n- Engineering docs live in `docs/engineering/` and need\n  `docs/engineering/docs.json` nav entries when adding pages.\n- Use `bash` for shell code blocks.\n- Prefer root-relative internal doc links.\n- Do not use em dashes in docs.\n\n## Verification\n\nChoose the smallest check that proves the change.\n\n- Go source change: targeted `mise exec -- rask ./path`.\n- Go file added or imports changed: `mise run build`.\n- Shared Go behavior or broad service change: `mise run test` when practical.\n- TypeScript change: targeted `mise exec -- pnpm --dir=web ...` command.\n- Formatting-sensitive change: `mise run fmt` or the narrower formatter task.\n- Docs-only change: link/content review. Note if no formatter applies.\n\nReport failed or skipped verification honestly.\n\n## PlanetScale and Query Insights\n\nUnkey runs on PlanetScale Vitess. Every production MySQL query should carry SQLCommenter tags so Query Insights can attribute load by service, operation, and deploy.\n\n- Go: inject tags through `db.Config.Tags` and `sqlcomment.ForService` in service `run.go`. See [`pkg/mysql/sqlcomment`](pkg/mysql/sqlcomment/doc.go).\n- TypeScript: use `createCommentedPool` from `@unkey/db` instead of raw `mysql.createPool`.\n- Never put high-cardinality values (user ids, key ids, request ids) in SQL comments.\n- Full guide: [`docs/engineering/infra/planetscale/query-insights-tags.mdx`](docs/engineering/infra/planetscale/query-insights-tags.mdx).\n\n## High-signal references\n\n- Local development: `docs/engineering/contributing/local/development.mdx`.\n- Build workflow: `docs/engineering/contributing/tooling/builds.mdx`.\n- Code quality: `docs/engineering/contributing/quality/code-quality.mdx`.\n- Testing: `docs/engineering/contributing/quality/testing/index.mdx`.\n- Documentation: `docs/engineering/contributing/quality/documentation.mdx`.\n"},"files":{"AGENTS.md":"# AGENTS.md - Unkey agent guide\n\nThis file is the first stop for agents working in this repo. Keep changes small,\ntyped, verified, and routed through `mise`.\n\n## Communication\n\n- Be concise.\n- Say what changed and how you verified it.\n- If you provide a plan, end with unresolved questions, if any.\n- Do not revert or rewrite work you did not make unless explicitly asked.\n\n## Source of truth\n\n- Tooling and task runner: `mise.toml`, `mise.lock`, and `.mise/tasks/*`.\n- Engineering docs: `docs/engineering/contributing/`.\n- Product docs: `docs/product/`.\n- Go tooling: `go.mod`, `go.sum`, `rask.toml`, and `.golangci.yaml`.\n- Web workspace: `web/package.json`, `web/pnpm-workspace.yaml`, and\n  `web/pnpm-lock.yaml`.\n\n## Repository map\n\n- `cmd/`: Unkey CLI commands and service entrypoints.\n- `svc/`: Go services (`api`, `ctrl`, `frontline`, `heimdall`, `krane`, `vault`).\n- `pkg/`: shared Go libraries.\n- `internal/`: shared internal Go services.\n- `proto/` and `gen/`: protobuf definitions and generated code.\n- `web/`: TypeScript apps, packages, database schema, and tooling.\n- `docs/`: Mintlify product and engineering documentation.\n- `dev/`: local development, Tilt, Kubernetes, and formatting config.\n\n## Tooling rules\n\nUse `mise` for all installs, tasks, and direct tool execution. Makefiles are\nlegacy and should not be used.\n\n```bash\n# Install pinned toolchain\n./dev/install-mise\nmise install\n\n# Discover tasks\nmise tasks\nmise run help\n```\n\nPrefer `mise run <task>` when a task exists. Use `mise exec -- <tool>` only for\ndirect commands without a task.\n\n### Common tasks\n\n```bash\nmise run build          # Go build, writes ./bin/unkey\nmise run lint           # golangci-lint checks\nmise run test           # run Go test suite through Rask\nmise run fmt            # dprint, go fmt, buf format, pnpm fmt\nmise run generate       # SQL, protobuf, Go generators, fmt\nmise run generate-bpf   # heimdall eBPF bindings\nmise run dev            # local Kubernetes/Tilt dev environment\nmise run dashboard      # dashboard-focused local setup\nmise run down           # stop Tilt and delete minikube cluster\nmise run tunnel         # port-forward 80/443 for *.unkey.local\nmise run unkey -- ...   # run the Unkey CLI\n```\n\n### Direct tool examples\n\n```bash\nmise exec -- rask ./pkg/cache\nmise exec -- go test -run TestCacheName ./pkg/cache\nmise exec -- pnpm --dir=web test\nmise exec -- pnpm --dir=web/apps/api vitest run -c vitest.integration.ts\nmise exec -- go test -fuzz=FuzzParseConfig -fuzztime=30s ./pkg/config/\n```\n\n## Code standards\n\n- Make minimal, surgical changes.\n- Preserve type safety. Do not add TypeScript `any`, non-null assertions, or\n  unsafe casts.\n- Model domain states explicitly. Parse untyped input at boundaries.\n- Prefer existing packages, helpers, and patterns before adding new ones.\n- Avoid new dependencies unless the local implementation would be worse.\n- Keep variable scope small. Use clear names with units or bounds where useful.\n- Handle every error. If a state is impossible, assert it rather than ignoring it.\n- Document why non-obvious code exists, not what each line does.\n\n## Go conventions\n\n- Build Go through `mise run build` and test Go through Rask with\n  `mise run test` or `mise exec -- rask ./path`.\n- Use `github.com/stretchr/testify/require` in tests.\n- Use `t.Helper()` in test helpers.\n- Use `t.Cleanup()` for resources.\n- Prefer `fault` for contextual errors and `assert` for invariants.\n- After changing generated inputs, run `mise run generate`.\n\n## TypeScript conventions\n\n- Run pnpm through mise: `mise exec -- pnpm --dir=web ...`.\n- Keep package manager changes scoped to `web/` unless a repo task says\n  otherwise.\n- Do not bypass formatter or type checks by weakening types.\n- Use the local app/package patterns in `web/` before introducing abstractions.\n\n## Documentation conventions\n\n- Follow `docs/engineering/contributing/quality/documentation.mdx`.\n- Product docs live in `docs/product/` and need `docs/product/docs.json` nav\n  entries when adding pages.\n- Engineering docs live in `docs/engineering/` and need\n  `docs/engineering/docs.json` nav entries when adding pages.\n- Use `bash` for shell code blocks.\n- Prefer root-relative internal doc links.\n- Do not use em dashes in docs.\n\n## Verification\n\nChoose the smallest check that proves the change.\n\n- Go source change: targeted `mise exec -- rask ./path`.\n- Go file added or imports changed: `mise run build`.\n- Shared Go behavior or broad service change: `mise run test` when practical.\n- TypeScript change: targeted `mise exec -- pnpm --dir=web ...` command.\n- Formatting-sensitive change: `mise run fmt` or the narrower formatter task.\n- Docs-only change: link/content review. Note if no formatter applies.\n\nReport failed or skipped verification honestly.\n\n## PlanetScale and Query Insights\n\nUnkey runs on PlanetScale Vitess. Every production MySQL query should carry SQLCommenter tags so Query Insights can attribute load by service, operation, and deploy.\n\n- Go: inject tags through `db.Config.Tags` and `sqlcomment.ForService` in service `run.go`. See [`pkg/mysql/sqlcomment`](pkg/mysql/sqlcomment/doc.go).\n- TypeScript: use `createCommentedPool` from `@unkey/db` instead of raw `mysql.createPool`.\n- Never put high-cardinality values (user ids, key ids, request ids) in SQL comments.\n- Full guide: [`docs/engineering/infra/planetscale/query-insights-tags.mdx`](docs/engineering/infra/planetscale/query-insights-tags.mdx).\n\n## High-signal references\n\n- Local development: `docs/engineering/contributing/local/development.mdx`.\n- Build workflow: `docs/engineering/contributing/tooling/builds.mdx`.\n- Code quality: `docs/engineering/contributing/quality/code-quality.mdx`.\n- Testing: `docs/engineering/contributing/quality/testing/index.mdx`.\n- Documentation: `docs/engineering/contributing/quality/documentation.mdx`.\n"},"items":[{"name":"AGENTS.md","path":"AGENTS.md","title":"AGENTS.md","content":"# AGENTS.md - Unkey agent guide\n\nThis file is the first stop for agents working in this repo. Keep changes small,\ntyped, verified, and routed through `mise`.\n\n## Communication\n\n- Be concise.\n- Say what changed and how you verified it.\n- If you provide a plan, end with unresolved questions, if any.\n- Do not revert or rewrite work you did not make unless explicitly asked.\n\n## Source of truth\n\n- Tooling and task runner: `mise.toml`, `mise.lock`, and `.mise/tasks/*`.\n- Engineering docs: `docs/engineering/contributing/`.\n- Product docs: `docs/product/`.\n- Go tooling: `go.mod`, `go.sum`, `rask.toml`, and `.golangci.yaml`.\n- Web workspace: `web/package.json`, `web/pnpm-workspace.yaml`, and\n  `web/pnpm-lock.yaml`.\n\n## Repository map\n\n- `cmd/`: Unkey CLI commands and service entrypoints.\n- `svc/`: Go services (`api`, `ctrl`, `frontline`, `heimdall`, `krane`, `vault`).\n- `pkg/`: shared Go libraries.\n- `internal/`: shared internal Go services.\n- `proto/` and `gen/`: protobuf definitions and generated code.\n- `web/`: TypeScript apps, packages, database schema, and tooling.\n- `docs/`: Mintlify product and engineering documentation.\n- `dev/`: local development, Tilt, Kubernetes, and formatting config.\n\n## Tooling rules\n\nUse `mise` for all installs, tasks, and direct tool execution. Makefiles are\nlegacy and should not be used.\n\n```bash\n# Install pinned toolchain\n./dev/install-mise\nmise install\n\n# Discover tasks\nmise tasks\nmise run help\n```\n\nPrefer `mise run <task>` when a task exists. Use `mise exec -- <tool>` only for\ndirect commands without a task.\n\n### Common tasks\n\n```bash\nmise run build          # Go build, writes ./bin/unkey\nmise run lint           # golangci-lint checks\nmise run test           # run Go test suite through Rask\nmise run fmt            # dprint, go fmt, buf format, pnpm fmt\nmise run generate       # SQL, protobuf, Go generators, fmt\nmise run generate-bpf   # heimdall eBPF bindings\nmise run dev            # local Kubernetes/Tilt dev environment\nmise run dashboard      # dashboard-focused local setup\nmise run down           # stop Tilt and delete minikube cluster\nmise run tunnel         # port-forward 80/443 for *.unkey.local\nmise run unkey -- ...   # run the Unkey CLI\n```\n\n### Direct tool examples\n\n```bash\nmise exec -- rask ./pkg/cache\nmise exec -- go test -run TestCacheName ./pkg/cache\nmise exec -- pnpm --dir=web test\nmise exec -- pnpm --dir=web/apps/api vitest run -c vitest.integration.ts\nmise exec -- go test -fuzz=FuzzParseConfig -fuzztime=30s ./pkg/config/\n```\n\n## Code standards\n\n- Make minimal, surgical changes.\n- Preserve type safety. Do not add TypeScript `any`, non-null assertions, or\n  unsafe casts.\n- Model domain states explicitly. Parse untyped input at boundaries.\n- Prefer existing packages, helpers, and patterns before adding new ones.\n- Avoid new dependencies unless the local implementation would be worse.\n- Keep variable scope small. Use clear names with units or bounds where useful.\n- Handle every error. If a state is impossible, assert it rather than ignoring it.\n- Document why non-obvious code exists, not what each line does.\n\n## Go conventions\n\n- Build Go through `mise run build` and test Go through Rask with\n  `mise run test` or `mise exec -- rask ./path`.\n- Use `github.com/stretchr/testify/require` in tests.\n- Use `t.Helper()` in test helpers.\n- Use `t.Cleanup()` for resources.\n- Prefer `fault` for contextual errors and `assert` for invariants.\n- After changing generated inputs, run `mise run generate`.\n\n## TypeScript conventions\n\n- Run pnpm through mise: `mise exec -- pnpm --dir=web ...`.\n- Keep package manager changes scoped to `web/` unless a repo task says\n  otherwise.\n- Do not bypass formatter or type checks by weakening types.\n- Use the local app/package patterns in `web/` before introducing abstractions.\n\n## Documentation conventions\n\n- Follow `docs/engineering/contributing/quality/documentation.mdx`.\n- Product docs live in `docs/product/` and need `docs/product/docs.json` nav\n  entries when adding pages.\n- Engineering docs live in `docs/engineering/` and need\n  `docs/engineering/docs.json` nav entries when adding pages.\n- Use `bash` for shell code blocks.\n- Prefer root-relative internal doc links.\n- Do not use em dashes in docs.\n\n## Verification\n\nChoose the smallest check that proves the change.\n\n- Go source change: targeted `mise exec -- rask ./path`.\n- Go file added or imports changed: `mise run build`.\n- Shared Go behavior or broad service change: `mise run test` when practical.\n- TypeScript change: targeted `mise exec -- pnpm --dir=web ...` command.\n- Formatting-sensitive change: `mise run fmt` or the narrower formatter task.\n- Docs-only change: link/content review. Note if no formatter applies.\n\nReport failed or skipped verification honestly.\n\n## PlanetScale and Query Insights\n\nUnkey runs on PlanetScale Vitess. Every production MySQL query should carry SQLCommenter tags so Query Insights can attribute load by service, operation, and deploy.\n\n- Go: inject tags through `db.Config.Tags` and `sqlcomment.ForService` in service `run.go`. See [`pkg/mysql/sqlcomment`](pkg/mysql/sqlcomment/doc.go).\n- TypeScript: use `createCommentedPool` from `@unkey/db` instead of raw `mysql.createPool`.\n- Never put high-cardinality values (user ids, key ids, request ids) in SQL comments.\n- Full guide: [`docs/engineering/infra/planetscale/query-insights-tags.mdx`](docs/engineering/infra/planetscale/query-insights-tags.mdx).\n\n## High-signal references\n\n- Local development: `docs/engineering/contributing/local/development.mdx`.\n- Build workflow: `docs/engineering/contributing/tooling/builds.mdx`.\n- Code quality: `docs/engineering/contributing/quality/code-quality.mdx`.\n- Testing: `docs/engineering/contributing/quality/testing/index.mdx`.\n- Documentation: `docs/engineering/contributing/quality/documentation.mdx`.\n","category":"root","tokens":1459}]}