Skip to content

fix(cli): use cobra mutual-exclusivity template in sso add - #5974

Open
Coly010 wants to merge 6 commits into
developfrom
columferry/cli-1982-sso-add-mutual-exclusivity-error-is-not-cobra-format
Open

fix(cli): use cobra mutual-exclusivity template in sso add#5974
Coly010 wants to merge 6 commits into
developfrom
columferry/cli-1982-sso-add-mutual-exclusivity-error-is-not-cobra-format

Conversation

@Coly010

@Coly010 Coly010 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

What changed

sso add emitted a hand-written mutual-exclusivity error (only one of --metadata-file or --metadata-url may be set) and detected the conflict via Option.isSome on parsed flag values. The Go CLI enforces this group via cobra's MarkFlagsMutuallyExclusive("metadata-file", "metadata-url") (apps/cli-go/cmd/sso.go:164), whose error template is:

if any flags in the group [metadata-file metadata-url] are set none of the others can be; [metadata-file metadata-url] were all set

sso update was already migrated to the shared cobraMutuallyExclusiveErrorMessage helper plus raw-argv pflag.Changed-semantics detection (CLI-1902); add was never migrated. This PR mirrors update's pattern in add.handler.ts:

  • Byte-exact cobra template via cobraMutuallyExclusiveErrorMessage (group in Go's registration order; the violating subset sorted, per cobra's validateExclusiveFlagGroups).
  • hasExplicitValueFlag raw-argv scan, so an explicit empty value (--metadata-file= --metadata-url x) still trips the mutex, while a bare --metadata-file --metadata-url (pflag consuming the second token as the first flag's value) correctly does not.
  • The check runs before project-ref resolution, matching cobra's ValidateFlagGroups-before-RunE precedence.

Integration tests cover the exact-message case (byte-match), the explicit-empty --metadata-file= case, the consumed-value non-violation case, and single-flag happy paths. SIDE_EFFECTS.md now documents the cobra template and Changed semantics.

Review findings deliberately left open

A four-perspective review pass (architect / engineer / security / DX) approved the change; these pre-existing, cross-cutting observations were noted rather than fixed here:

  • The mutex filter/fail orchestration is now duplicated between sso add and sso update — a family-root helper (e.g. sso.mutex.ts) is a reasonable follow-up.
  • SSO_ADD_VALUE_FLAG_NAMES (like update's equivalent) is a hand-maintained mirror of the command's declared value flags with no compile-time sync guarantee.
  • Telemetry flushes on a mutex violation, whereas Go's cobra fails flag-group validation before telemetry is installed — pre-existing divergence shared with sso update.
  • The raw-argv scan doesn't understand global/inherited value flags or the -t shorthand — documented limitation shared with sso update; pflag fails -t's enum validation before flag groups anyway.
  • The --domains= explicit-empty edge on add (parity audit §3.10) is a separate issue and is not addressed here.

Fixes CLI-1982

https://linear.app/supabase/issue/CLI-1982/sso-add-mutual-exclusivity-error-is-not-cobra-format

@Coly010

Coly010 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bb94ec7ee8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/sso/add/add.handler.ts Outdated
…(review: PR #5974)

The raw-argv mutex scan and the Effect parser could disagree on which
flags pflag would consider set: pflag consumes flag-shaped tokens as
values unconditionally, the Effect parser does not. The scan matched
pflag for the mutex check, but the handler then acted on the parsed
Options — so 'sso add --type saml --project-ref --metadata-file x.xml
--metadata-url u' suppressed the mutex yet read the metadata file and
POSTed metadata_xml, an API call the Go CLI never makes (Go fails
AssertProjectRefIsValid on the consumed value '--metadata-file' in
PersistentPreRunE, cmd/root.go:113, before ValidateFlagGroups).

Replace the per-flag hasExplicitValueFlag scan with a single
pflag-faithful pflagLongFlagOccurrences pass that also yields each
flag's effective value(s), and reconcile everything both sso handlers
act on (project-ref, metadata-file, metadata-url,
attribute-mapping-file, the domain slices, and set-ness of
name-id-format/skip-url-validation) to those values. sso update shares
the same gap and gets the same fix.
@Coly010

Coly010 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

🤖 pr-autopilot needs a human here: this branch now conflicts with develop in apps/cli/src/legacy/commands/sso/update/update.handler.ts. The conflict is between this PR's pflag value-reconciliation in sso update (820f0e7, added while addressing the Codex review) and #5973 (CLI-1981, 5cd669cd — "always send domains in sso update PUT body"), which landed on develop during this run and changed the same domains body block. Both changes are wanted; the merge needs a human to combine the reconciled domains/addDomains/removeDomains values with CLI-1981's always-send-domains body shape. Per policy I don't auto-resolve conflicts, so I'm stopping here — everything else on this PR is done (CI was green on the previous head, and the one open review thread is addressed and resolved).

…2-sso-add-mutual-exclusivity-error-is-not-cobra-format

# Conflicts:
#	apps/cli/src/legacy/commands/sso/update/update.handler.ts
@Coly010

Coly010 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

Merged origin/develop (887811b). The one conflict was the domains block in update.handler.ts, resolved by combining both parity fixes: #5973's unconditional always-send-domains control flow (the else branch always recomputes and sends domains, CLI-1981) wins, but it now consumes this branch's pflag-reconciled domains/addDomains/removeDomains instead of the raw parsed flags (CLI-1982). mergeDomains' relaxed seed filter from #5973 is preserved, and the two behaviours compose cleanly — e.g. --domains= reconciles to an empty slice via the pflag scan and still falls into the merge branch, exactly as #5973's test pins. Both test suites pass unmodified: all sso add/update files (112 tests), full test:core, and check:all are green.

@Coly010

Coly010 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 887811b4e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/sso/add/add.handler.ts
Comment thread apps/cli/src/legacy/commands/sso/update/update.handler.ts Outdated
…ective argv in sso (review: PR #5974)

The pflag reconciliation kept handlers from acting on values pflag never
set, but two cobra validations that run before RunE were still invisible
to it (Codex review on 887811b):

- 'sso add --domains --type saml': pflag hands --type to --domains, so
  Go fails ValidateRequiredFlags (command.go:1007, required "type" per
  cmd/sso.go:165) and never POSTs — the TS handler POSTed with
  domains ["--type"].
- 'sso update --domains --metadata-url u <id>': the consumed token
  orphans u into the positionals, so Go fails ValidateArgs/ExactArgs(1)
  (command.go:968, cmd/sso.go:87) before any hook — the TS handler
  performed the GET and PUT.

Evolve the raw-argv scan (pflagLongFlagOccurrences -> pflagArgvScan)
into a fuller pflag walk over the closed set of flags the parser can let
through: root persistent value flags (cmd/root.go:324-333, incl. the
TS-only --output-format), value shorthands (-t/-o per parseSingleShortArg,
flag.go:1080-1094), pflag-effective positionals, and consumed long-flag
tracking. sso add emulates the required-type check ahead of the mutex
block (required beats groups); sso update emulates ExactArgs(1) ahead of
the mutex and UUID checks (arity beats both) — binary-verified orderings.
Naive per-thread fixes would have regressed '-t saml' and
'-o json <id>' / '--workdir . <id>'; the update test that expected ref
validation for '--project-ref --metadata-file x.xml ...' now expects the
arity error Go actually raises there (x.xml is positional to pflag).
@Coly010

Coly010 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 25df67c562

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/shared/cli/cobra-flag-groups.ts
Comment thread apps/cli/src/shared/cli/cobra-flag-groups.ts Outdated
Comment thread apps/cli/src/shared/cli/cobra-flag-groups.ts Outdated
…es, and interspersed flags (review: PR #5974)

Three narrow gaps in the pflag-faithful argv scan, all binary-verified
against apps/cli-go (Codex review round 3 on 25df67c):

- 'sso add --domains -t saml': pflag hands the -t token to --domains, so
  type is never Changed and Go fails ValidateRequiredFlags — the TS
  handler POSTed type "saml" with domains ["-t"]. The scan's
  consumed-token tracking now maps shorthand tokens (-t, -t=saml, -tsaml)
  to their canonical long names (consumedLongFlagNames ->
  consumedFlagNames).
- 'sso update <id> --domains': pflag fails ParseFlags (cobra
  command.go:919) with 'flag needs an argument: --domains'
  (pflag errors.go:75,78 for the 't' in -t shorthand form) before
  ValidateArgs, every hook, and RunE — the TS handlers performed the GET
  and PUT / the POST. The scan now reports missingValueError instead of
  inventing an empty occurrence, and both handlers reject it first
  (parse beats arity: 'sso update a b --domains' names the missing
  argument, not the arg count).
- 'sso --profile foo update --domains --metadata-url u <id>': cobra's
  Find/stripFlags routes through persistent flags between path segments
  and Go still raises 'accepts 1 arg(s), received 2', but the contiguous
  anchor failed and the TS handler skipped the arity re-count and
  proceeded. Anchoring now walks argv matching segments while stepping
  over flag tokens and their consumed values. (The reviewer's original
  '--project-ref' example cannot reach the handler — the Effect parser
  rejects leaf flags at the group level — but root globals like
  --profile/-o reproduce it.)

Known shared residual, unchanged from the round-2 arity emulation: Go
prints a usage block for errors raised before PersistentPreRunE sets
SilenceUsage (cmd/root.go:97), i.e. parse and arity errors; the TS
handler-level emulations render the single error line + --debug
suggestion only.
@Coly010

Coly010 commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: e2de9121e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@Coly010
Coly010 marked this pull request as ready for review July 29, 2026 13:40
@Coly010
Coly010 requested a review from a team as a code owner July 29, 2026 13:40
@github-actions

github-actions Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@07b145b174dd4ed120c91863eb944fda0aa7edf1

Preview package for commit 07b145b.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e2de9121e1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/cli/src/legacy/commands/sso/update/update.handler.ts Outdated
Comment thread apps/cli/src/legacy/commands/sso/update/update.handler.ts
…tics in sso (review: PR #5974)

The round-2 value reconciliation covered sso's string and slice flags but
left --skip-url-validation, --name-id-format, and --type on the Effect-
parsed values gated on set-ness. Those values can disagree with pflag in
two ways, both binary-verified against apps/cli-go (Codex review round 4
on e2de912):

- Repeated flags: the Effect parser resolves first-wins, pflag Sets every
  occurrence so the last wins. 'sso update <id> --skip-url-validation
  --skip-url-validation=false --metadata-url http://x' skips URL
  validation in TS but validates (and rejects non-HTTPS) in Go; the
  mirror argv diverges the other way, and '--domains' consuming one of
  two --name-id-format occurrences flips which URN lands in the PUT body.
- Set-rejected values: pflag aborts ParseFlags on any occurrence its
  Value.Set rejects, before every hook, validation, and request. The
  Effect parser accepts yes/no booleans (strconv.ParseBool does not) and
  never validates the repeats it discards, so '--type saml --type bogus'
  and '--skip-url-validation=yes' reached the handlers and called the API
  where Go exits 1 with 'invalid argument ...'.

The scan already records every non-consumed occurrence with its raw
value, so the fix stays at the established handler-emulation level: two
new helpers in sso.pflag-reconcile.ts re-run pflag's per-occurrence Set
over the scan output (ParseBool set; enum membership; byte-exact pflag
error messages incl. the '-t, --type' shorthand label) and yield the
last-occurrence effective values the handlers now act on. Checks sit
ahead of the missing-value emulation, matching pflag's sequential walk
(an occurrence always precedes a trailing bare flag; binary-verified
'--skip-url-validation=yes --domains' names the invalid argument).

The shared NAME_ID_FORMATS list is hoisted to sso.saml.ts per the
family-root rule. Known residuals unchanged: parse errors raised before
Go sets SilenceUsage print cobra's usage block in Go only, and boolean
literals ParseBool accepts but the Effect parser rejects (t/T/TRUE/...)
still fail at the TS parse layer with the parser's own error.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 07b145b174

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +49 to +52
try {
return legacyParseStringSliceFlag(values);
} catch {
return parsedFallback;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject malformed repeated domain values

When a valid domain occurrence is followed by malformed CSV, such as sso add --type saml --domains good.example --domains='"bad', the Effect parser's first-wins behavior allows the handler to run, while pflag calls StringSlice.Set for every occurrence and rejects the malformed second value before any hook or request. This catch instead returns the already-parsed first occurrence, so add can POST—and update can GET/PUT—where Go exits with an invalid-argument error; propagate the CSV parse failure rather than falling back.

AGENTS.md reference: apps/cli/AGENTS.md:L248-L256

Useful? React with 👍 / 👎.

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.

1 participant