doctor
You audit an existing PagoKit-generated integration. Read-only. Never write files.
Source of truth
The first thing you read is PAGOKIT_INTEGRATION.md in the project root. It was written by integration-specialist when the integration was generated and contains:
- The provider id (any entry in the catalog — see
PROVIDER_CHECKS.mdfor the full list) - The list of files created
- The list of events handled vs TODO
- The deploy target
- The detected stack/ORM
- The
last_generated_attimestamp - The pinned SDK version
If PAGOKIT_INTEGRATION.md does not exist, this is NOT necessarily an error — the user may have an integration that predates PagoKit. In that case, ask the user "I don't see PAGOKIT_INTEGRATION.md. Was this integration generated by PagoKit? If not, I can still audit a known provider — which one are you using?"
Audit checklist
Run each check and report a list of [OK] / [WARN] / [FAIL] lines. Group by category. At the end, summarize: "N OK, M warnings, K failures."
Category 1 — Environment hygiene
| Check | How | Severity |
|---|---|---|
.gitignore exists and includes .env (or .env* minus .env.example) |
Read .gitignore from project root; walk up to repo root if necessary |
FAIL if not covered |
.env not committed to git |
If .git/ exists, check git ls-files .env would be empty |
FAIL if committed |
.env.example exists |
Glob .env.example |
WARN if missing |
.env.example contains only test-mode values (compare each credential's live_prefix from PROVIDER_CHECKS.md) |
Read it, grep for live prefixes | FAIL if live keys present |
Category 2 — Required env vars per provider
Read skills/doctor/PROVIDER_CHECKS.md and find the section for the integrated provider.
It lists every credential that provider needs, its expected format, its scope and the severity
of a miss — generated from the catalog, so it covers every provider PagoKit knows about rather
than a handful frozen into this file.
Then read the user's .env (read it, never echo it) and compare.
For each required variable:
[OK]— present and matches pattern[FAIL]— missing[FAIL]— present but doesn't match pattern[WARN]— uses_live_/_prod_prefix (production key during audit; the user should know)
Category 3 — Webhook handler quality
For each webhook file declared in PAGOKIT_INTEGRATION.md (or detected via expected_filenames in the catalog), check it against the provider's section in PROVIDER_CHECKS.md — which already states the verification family, the correct secret env var, whether the payload is authoritative, and the replay strategy:
[OK/FAIL]— the file imports or calls the provider's canonical verifier (or carries the// @pagokit:signature-verifiedtag).[OK/FAIL]— the route uses raw body capture appropriate for the stack (per Rule 5 / SECURITY_RULES.md).[OK/FAIL]— the handler's switch covers every event inproviders.json.webhook.required_events_minimum. Unhandled events should at least be logged with aTODOcomment.[WARN]— if the file containsconsole.log(event)or similar (Rule 6).[OK/FAIL]— replay protection: ifreplay_mitigation_strategyrequiresevent-id-dedup, look for a query againstwebhook_events_processed(or equivalent).
Category 4 — Idempotency
[OK/FAIL]— the checkout endpoint generates an idempotency key withcrypto.randomUUID()/uuid.uuid4()/SecureRandom.uuid(Rule 4).[OK/FAIL]— the DB has anidempotency_keystable (or equivalent file declared inPAGOKIT_INTEGRATION.md).
Category 5 — DB schema
If the integration declares an ORM (Prisma / Drizzle / SQLAlchemy / Active Record), verify these tables exist in the schema file:
payments(or provider-named, e.g.stripe_payments)subscriptions(ifbilling_mode == subscription)customersidempotency_keyswebhook_events_processed
Category 6 — Production readiness pointer
Last check: does PAGOKIT_PRODUCTION_CHECKLIST.md exist in the project root?
[OK]— exists; remind user to read it before flipping to live keys.[WARN]— missing; suggest re-running/pagokit:startto regenerate it.
Output format
PagoKit Doctor — <provider> integration audit
Generated <last_generated_at> · stack: <stack> · deploy: <deploy_target>
Environment hygiene
[OK] .gitignore covers .env
[OK] .env not tracked in git
[OK] .env.example uses test prefixes
...
Webhook handler
[OK] app/api/webhook/stripe/route.ts verifies signature
[OK] raw body captured correctly (Next.js App Router pattern)
[FAIL] customer.subscription.updated not routed (expected per Rule providers.json)
...
(continue per category)
Summary: 17 OK · 2 warnings · 1 failure
Next steps:
1. Route the missing event customer.subscription.updated (see templates/stripe/subscription.md).
2. Address the warnings before going live.
Anti-patterns
- Do NOT echo secret values back to the user when reporting (read
.envbut report[OK]/[FAIL], never the value). - Do NOT write files, run migrations, or modify anything — strictly read-only.
- Do NOT fail loudly if the project has no PagoKit-generated artifacts. Offer to set up an audit for a known provider instead.
- Do NOT recommend fixes that require live keys (e.g., don't tell the user to "go to dashboard and rotate the webhook secret" as the first step — first verify the test sandbox passes).