<!-- BEGIN GENERATED: tidbcloud-auth skill -->
# tidbcloud-auth — skill adapter (Google Gemini CLI)

**Use this skill when:** Use when working with TiDB Cloud Auth, including Admin API automation, project setup, database bindings, table creation or publication, policies, Google/GitHub/OIDC auth providers, Data API and Auth API documentation, @tidbcloud/auth-js frontend apps, type generation, or troubleshooting published table/Auth/Data API access.

This project ships the `tidbcloud-auth` skill. The canonical instructions are [`skills/tidbcloud-auth/SKILL.md`](skills/tidbcloud-auth/SKILL.md), with detailed references under `skills/tidbcloud-auth/references/`. The guidance below is mirrored from that skill; run its CLI from the project root using the paths shown.

# TiDB Cloud Auth

## Core Rules

Use bundled scripts for Admin API mutations. Use `@tidbcloud/auth-js` for
frontend application code. Verify endpoint contracts from generated references
before calling unfamiliar endpoints.

Do not place Admin private keys, service key secrets, OAuth client secrets, raw
DSNs, bearer tokens, refresh tokens, or user JWTs in prompts, frontend files,
logs, generated docs, or reports.

Treat the single `.tidbcloud-auth/*.env` project file as secret. Never open,
print, or shell-source it. Run the bundled CLI from the target project root;
the CLI securely discovers exactly one such file before every command. Zero
files means no project config; multiple files fail closed.

Do not use public Data API routes for DDL, DCL, raw SQL, RPC, stored procedure
execution, schema mutation, or PostgREST compatibility. Table creation and
publication must go through Admin API workflows.

## Before You Start

Before a mutating command, confirm the following inputs. Ask in one pass only
for items still missing from the user's request, the single project env file,
`.tidbcloud-auth/setup-result.json`, or `scopes preflight`; never ask the user to
repeat discovered values or perform an environment setup step. Read-only
commands (`doctor`, `scopes preflight`, `docs check`) may run first to resolve
unknowns.

- **Task type & project name** — new-app provisioning or a one-off Admin
  operation, and the project name (and whether it already exists).
- **Database / BYO DSN** — whether a BYO TiDB DSN is available (required for
  `binding create --yes`). Never accept the DSN itself in the prompt; it is
  supplied through `TIDBCLOUD_AUTH_DB_DSN` at execute time, normally from the
  automatically loaded project env file.
- **Auth providers** — which of Google / GitHub / OIDC / email the app needs.
- **App origins & redirect URIs** — the browser origin(s) for client-key
  `--allowed-origins` and the OAuth `--redirect-uris`.

Never ask the user to paste secret material (private keys, service key secrets,
OAuth client secrets, DSNs, tokens) into the conversation — see Core Rules.

## Script Entry Point

Run the consolidated CLI by its resolved Skill path while keeping the command
working directory at the target project root. In the examples, `$SKILL_DIR`
means the absolute directory containing this loaded `SKILL.md`; native Skill
agents resolve it internally, and generated adapters replace it with their
project-relative installed path. Never ask the user to set this variable. The
CLI automatically loads the single `.tidbcloud-auth/*.env`; do not ask the user to
run `source`, pass an env file flag, or copy values into the shell:

```sh
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" doctor
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" scopes preflight
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" docs generate
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" docs check
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" project setup --name NAME --owner-user-id USER_ID --reveal-to .tidbcloud-auth/project-admin.json
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" project bootstrap --profile auth_ready --reason "prepare application" --reveal-to .tidbcloud-auth/bootstrap-secrets.json
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" binding create --name main --bootstrap-profile auth_ready
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" binding get
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" binding normalize-dsn
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" binding validate
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" key client create --name web --allowed-origins https://app.example
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" key service create --name private-ops --reveal-to service-key.json
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" table create --name todos --columns id:bigint,title:varchar(255) --apply
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" schema version create --state active
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" schema refresh
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" table publish --spec publish.json
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" policy upsert --resource todos --action table.read --owner-column user_id
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" policy simulate --resource todos --action table.read
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" auth provider --provider github --client-id GITHUB_CLIENT_ID --redirect-uris https://app.example/callback
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" oauth google --client-id GOOGLE_CLIENT_ID --redirect-uris https://app.example/callback
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" auth mail-provider --from-email no-reply@app.example --smtp-host smtp.example --smtp-port 587
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" frontend scaffold --output ./app --name app-name --schema-file schema.json
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" typegen --schema-file schema.json --output app/src/database.types.ts
```

Provision in this exact order: `doctor` -> `scopes preflight` -> optional
`project setup` -> existing-project `project bootstrap` when readiness requires
it -> `binding create` -> `binding get` + `binding validate` ->
`key client create` -> requested providers/settings -> every `table create
--apply` -> `schema version create` -> `schema refresh` -> every `table
publish` -> `policy upsert` + `policy simulate` -> `frontend scaffold` ->
`typegen` -> `project readiness` -> SDK runtime smoke tests. Never publish
before schema refresh proves that exact version. Never generate types before
publication and policy readbacks pass. Run `typegen` after the starter is
copied so its `database.types.ts` cannot be replaced by a template. Executed `binding` and
`key client` results are threaded into `.tidbcloud-auth/setup-result.json`, so a
later `frontend scaffold` wires the app without re-passing URLs or the client
key.

Use logical names such as `--name main`, `--name web`, and table resource names.
Do not invent fixed physical metadata IDs. The CLI derives stable physical IDs
from `project_id` plus the logical identity, so the same project reruns
idempotently while two projects may use identical logical names without a
global-ID collision. Explicit operator IDs remain exact and fail closed on
project-state or remote conflicts.

Executing `project setup --yes` requires `--owner-user-id` (or
`TIDBCLOUD_AUTH_OWNER_USER_ID`) and `--reveal-to FILE`. It uses stable request
IDs, creates the project, creates a project-scoped Admin API key, writes all
one-time secrets only to the pre-reserved owner-only file, then authenticates
with the new key to read back both the project and key metadata. Setup state
stores only the project ID, public key metadata, request fingerprints, and
phase; it never stores the Admin private key. If the Admin-key create response
is lost after commit, the workflow reads back and rotates that exact key instead
of creating a duplicate grant.

`project bootstrap` is the formal recovery path for an existing project whose
readiness reports `jwt_config_missing` or `auth_configuration_required`. Use
`--profile auth_ready`, a non-empty `--reason`, and a pre-reserved
`--reveal-to FILE`; the workflow validates the project-scoped response, writes
flat first-return client/service secrets only to that 0600 file, saves only the
publishable client key in setup state, then reads readiness back. The service
key is never placed in setup state or stdout. If the mutation response is lost,
the workflow reads readiness when possible and fails closed because one-time
secrets cannot be reconstructed.

When the project env file already supplies `TIDBCLOUD_AUTH_PROJECT_ID`, reuse
that project and do not run `project setup`; run doctor/scopes and use `project
bootstrap` before binding/client/Auth only when readiness requests it.

Before provisioning, run `scopes preflight` (or `doctor` with project Admin
credentials set — it runs the same check). It reads the project Admin key's
granted scopes live from `GET /admin/v1/projects/{project_id}` and diffs them
against every write and its required GET readback, so a key missing a write or
read scope (for example `binding.write`, `project.database.read`,
`project.migration.write`, or `project.migration.read`) is reported upfront as
an exact "add these scopes in the console" list instead of failing mid-run with
`admin_forbidden`. A principal cannot grant its own scopes; add the missing
scopes to the key in the TiDB Cloud Auth console and keep the `owner` role
required by project bootstrap, then re-run. Project setup creates an owner-role
project Admin key by default; an explicitly requested lower role remains exact
and will fail preflight rather than being silently elevated.

`table create` uses an explicit `--binding-id`, then a spec `binding_id`, then
the `binding_id` saved in `.tidbcloud-auth/setup-result.json`. An optional
`--database` (or `TIDBCLOUD_AUTH_DATABASE_NAME`) is sent only as a consistency
check; it never selects the migration target. `key client create` uses
`TIDBCLOUD_AUTH_APP_ORIGIN` when no origins flag is given.

Service keys are private machine credentials for supported internal/Ops
workflows. Public Data API rejects `X-Service-Key`; use a project client key and,
when end-user policy evaluation requires it, a user bearer JWT. Executing
`key service create --yes` requires `--reveal-to FILE`; the CLI exclusively
creates that file with owner-only permissions before the network mutation.

Policy commands fail closed. The flag-built path requires an explicit
`--owner-column` for row-restricted authenticated reads, plus
`--write-owner-column` for writes. Truly unrestricted rows require the explicit
`--allow-all-rows` acknowledgement. A JSON spec may use the backend's legal
non-empty `kind: "all"` composite AST; an empty `all` node is rejected.

Publication also fails closed: every table must choose exactly one mode.
Per-user rows require `row_security` (or `--owner-column` plus
`--physical-table-ref`); a deliberately shared table requires the explicit
`disable_row_security: true` acknowledgement. Never infer or default to the
shared mode. Policies do not replace publication-level row isolation.

Admin workflow commands are dry-run by default. Review each generated body,
then add `--yes`. If the user's prompt already authorizes full creation, perform
that review and continue without asking the user to type commands or repeat
configuration. Pause only for a real missing permission, missing choice, or
unsafe conflict. `table create --apply --yes` additionally
reviews and applies the migration job. Secret material (BYO DSN, SMTP secret,
OAuth client secret, service key) is read from the environment at execute time,
never accepted as a flag or printed; use `--reveal-to FILE` to capture a created
service key once with restricted permissions.

Treat a failed command as evidence, not permission to rerun blindly. The CLI
returns a redacted JSON error with `code`, `status`, `request_id`, safe
`details`, and retry classification when available. Inspect durable readback or
the saved project journal first. The project, binding, client key, migration,
schema-version, publication, and policy paths use stable identities and narrow
lost-response recovery; a mismatched readback must stop the workflow.

## References

- **Endpoint Index** -> [references/01-endpoint-index.md](skills/tidbcloud-auth/references/01-endpoint-index.md)
  Read first for API family selection and supported surfaces.
- **Admin API** -> [references/02-admin-api.md](skills/tidbcloud-auth/references/02-admin-api.md)
  Read before Admin API calls, project setup, table publishing, policies, or
  provider configuration. This reference intentionally includes the useful
  canonical skill surface, not legacy mirrors or dashboard-backend-only routes.
- **Data API** -> [references/03-data-api.md](skills/tidbcloud-auth/references/03-data-api.md)
  Read before app-facing table reads/writes or Data API troubleshooting.
- **Auth API** -> [references/04-auth-api.md](skills/tidbcloud-auth/references/04-auth-api.md)
  Read before signup, token, password, session, email verification, or OAuth
  work.
- **Schema And Publishing** -> [references/05-schema-and-publishing.md](skills/tidbcloud-auth/references/05-schema-and-publishing.md)
  Read before creating or publishing tables.
- **Policies** -> [references/06-policies.md](skills/tidbcloud-auth/references/06-policies.md)
  Read before writing or simulating policies.
- **Auth Providers** -> [references/07-auth-providers.md](skills/tidbcloud-auth/references/07-auth-providers.md)
  Read before configuring Google, GitHub, or OIDC providers.
- **Frontend Apps** -> [references/08-frontend-apps.md](skills/tidbcloud-auth/references/08-frontend-apps.md)
  Read before scaffolding or modifying frontend code.
- **Security** -> [references/09-security.md](skills/tidbcloud-auth/references/09-security.md)
  Read for any secret, credential, policy, or auth boundary task.
- **Troubleshooting** -> [references/10-troubleshooting.md](skills/tidbcloud-auth/references/10-troubleshooting.md)
  Read when a route, table, policy, or OAuth flow does not behave as expected.
- **Skill Feedback** -> [references/11-skill-feedback.md](skills/tidbcloud-auth/references/11-skill-feedback.md)
  Read when the user reports missing or incorrect skill guidance.

## Agent Compatibility

This skill is agent-agnostic: every action runs through the Node CLI
(`scripts/tidbcloud-auth.mjs`, Node built-ins only) and plain-markdown
references, so any agent that can read files and run a shell can use it. Claude
loads it natively through this `SKILL.md`. Adapter files route other agents to
the same skill and are generated from this file — never edit them by hand:

```sh
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" agents sync    # write/update agent adapters
node "skills/tidbcloud-auth/scripts/tidbcloud-auth.mjs" agents check   # verify adapters match SKILL.md
```

Generated adapters: `AGENTS.md` (OpenAI Codex and the AGENTS.md standard),
`.github/copilot-instructions.md` (GitHub Copilot), `GEMINI.md` (Gemini CLI),
and `.cursor/rules/tidbcloud-auth.mdc` (Cursor). Re-run `agents sync` after
editing this file so every agent stays in sync.

## Environment

The normal configuration path is one owner-only
`.tidbcloud-auth/<app>.env` file under the target project root. The filename is
not fixed. The CLI finds the only `.env` file there and parses it automatically
for every command, so filling that file is the only
configuration action the user needs. It never executes the file as shell code,
does not expand `$VAR` or command substitutions, stays silent while loading,
and never replaces a variable already present in the process environment.

On macOS and Linux the file must be a regular, non-symlink file with no group or
world permissions (for example mode `0600`). Only TiDB Cloud Auth, compatible
TiDB, frontend client, and Google/GitHub/OIDC variables are accepted. An
advanced caller may override discovery with `--project-env-file FILE` or
`TIDBCLOUD_AUTH_ENV_FILE`, but normal Skill use must not require either.

Prefer scoped credentials in the project env file:

```sh
TIDBCLOUD_AUTH_ADMIN_URL=...
TIDBCLOUD_AUTH_DATA_URL=...
TIDBCLOUD_AUTH_OWNER_USER_ID=...
TIDBCLOUD_AUTH_ORG_ID=...
TIDBCLOUD_AUTH_PROJECT_ID=...
TIDBCLOUD_AUTH_ADMIN_API_KEY_ID=...
TIDBCLOUD_AUTH_ORG_ADMIN_PUBLIC_KEY=...
TIDBCLOUD_AUTH_ORG_ADMIN_PRIVATE_KEY=...
TIDBCLOUD_AUTH_PROJECT_ADMIN_PUBLIC_KEY=...
TIDBCLOUD_AUTH_PROJECT_ADMIN_PRIVATE_KEY=...
TIDBCLOUD_AUTH_CLIENT_KEY=...
TIDBCLOUD_AUTH_DATABASE_NAME=...
TIDBCLOUD_AUTH_APP_ORIGIN=http://localhost:8080
GOOGLE_OAUTH_CLIENT_ID=...
GOOGLE_OAUTH_REDIRECT_URIS=http://localhost:8080/
```

`TIDBCLOUD_AUTH_OWNER_USER_ID` and `TIDBCLOUD_AUTH_ADMIN_API_KEY_ID` are local
bootstrap identity metadata. The loader makes them available for checks, but no
workflow sends them to an API that does not define those fields.

Compatibility single-key mode may use `TIDBCLOUD_AUTH_ADMIN_PUBLIC_KEY` and
`TIDBCLOUD_AUTH_ADMIN_PRIVATE_KEY` only when the key is intentionally scoped for
the requested operation.

Secret material loaded from the file is supplied to workflows only through the
process environment and is never printed:

```sh
TIDBCLOUD_AUTH_DB_DSN=...              # BYO TiDB DSN for `binding create --yes`;
                                      # accepts the console URL form
                                      # (mysql://user:pass@host:4000/db) or the
                                      # go-driver form, and is normalized to the
                                      # go-driver form the Admin API expects
                                      # (tls=true added for *.tidbcloud.com).
                                      # Preview it with `binding normalize-dsn`.
GOOGLE_OAUTH_CLIENT_SECRET=...        # or GITHUB_/<PROVIDER>_OAUTH_CLIENT_SECRET
TIDBCLOUD_AUTH_SMTP_PASSWORD=...      # or TIDBCLOUD_AUTH_SMTP_API_TOKEN
TIDBCLOUD_AUTH_DATA_URL=...           # Data + Auth API origin used by the frontend
```
<!-- END GENERATED: tidbcloud-auth skill -->
