Skip to content

fix(cli): register two-field basic auth at root so auth status lists it [FER-11474]#16761

Open
fern-support wants to merge 2 commits into
mainfrom
judah/fer-11474-mailchimp-cli-generator-auth-status-reports-no-auth-schemes
Open

fix(cli): register two-field basic auth at root so auth status lists it [FER-11474]#16761
fern-support wants to merge 2 commits into
mainfrom
judah/fer-11474-mailchimp-cli-generator-auth-status-reports-no-auth-schemes

Conversation

@fern-support

@fern-support fern-support commented Jun 26, 2026

Copy link
Copy Markdown
Collaborator

Summary

Fixes FER-11474. Generated Fern CLIs whose auth resolves to standard two-field HTTP Basic report No auth schemes are declared from <bin> auth status, even though credentials are wired and requests authenticate correctly. This is cosmetic but confusing — it surfaced while a prospect evaluated the Mailchimp CLI.

Root cause

There are two auth_bindings registries in fern-cli-sdk:

  • App-level on the framework CliApp — populated by .auth(...). This is the only list the framework auth subcommand reads (dispatch_auth(..., &self.auth_bindings, ...)handle_status).
  • Binding-level on OpenApiBinding — populated by .auth_basic_scheme(...).

propagate_root_auth pushes app-level auth down to bindings via set_root_auth, but there is no reverse harvest, so binding-level schemes never reach the list auth status reads.

The generator's detectAuth.ts placed schemes accordingly:

scheme placement visible in auth status?
bearer root (.auth(BearerAuth))
header root (.auth(ApiKeyAuth))
basic (two-field) binding (.auth_basic_scheme)

Basic was the one scheme not migrated to root when the auth-at-root architecture landed (fern 8c3588d9dec) — the BasicAuth root builder existed and was unit-tested in cli-sdk (b4e773d), but no sample binary exercised it, so it was overlooked.

Change

Emit two-field basic via the root BasicAuth typed builder:

-.auth_basic_scheme("basicAuth", AuthCredentialSource::from_env("X_USERNAME"), AuthCredentialSource::from_env("X_PASSWORD"))   // on OpenApiBinding
+.auth(BasicAuth::new("basicAuth").username_env("X_USERNAME").password_env("X_PASSWORD"))                                       // at root

Why this is safe for existing users

  • BasicAuth::into_binding() lowers to the identical SchemeBinding::Basic { username, password } variant as .auth_basic_scheme(...).
  • set_root_auth still propagates root auth into every binding, so request-time credential resolution is unchanged byte-for-byte.
  • The only added effects are (a) the scheme now appears in auth status, and (b) validate_auth runs for it — and that path warns, never errors.

Explicitly out of scope

The usernameOmit / passwordOmit custom-provider variants (e.g. the Close "API-key-in-basic-slot" pattern) stay binding-level — there is no root path for BasicAuthProvider. Those configs see zero change and do not regress. Giving them accurate auth status requires a root provider path or a binding→app harvest, tracked separately.

Testing

  • Updated and ran detectAuth.test.ts (12 passing) — asserts root placement + BasicAuth builder output for two-field basic.
  • Ran consumer suites copySpecs / emitReadme / emitReference / generateAgentSkills (44 passing) — confirms main.rs rendering, README, and skills are unaffected.

Recommended reviewer/CI check

The end-to-end seed repro from the ticket (builds + runs a real basic-auth CLI):

pnpm seed run --generator cli \
  --path ~/.frond/companies/mailchimp/config-repo/fern/apis/mailchimp-cli \
  --output-path /tmp/mailchimp-seed-out --skip-scripts
cd /tmp/mailchimp-seed-out && cargo build
MAILCHIMP_USERNAME=any MAILCHIMP_PASSWORD=fake ./target/debug/mailchimp auth status

Expected after this change: auth status lists the basicAuth scheme instead of "No auth schemes are declared."


Open in Devin Review

…s it [FER-11474]

Generated CLIs wired standard HTTP Basic via `.auth_basic_scheme(...)` on the
OpenApiBinding (binding-level), but the framework `auth` subcommand only reads
app-level auth bindings. Result: `<bin> auth status` printed "No auth schemes
are declared" for basic-auth CLIs even though credentials flowed and requests
authenticated correctly.

Emit two-field basic via the root `BasicAuth` typed builder instead, matching
how bearer and header schemes are already placed. The root builder lowers to
the identical `SchemeBinding::Basic` and still propagates to the binding via
`set_root_auth`, so request-time behavior is unchanged — this only makes the
scheme visible to `auth status` (and the warn-only startup validation).

The usernameOmit/passwordOmit custom-provider variants stay binding-level; no
root path exists for `BasicAuthProvider`, so those configs are untouched.
@fern-support fern-support requested a review from Swimburger as a code owner June 26, 2026 20:41
devin-ai-integration[bot]

This comment was marked as resolved.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants