You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
feat(auth): default human views and default fields for auth status/login - #129
The built-in auth status / auth login declared no human view, so their columns rendered in alphabetical order (ENV EXPIRED EXPIRES_AT IDENTITY PROVIDER REFRESHABLE), and a consumer had no supported way to change them short of replacing the whole auth group.
Changes
Default views. Both commands render through the view ids auth:status / auth:login (AUTH_STATUS_VIEW_ID, AUTH_LOGIN_VIEW_ID). The engine registers default_auth_status_view() / default_auth_login_view() (identity, expires, env, provider, expired, refreshable, scopes) only when nothing already holds the id, so a view from CliConfig::with_view or register_global_human_view always wins, including across a later register_auth_provider.
Default fields.CliConfig::with_auth_status_default_fields / with_auth_login_default_fields set the commands' default_fields, so a consumer can leave a column out by default (e.g. provider) while it stays available with --fields. As with any default_fields, this also projects JSON/TOON output.
Schema.AuthStatusEntry / AuthLoginResult derive JsonSchema and are registered on the commands, so --help lists every output field (marking defaults) and --schema works.
--expr and views. A fixed view rendered a blank table when --expr reshaped the result into fields it doesn't name (a regression for auth status / auth login, which previously rendered generically), and view-based --fields validation rejected names from the expression's result. In human output, --expr now means the command has no view: the result renders generically and --fields is validated and projected against it, as for JSON. --filter keeps the view. This applies to every view-backed command. (refined during review)
Help fixes found along the way.
--fields printed clap's [default: ...] after the last row of the output-field table; it is now on the flag's first line.
--interactive always claimed "(default when TTY is detected)"; it now says so only when auto_interactive is enabled.
Testing
New tests/auth_views.rs covers the default views, a view override (and that it survives a later provider registration), default fields keeping provider selectable, JSON projection, the help output, and --expr / --fields interplay (generic rendering, validation, and projecting from the expression result). tests/interactivity.rs covers the --interactive help text. cargo fmt, clippy -D warnings, cargo doc, cargo test --all-targets, cargo test --doc, check-module-size.sh and missing-docs (0) all pass. Also checked end to end against gddy with a local path patch.
The built-in `auth status` and `auth login` had no human view, so their
columns rendered in alphabetical order and a consumer could not change
them without replacing the whole auth group.
- Render both through the views `auth:status` / `auth:login`
(`AUTH_STATUS_VIEW_ID`, `AUTH_LOGIN_VIEW_ID`). The engine registers
`default_auth_status_view()` / `default_auth_login_view()` (identity,
expires, env, provider, ...) unless the consumer already registered a
view under that id, so an override is never clobbered.
- Add `CliConfig::with_auth_status_default_fields` and
`with_auth_login_default_fields` to choose the default `--fields`
without removing columns from the view.
- Register a JSON schema for `AuthStatusEntry` / `AuthLoginResult` so
`--help` lists every output field and `--schema` works.
- Print `[default: ...]` for `--fields` on the flag's first help line
instead of after the last row of the output-field table.
- Only say `--interactive` is the default on a TTY when
`auto_interactive` is enabled.
Refs DEVEX-1267
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…of the data
A fixed human view rendered an all-blank table when `--expr` reshaped the
result into fields the view never names (e.g. `auth status --expr
'{user: identity}'`). Render such data generically instead. Only data that
is objects, none of which resolve any of the view's columns, falls back;
a view that matches at least one column keeps rendering as before.
Refs DEVEX-1267
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Adding this view rejects explicit fields created by --expr before the new rendering fallback can run. For example, auth status --provider primary --env prod --expr '{user: identity}' --fields user --output human fails with an unknown-field error because middleware/run.rs:516–539 validates user against the auth view before evaluating the expression. Login is affected too. Defer view-specific validation until the transformed shape is known, and validate explicit selections against the transformed data when using generic rendering. Add regression tests for both commands.
A view whose columns are all optional would fall back to generic rendering
for an ordinary response that merely lacked those fields, dropping the view.
Fall back only when `--expr` reshaped the data.
Refs DEVEX-1267
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
`--expr` can reshape the result into any shape, so the view's columns say
nothing about what `--fields` may name. Skip the view-catalog check in that
case, and let the generic fallback apply an explicit `--fields` to the
reshaped data.
Refs DEVEX-1267
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Re the review-body finding "Validate fields after expression reshaping": fixed in 5117d05. --fields is no longer validated against the view's columns when --expr is set, since the expression's result can be any shape. When the generic fallback renders a reshaped result, an explicit --fields is applied to it, so auth status --expr '{user: identity}' --fields user now works for both auth status and auth login. This also fixes the same failure for any other view-backed command. Without --expr, an unknown --fields name is still rejected (covered by tests).
`--expr` hands the caller control of the result's shape, so a registered
view's columns no longer describe it. Treat the command as having no view
in human output when `--expr` is set; the existing pipeline then validates
and projects `--fields` against the expression's result, as it does for
JSON. This replaces the earlier fallback heuristic and skipped validation,
both of which left edge cases (typos accepted, explicit fields dropped when
the result kept one view column). `--filter` still keeps the view.
Refs DEVEX-1267
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
Possible bug: --expr combined with with_auth_*_default_fields may give empty output
Re the new view_id override in cli-engine/src/middleware/run.rs: I think the default-fields fallback still runs after --expr changes the result's shape. If --fields isn't passed, effective_fields falls back to default_fields, and apply_pipeline projects onto those names after the expression runs. Default fields are never checked against the data (fields_are_default: true), so names the expression's result doesn't have are dropped without any error.
Untested repro, from reading the code:
let cli = cli_with(config().with_auth_status_default_fields(NO_PROVIDER));run(&cli,&["auth","status","--provider","primary","--env","prod","--expr","{user: identity}","--output","human"]).await
I'd expect user tester. As far as I can tell, {user: "tester"} gets projected onto identity,expires_at,env,…, which leaves {}, so the output is blank. JSON output would have the same problem.
The existing expr_* tests don't set default fields, so they wouldn't catch this. Since hiding provider with with_auth_status_default_fields is the main reason to use the new API, this combination seems likely to come up in practice.
One possible fix: when --expr is set and --fields wasn't passed explicitly, skip the default-fields projection, because default fields describe the command's own output, not the expression's. Roughly:
let effective_fields = ifself.fields_explicit{self.fields.as_str()}elseif !self.expr.is_empty(){""}else{
default_fields
};
This would also change JSON/TOON output for any command that has default_fields and is run with --expr. I think that's the right behavior, but it's worth deciding on purpose. Am I missing something that already handles this?
When `--expr` was set without an explicit `--fields`, `effective_fields`
still fell back to the command's `default_fields` and projected those names
onto the expression's result. Since default-field projection is never
validated against the data, names the result lacked were silently dropped,
collapsing e.g. `auth status --expr '{user: identity}'` to `{}` / `(no data)`
whenever the command had default fields set (as a consumer does to hide
`provider`). Fall back to no projection under `--expr` instead. Affects
JSON/TOON too, intentionally: default fields describe the command's own
output, not the expression's.
Refs DEVEX-1267
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Good catch, and you're right — confirmed the repro. With default_fields set, auth status --expr '{user: identity}' (no --fields) projected identity,expires_at,env,… onto {user: tester} and collapsed it to {} / (no data), in JSON too. My round-3 change dropped the view under --expr but left effective_fields falling back to default_fields, so the projection still ran.
Fixed in b4f3d7a with your suggested change: under --expr with no explicit --fields, effective_fields is "" rather than default_fields, so nothing is projected and the expression's result renders as-is. An explicit --fields still applies; --filter still keeps the view and default fields. As you noted this also changes JSON/TOON for any default_fields command run with --expr, which is the intended behavior. Added a regression test with default fields set (the gap the existing expr_* tests missed), covering status and login in both human and JSON, and verified against the gddy build.
The reason will be displayed to describe this comment to others. Learn more.
🟢 Approval recommended
No unresolved blocking issues remain, and focused regression tests cover the changed behavior and previously reported problems.
No open issues 🎉
Review effort: Balanced
This branch has not been deployed
No deployments
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs DEVEX-1267.
Problem
The built-in
auth status/auth logindeclared no human view, so their columns rendered in alphabetical order (ENV EXPIRED EXPIRES_AT IDENTITY PROVIDER REFRESHABLE), and a consumer had no supported way to change them short of replacing the wholeauthgroup.Changes
auth:status/auth:login(AUTH_STATUS_VIEW_ID,AUTH_LOGIN_VIEW_ID). The engine registersdefault_auth_status_view()/default_auth_login_view()(identity, expires, env, provider, expired, refreshable, scopes) only when nothing already holds the id, so a view fromCliConfig::with_vieworregister_global_human_viewalways wins, including across a laterregister_auth_provider.CliConfig::with_auth_status_default_fields/with_auth_login_default_fieldsset the commands'default_fields, so a consumer can leave a column out by default (e.g.provider) while it stays available with--fields. As with anydefault_fields, this also projects JSON/TOON output.AuthStatusEntry/AuthLoginResultderiveJsonSchemaand are registered on the commands, so--helplists every output field (marking defaults) and--schemaworks.--exprand views. A fixed view rendered a blank table when--exprreshaped the result into fields it doesn't name (a regression forauth status/auth login, which previously rendered generically), and view-based--fieldsvalidation rejected names from the expression's result. In human output,--exprnow means the command has no view: the result renders generically and--fieldsis validated and projected against it, as for JSON.--filterkeeps the view. This applies to every view-backed command. (refined during review)--fieldsprinted clap's[default: ...]after the last row of the output-field table; it is now on the flag's first line.--interactivealways claimed "(default when TTY is detected)"; it now says so only whenauto_interactiveis enabled.Testing
New
tests/auth_views.rscovers the default views, a view override (and that it survives a later provider registration), default fields keepingproviderselectable, JSON projection, the help output, and--expr/--fieldsinterplay (generic rendering, validation, and projecting from the expression result).tests/interactivity.rscovers the--interactivehelp text.cargo fmt,clippy -D warnings,cargo doc,cargo test --all-targets,cargo test --doc,check-module-size.shand missing-docs (0) all pass. Also checked end to end against gddy with a local path patch.🤖 Generated with Claude Code