fix(cli): use cobra mutual-exclusivity template in sso add - #5974
Conversation
|
@codex review |
There was a problem hiding this comment.
💡 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".
…(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.
|
🤖 pr-autopilot needs a human here: this branch now conflicts with |
…2-sso-add-mutual-exclusivity-error-is-not-cobra-format # Conflicts: # apps/cli/src/legacy/commands/sso/update/update.handler.ts
|
Merged origin/develop (887811b). The one conflict was the domains block in |
|
@codex review |
There was a problem hiding this comment.
💡 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".
…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).
|
@codex review |
There was a problem hiding this comment.
💡 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".
…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.
|
@codex review |
|
Codex Review: Didn't find any major issues. Bravo. Reviewed commit: ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
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". |
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@8213bb0e627a9f766e6d0b7c35e46e5b14052142Preview package for commit |
There was a problem hiding this comment.
💡 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".
…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.
There was a problem hiding this comment.
💡 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".
…2-sso-add-mutual-exclusivity-error-is-not-cobra-format
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7e21b4aafc
ℹ️ 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".
…flag scan (review: codex) pflag records NoOptDefVal "true" for a bare boolean occurrence and the literal empty string for --flag= (flag.go:1013-1019), then hands "" to strconv.ParseBool, which rejects it. The argv scan conflated the two, so --skip-url-validation=false --skip-url-validation= slipped past the handler as true and issued requests the Go CLI never makes (binary-verified: Go aborts ParseFlags with 'invalid argument "" for "--skip-url-validation" flag' before any request). Record the bare form as "true" in the scan so the bool reconciler fails inline-empty values exactly like Go.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 6fb04b67b7
ℹ️ 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".
… sso add/update (review: codex)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 050108e854
ℹ️ 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".
…so add/update (review: codex)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57e608cce1
ℹ️ 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".
…ike Go in sso add/update (review: codex) - an undecodable 200 body from the reconciled GET aborts with Go's failed-to-get error before any PUT (update.go:42-45); a 200 without a JSON content type falls into Go's nil-JSON200 gate branch - the reconciled raw GET stitches identity through the shared per-command guard, like Go's identityTransport on every response - the upgrade-gate fallback GETs and the linked-project cache fill target the reconciled profile host (Go's CurrentProfile is process-wide)
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 22f27acf90
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4b9e88f1e1
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8cc1bcc75a
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c4d15a0045
ℹ️ 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".
…2-sso-add-mutual-exclusivity-error-is-not-cobra-format
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: fbc2bba60c
ℹ️ 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".
kanadgupta
left a comment
There was a problem hiding this comment.
One refactoring suggestion and one stale comment suggestion per Claude otherwise LGTM
…I-1982) The comment said "Keep this the very first check" but three enum/bool validations already precede the missing-value check. Reworded to describe what it actually precedes, matching update.handler.ts:264's "Keep this ahead of the arity check" phrasing.
…988) hasExplicitValueFlag was removed from cobra-flag-groups.ts (#5974), which broke gen types' mutex-flag detection after the develop merge. Migrate onto pflagArgvScan (the sso add/update pattern): a GEN_TYPES_SCAN_SPEC drives the scan, and its occurrences replace every flagChanged(...) call site. This also closes two gaps flagged on the PR: - The mutex scan is now short-flag aware (-s), and no longer ORs against the Effect-parsed boolean flags, which independently mark a flag changed even when pflag would have consumed its token as -s's value. - The postgrest-v9-compat PreRunE gate, the positional-lang guard, and the mutex-group checks now run inside the same Effect.ensuring(telemetryState.flush) block as the rest of the handler, matching Go's PersistentPreRunE-before-PreRunE ordering so a rejected invocation still flushes telemetry.
…LI-1990) (supabase#5978) Batch sweep of the small confirmed edge/cosmetic Go-parity divergences from the 2026-07-24 audit. Every item was re-verified against `apps/cli-go` at current develop before changing anything (audit line numbers were stale); several items turned out to be already fixed or in-flight in other PRs and are listed as such. Fixes CLI-1990 — https://linear.app/supabase/issue/CLI-1990/edgecosmetic-parity-sweep-from-the-2026-07-24-audit-batchable-tail ## Item-by-item | # | Item | Status | Notes | |---|------|--------|-------| | 1 | `functions delete` line colour | **Fixed** | Aqua slug + ref, stdout-gated (`delete.go:20`) | | 2 | `functions deploy` success ref Aqua, `Bundling Function:` bold, `No Functions specified…` bold | **Fixed** | `deploy.go:70,35`, `bundle.go:30`; stdout-gated where stdout-bound | | 3 | Prune bullets ` • <bold>` | **Already fixed** | by supabase#5947 (CLI-1974), commit `c4b45874` | | 4 | serve `supabase start is not running.` Aqua | **Deferred** | open PR supabase#5976 modifies the same `assertLocalDbRunning` hunk in `shared/functions/serve.ts`; one-liner to do after it merges | | 5 | `encryption update-root-key` Finished line + bogus comment | **Fixed** | Aqua'd; comment claimed a nonexistent "render Aqua as plain" convention | | 6 | start rollback missing `Stopping containers...` | **Fixed** | stderr, matching Go's `DockerRemoveAll` writer on the start-failure path (`start.go:77`) | | 7 | `--debug` `Pruned …` reports | **Fixed** | `Pruned containers:/volumes:/network:` (singular network) `[a b c]` on stderr; prune stdout now collected (also removes a latent unread-pipe hazard); `LegacyDebugFlag` threaded through stop/start/rollback | | 8 | Per-retry `Retrying after Ns: <image>` banner | **Fixed** | `4s`/`8s` per Go's `2<<(i+1)` schedule (`docker.go:314`); the failed attempt's error line is played by the already-teed `docker pull` stderr | | 9 | `inspect db blocking` backtick `blocking_statement` | **Fixed** | col 2 only; col 5 (`blocked_statement`) stays bare per Go's format string (`blocking.go:56`) | | 10 | `seed buckets` mutex bracket `[local linked]` | **Fixed** | cobra keeps registration order for the group list and sorts only the "were all set" list; corrected the misleading comment in `legacy-db-target-flags.ts` (storage's `[linked local]` stays correct) | | 11 | `snippets download` 4 UUID forms + lowercase URL | **Fixed** | faithful `uuid.Parse` port incl. the braced-form `s[1:]` quirk; canonical lowercase interpolated into the URL; Go's three error branches verbatim | | 12 | `storage cp --jobs` negative rejection | **Fixed** | pflag's exact uint error (`invalid argument "-1" for "-j, --jobs" flag: strconv.ParseUint: …`), before mutex validation and without telemetry; the documented `0 → 1` clamp stays (Go's 0 deadlocks) | | 13 | `postgres-config` value coercion + `%+v` floats | **Fixed** | exact `ParseBool` case set; int64-overflow → verbatim string; pretty table renders numbers with Go's float64 `%g` (`1000000` → `1e+06`) via hoisted `legacyGoFormatFloat` (also reused by `db query`) | | 14 | init template file modes | **Fixed** | 0644/0755 pinned; the gitignore *append*-branch write is deliberately left unpinned — mode only applies at creation, and supabase#5977 rewrites that exact line | | 15 | login fallback dir 0700→0755 | **Fixed** | Go pins the dir 0755 (`access_token.go:91`); the token file stays 0600, so no secret exposure | | 16 | `test new` 0644 | **Fixed** | + dir 0755, like Go's `utils.WriteFile` | | 17 | `inspect report` 0755/0644 | **Fixed** | | | 18 | bootstrap invalid-stored-token fast-fail | **Deferred** | not small: `resolveLegacyAccessToken` deliberately collapses invalid→`None` for many callers (sso, snippets, postgres-config, …); distinguishing invalid-vs-missing needs a shared-semantics change | | 19 | `migration new` Created line on stdin-copy failure | **Fixed** | mirrors Go's deferred `Println` (`new.go:24-28`); also stdout-gates the Bold path (CLI-1546 class) | | 20 | telemetry state-file recovery | **Fixed** | all-or-nothing decode like Go's `decodeState`; a corrupt file resets `enabled` to true and rotates identity, exactly like Go | | 21 | unlink/services ref-read error | **Fixed (services)** | unlink already matched Go; services now warns `failed to load project ref: …` on a read error and continues unlinked (TOCTOU NotFound stays silent, like Go's `ErrNotLinked` branch) | | 22 | `domains` CNAME dump byte codes | **Kept documented** | premise inaccurate: the non-reproducible part of Go's `%+v` is a runtime *pointer address* for `ValidationErrors`, not byte codes; TS's deterministic rendering is already documented in `domains.format.ts` | | 23 | sso `--domains=` explicit-empty | **Deferred** | `sso update` already matches Go (len-check drops it); the `add` fix touches `sso/add/add.handler.ts`, in-flight in open PR supabase#5974 | | 24 | `db dump --file ""` | **Fixed** | keys off `len > 0` like Go: empty means stdout, no file open, no `Dumped schema to …` line | | 25 | network-restrictions CIDR-before-ref ordering | **Deferred, kept documented** | direction is inverted vs the issue text: TS validates CIDR *before* ref, Go resolves ref first in `PersistentPreRunE`; aligning overlaps open PR supabase#5975 (incl. its integration test file). The `SIDE_EFFECTS.md` note frames this as intended based on an incomplete Go reading — worth revisiting after supabase#5975 | ## Known residuals (deliberate, documented in code) - `postgres-config` digits in `(2^53, 2^63)` still lose precision on the way in (`JSON.stringify` cannot emit exact int64 tokens); Go sends exact integers there. Values beyond int64 now match Go (string fallback). - Colour TTY gating: stderr-bound colour gates on stderr's TTY (per `legacy-colors.ts`/CLI-1546 convention), whereas Go's lipgloss gates everything on stdout. Deliberate, pre-existing convention; only observable when exactly one of stdout/stderr is a TTY. - Bun's `util.styleText` currently ignores `validateStream`/`NO_COLOR` (verified on Bun 1.3.x), so under Bun piped output still carries ANSI for *all* legacy colour sites — a pre-existing runtime gap that predates this PR and deserves its own issue. - The services warning's error suffix is Effect's error text, not Go's `*PathError` bytes — the `failed to load project ref: ` prefix is the parity-bearing part. - `--jobs abc`/`3.5` still surface Effect CLI's parser error rather than pflag's; this PR scopes to negatives (the only case `Flag.integer` accepts that Go rejects). ## Review notes Four-perspective review (architect / engineer / security / DX) run pre-PR; all approve. Engineer fuzz-verified `legacyGoFormatFloat` (23k values) and `legacyParseSnippetUuid` (~8k inputs) byte-identical to Go/google-uuid. Security signed off on the 0700→0755 fallback-dir change (token file unchanged at 0600, matches Go exactly). Remaining findings were the documented residuals above.
…onsumer (review: sso reconciliation ownership) Codex flagged that legacy-pflag-reconcile.ts/legacy-profile-load.ts have only two current consumers (sso add + update), which by AGENTS.md's hoist rule reads as "family root" tier, not shared/. The hoist is intentional: a human reviewer asked for exactly this in #5974's review, on the grounds that the pflag-vs-Effect-parser divergence is CLI-wide, not sso-specific. Recording that link in the source so future readers don't re-litigate it.
What changed
sso addemitted a hand-written mutual-exclusivity error (only one of --metadata-file or --metadata-url may be set) and detected the conflict viaOption.isSomeon parsed flag values. The Go CLI enforces this group via cobra'sMarkFlagsMutuallyExclusive("metadata-file", "metadata-url")(apps/cli-go/cmd/sso.go:164), whose error template is:sso updatewas already migrated to the sharedcobraMutuallyExclusiveErrorMessagehelper plus raw-argvpflag.Changed-semantics detection (CLI-1902);addwas never migrated. This PR mirrors update's pattern inadd.handler.ts:cobraMutuallyExclusiveErrorMessage(group in Go's registration order; the violating subset sorted, per cobra'svalidateExclusiveFlagGroups).hasExplicitValueFlagraw-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.ValidateFlagGroups-before-RunEprecedence.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.mdnow documents the cobra template andChangedsemantics.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:
sso addandsso 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.sso update.-tshorthand — documented limitation shared withsso update; pflag fails-t's enum validation before flag groups anyway.--domains=explicit-empty edge onadd(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