← back to Cli Printing Press
fix(skills): canonicalize auth env var when slug-derived differs (#1428)
2988814e0585f9ede348ffbeb80c6cdf219f92d9 · 2026-05-14 23:43:12 -0700 · Trevin Chow
* fix(skills): canonicalize auth env var when slug-derived differs
Extend Pre-Generation Auth Enrichment so the canonical-env-var check
also fires when auth IS present, not only when auth is missing or
auth.type is none. Agents now compute the slug-derived env var the
generator will pick, compare against canonical names surfaced in Phase
1 research / Phase 1.5a MCP source analysis / community wrapper docs,
and add x-auth-env-vars on the security scheme before running generate
when they diverge.
Avoids the post-generation patching pattern (editing config.go Load
plus doctor.go env-var checks after a doctor FAIL against the
operator's real environment) that retro #1157 surfaced on Keap and
that recurs across Stripe, HubSpot, Twilio, and other established APIs
where the canonical token name differs from the security-scheme slug.
x-auth-env-vars parsing already exists in internal/openapi/parser.go;
no generator-code change needed.
Refs #1157
* fix(skills): correct Twilio example and note OAuth2 client_credentials trap
Addresses Greptile review on PR #1428:
- Twilio HTTP Basic actually derives TWILIO_USERNAME + TWILIO_PASSWORD
(per TestOpenAPIHTTPBasicAuthDefaultEnvVars), and the canonical pair
is TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN. Old bullet showed a single
TWILIO_AUTH_TOKEN override against a wrong TWILIO_API_KEY slug-form,
which would silently break the Basic {username}:{password} format
string for an agent following the example verbatim.
- applyAuthEnvVarDefaults in internal/openapi/parser.go re-applies the
default CLIENT_ID / CLIENT_SECRET pair for OAuth2 client_credentials
whenever x-auth-env-vars has fewer than 2 entries. A single canonical
override on that grant would be silently lost. Step 3 now calls out
the threshold and points agents at x-auth-vars for the single-
service-account-token case.
Also expands the YAML example block to cover the HTTP Basic two-var
pair alongside the single-token bearer/oauth2-authorization-code case,
so the examples match the corrected bullets directly.
Refs #1157
Files touched
M skills/printing-press/SKILL.md
Diff
commit 2988814e0585f9ede348ffbeb80c6cdf219f92d9
Author: Trevin Chow <trevin@trevinchow.com>
Date: Thu May 14 23:43:12 2026 -0700
fix(skills): canonicalize auth env var when slug-derived differs (#1428)
* fix(skills): canonicalize auth env var when slug-derived differs
Extend Pre-Generation Auth Enrichment so the canonical-env-var check
also fires when auth IS present, not only when auth is missing or
auth.type is none. Agents now compute the slug-derived env var the
generator will pick, compare against canonical names surfaced in Phase
1 research / Phase 1.5a MCP source analysis / community wrapper docs,
and add x-auth-env-vars on the security scheme before running generate
when they diverge.
Avoids the post-generation patching pattern (editing config.go Load
plus doctor.go env-var checks after a doctor FAIL against the
operator's real environment) that retro #1157 surfaced on Keap and
that recurs across Stripe, HubSpot, Twilio, and other established APIs
where the canonical token name differs from the security-scheme slug.
x-auth-env-vars parsing already exists in internal/openapi/parser.go;
no generator-code change needed.
Refs #1157
* fix(skills): correct Twilio example and note OAuth2 client_credentials trap
Addresses Greptile review on PR #1428:
- Twilio HTTP Basic actually derives TWILIO_USERNAME + TWILIO_PASSWORD
(per TestOpenAPIHTTPBasicAuthDefaultEnvVars), and the canonical pair
is TWILIO_ACCOUNT_SID + TWILIO_AUTH_TOKEN. Old bullet showed a single
TWILIO_AUTH_TOKEN override against a wrong TWILIO_API_KEY slug-form,
which would silently break the Basic {username}:{password} format
string for an agent following the example verbatim.
- applyAuthEnvVarDefaults in internal/openapi/parser.go re-applies the
default CLIENT_ID / CLIENT_SECRET pair for OAuth2 client_credentials
whenever x-auth-env-vars has fewer than 2 entries. A single canonical
override on that grant would be silently lost. Step 3 now calls out
the threshold and points agents at x-auth-vars for the single-
service-account-token case.
Also expands the YAML example block to cover the HTTP Basic two-var
pair alongside the single-token bearer/oauth2-authorization-code case,
so the examples match the corrected bullets directly.
Refs #1157
---
skills/printing-press/SKILL.md | 66 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 66 insertions(+)
diff --git a/skills/printing-press/SKILL.md b/skills/printing-press/SKILL.md
index d6bb4b18..df9006a5 100644
--- a/skills/printing-press/SKILL.md
+++ b/skills/printing-press/SKILL.md
@@ -1642,6 +1642,72 @@ name in `env_vars`; do not add guessed slug-based aliases. For OpenAPI specs,
prefer `x-auth-env-vars` on the selected security scheme when the wrapper slug
differs from the underlying API brand.
+**If auth IS present** in the spec but Phase 1 evidence shows the slug-derived
+env var will differ from the canonical name users have already set for this
+API, enrich the spec with the canonical name before generation. The
+slug-derivation rule (security-scheme slug uppercased plus `_TOKEN` /
+`_API_KEY` / `_OAUTH2` per type) rarely matches the canonical name for
+established APIs. Common shapes:
+
+- Stripe (bearer): canonical `STRIPE_SECRET_KEY`, not slug-derived `STRIPE_OAUTH2`
+- HubSpot (bearer): canonical `HUBSPOT_PRIVATE_APP_TOKEN`, not slug-derived `HUBSPOT_API_KEY`
+- Twilio (HTTP Basic, two-var pair): canonical `TWILIO_ACCOUNT_SID` + `TWILIO_AUTH_TOKEN`, not slug-derived `TWILIO_USERNAME` + `TWILIO_PASSWORD`
+- Keap (OAuth2 authorization-code): canonical `KEAP_SERVICE_ACCOUNT_KEY`, not slug-derived `KEAP_OAUTH2`
+
+Walk through:
+
+1. Compute the slug-derived env var the generator will pick (security-scheme
+ slug, uppercased, plus the type-suffix above; HTTP Basic produces a
+ `_USERNAME` + `_PASSWORD` pair; OAuth2 `client_credentials` produces a
+ `_CLIENT_ID` + `_CLIENT_SECRET` pair).
+2. Check Phase 1 research, Phase 1.5a MCP source code analysis, and community
+ wrapper READMEs for a canonical env var name documented by the vendor or
+ in widespread use.
+3. If they differ, add `x-auth-env-vars` on the selected security scheme
+ (OpenAPI) or set `auth.env_vars` to the canonical name (internal YAML).
+ Use only the canonical name; do not retain the slug-derived form as an
+ alias. For HTTP Basic, supply the full two-entry canonical pair
+ (username position first, password position second). For OAuth2
+ `client_credentials`, the parser silently re-applies the
+ `CLIENT_ID`/`CLIENT_SECRET` default when `x-auth-env-vars` has fewer
+ than two entries (see `applyAuthEnvVarDefaults` in
+ `internal/openapi/parser.go`); if the canonical secret is a single
+ service-account token for a `client_credentials` flow, use
+ `x-auth-vars` instead (next section) so the override is preserved.
+4. If research surfaces no canonical name distinct from the slug-derived
+ form, do nothing. The slug-derived name is fine, and a spurious
+ `x-auth-env-vars` would just shadow it with the same value.
+
+```yaml
+# Bearer / API-key single-token case (Stripe, HubSpot, Keap on
+# authorization-code grant, most apiKey schemes).
+components:
+ securitySchemes:
+ keapOAuth2:
+ type: oauth2
+ flows:
+ authorizationCode: { ... }
+ x-auth-env-vars:
+ - KEAP_SERVICE_ACCOUNT_KEY
+```
+
+```yaml
+# HTTP Basic two-var canonical pair (Twilio).
+components:
+ securitySchemes:
+ basicAuth:
+ type: http
+ scheme: basic
+ x-auth-env-vars:
+ - TWILIO_ACCOUNT_SID
+ - TWILIO_AUTH_TOKEN
+```
+
+Skipping this step pushes the agent into hand-patching
+`internal/config/config.go` Load and `internal/cli/doctor.go` env-var
+checks after a `doctor` FAIL against the operator's real environment.
+Enriching the spec avoids that round-trip.
+
For OpenAPI specs that need richer env-var metadata (kind classification,
optional credentials, OR-group relationships), use `x-auth-vars` on the
security scheme. See `docs/SPEC-EXTENSIONS.md` for the canonical schema.
← 55b0f16b feat(skills): contain session-state.json outside DISCOVERY_D
·
back to Cli Printing Press
·
fix(cli): derive doctor auth.verify_path from me-shaped endp 95f03501 →