Skip to content

feat(cli): experimental compute - add secrets scope field - #7531

Open
kallebysantos wants to merge 32 commits into
developfrom
ks/feat-compute-add-secrets-scope
Open

kallebysantos wants to merge 32 commits into
developfrom
ks/feat-compute-add-secrets-scope

Conversation

@kallebysantos

@kallebysantos kallebysantos commented Nov 7, 2026 •

Copy link
Copy Markdown
Member

Towards FUNC-954

@kallebysantos
kallebysantos force-pushed the ks/feat-compute-add-secrets-scope branch from e66cc7f to f2c631c Compare November 9, 2026 12:59
@kallebysantos
kallebysantos marked this pull request as ready for review November 9, 2026 14:28
@kallebysantos
kallebysantos requested a review from a team as a code owner November 9, 2026 14:28
@kallebysantos kallebysantos changed the title feat(compute): add secrets scope feat(cli): experimental compute - add secrets scope field Nov 9, 2026
@github-actions

github-actions Bot commented Nov 9, 2026

Copy link
Copy Markdown
Contributor

CLI benchmark (Lightweight Commands): no changes found

Commit 7aaa831 against develop at d4fc0e5 · 10 runs each · report only, never blocks merging

Command Workload Before After Change
supabase --version version 446 ms 476 ms no real change (+7%, within normal variation)
supabase --help help 338 ms 332 ms no real change
supabase init init 237 ms 247 ms no real change
supabase migration new bench migration-new 281 ms 260 ms no real change (-7%, within normal variation)
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 409 ms 384 ms no real change (-6%, within normal variation)
supabase projects list projects-list 320 ms 318 ms no real change
supabase functions list --project-ref replayfixtureprojref functions-list 359 ms 349 ms no real change

API calls: unchanged for all 7 commands.

Binary size: 134.9 MB, up 12.0 KB from 134.9 MB.

Details: timing ranges, API calls per command, slowest phases

Timing ranges

Command Workload Before range After range Change Verdict
supabase --version version 366-601 ms 420-766 ms +31 ms (+7%) within noise
supabase --help help 295-369 ms 286-420 ms -6 ms (-2%) within noise
supabase init init 204-274 ms 218-289 ms +10 ms (+4%) within noise
supabase migration new bench migration-new 268-309 ms 229-433 ms -21 ms (-7%) within noise
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 328-481 ms 323-513 ms -24 ms (-6%) within noise
supabase projects list projects-list 275-337 ms 294-367 ms -2 ms (-1%) within noise
supabase functions list --project-ref replayfixtureprojref functions-list 285-511 ms 310-376 ms -10 ms (-3%) within noise

API calls per command

Command Workload Before After Endpoint changes
supabase --version version 0 0
supabase --help help 0 0
supabase init init 0 0
supabase migration new bench migration-new 0 0
supabase gen types --lang typescript --project-id replayfixtureprojref gen-types 2 2
supabase projects list projects-list 1 1
supabase functions list --project-ref replayfixtureprojref functions-list 2 2

Slowest phases

No command moved beyond noise, so there are no phase deltas.

Workflow run

Comment /bench to run the lightweight benchmark (this comment) again on the latest commit, or /bench full to also run the integration-heavy benchmark, which posts in its own comment.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI Review

Reconciled all 13 Claude and 6 Codex findings into 13 entries. Confirmed incomplete flag metadata, blank custom secret names, missing override warnings, incorrect error classification, stale documentation, and cleanup issues. Refuted the malformed-config exposure claim, the schema-enum requirement, and the redundant-test allegation. Verification was static; dependencies were unavailable for executing checks.

Findings

Severity Location Category Sources Claim
🟡 MINOR apps/cli/src/shared/compute/compute-runtimes.ts:169 input-validation claude+codex Custom scope parsing accepts blank secret names and carries them into configuration and deployment requests.
🟡 MINOR apps/cli/src/commands/experimental/compute/push/push.command.ts:51 flag-registration claude+codex The new value-consuming --secrets-scope:custom spelling is missing from shared argv metadata and both commands' permission declarations.
🟡 MINOR apps/cli/src/commands/experimental/compute/push/push.handler.ts:218 error-handling claude An invalid recorded secrets scope is reported as UnknownComputeRuntimeError, giving it an unrelated JSON error tag and telemetry fingerprint.
🟡 MINOR apps/cli/src/commands/experimental/compute/push/push.handler.ts:203 consistency claude A restrictive secrets-scope override applies silently to one deploy, and a subsequent bare push returns to the recorded scope or all without the warning provided for exposure overrides.
🟡 MINOR apps/cli/src/commands/experimental/compute/push/SIDE_EFFECTS.md:23 documentation claude Both command side-effect contracts omit the newly read, prompted, persisted, and deployed secrets_scope behavior.
⚪ NIT apps/cli/src/shared/compute/compute-api.ts:89 duplication claude The built-in secrets-scope literals are duplicated, and the API converter unnecessarily revalidates already resolved values with a possible undefined result.
⚪ NIT apps/cli/src/commands/experimental/compute/push/push.handler.ts:465 formatting claude The added code and unrelated reindentation do not follow the repository's formatter style.
⚪ NIT apps/cli/src/commands/experimental/compute/push/push.integration.test.ts:40 unused-import claude+codex The new SupabaseApiInputError import is unused; the added tests also contain missing semicolons and misspelled override descriptions.
⚪ NIT apps/cli/src/commands/experimental/compute/new/new.integration.test.ts:359 misleading-comment claude+codex The copied test comment incorrectly says secrets scope has no prompt and is omitted when unspecified; nearby comments and JSDoc are incomplete.
⚪ NIT packages/config/src/compute.ts:50 copy claude+codex The public schema description and prompt hint contain the grammatical error complete hide, with additional inconsistent prompt punctuation.

Findings outside the diff

  • 🟡 MINOR apps/cli/src/commands/experimental/compute/push/SIDE_EFFECTS.md:23 — Both command side-effect contracts omit the newly read, prompted, persisted, and deployed secrets_scope behavior.
Refuted findings (kept for transparency, not posted as review comments)
  • apps/cli/src/shared/compute/compute-config.ts:145 (security): Malformed secrets_scope values silently become undefined and cause push to expose all secrets.
    Refuted: The production path validates configuration before this reader runs. cli-config-values.layer.ts:550-583 decodes the declared and materialized documents; packages/config/src/io.ts:280-299 calls validateCliConfig, whose validate.ts:6,20 uses Schema.decodeUnknownEffect(CliConfigSchema). Numbers, mixed arrays, and tables fail that schema. push.handler.ts:617 propagates the load failure rather than deploying with defaults.
  • packages/config/src/compute.ts:47 (config-schema): The secrets_scope schema should use literal enums, as exposure and size do, to reject values such as meow and ALL with trailing whitespace.
    Refuted: The claimed comparison is contradicted by both the checked-out code and trusted/packages/config/src/compute.ts:22-35: size and exposure are unconstrained strings. Scope validation occurs in push.handler.ts:216-221, rejecting meow before deployment, while compute-runtimes.ts:164-166 intentionally normalizes casing and whitespace, making ALL with trailing whitespace valid. The genuine wording typo is preserved in claude-13.
  • apps/cli/src/commands/experimental/compute/new/new.integration.test.ts:346 (test-quality): The default-scope persistence test duplicates the existing full-configuration assertion and should be removed.
    Refuted: These tests exercise different resolution paths. setupCompute at tests/helpers/compute.ts:506-523 makes text setup interactive and JSON setup noninteractive. new.handler.ts:221-245 selects through a prompt in the first case but returns the default without prompting in the second. The shared expected value does not make those paths redundant.

Stats

Claude findings: 13 · Codex findings: 6 · Confirmed: 10 · Refuted: 3 · Uncertain: 0


Models: claude-opus-5-5 + gpt-6.1-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment on lines +169 to +174
export function parseSecretsScopeCustom(secretsNames: string) {
if (typeof secretsNames !== 'string') {
return []
}

return secretsNames.split(',').map(secretName => secretName.trim())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MINOR · input-validation · source: claude+codex

Custom scope parsing accepts blank secret names and carries them into configuration and deployment requests.

Evidence: compute-runtimes.ts:174 splits and trims without rejecting empty elements; lines 155-166 accept every string array. new.handler.ts:235-242 supplies no prompt validator, and compute-api.ts:108-109 maps blank elements to {secret_name: ""}.

Suggested fix: Validate custom input in both flag parsing and the prompt, rejecting blank names and explaining how to select none.

Comment on lines +51 to +59
secretsScope: Flag.orElse(
Flag.Literals("secrets-scope", COMPUTE_SECRETS_SCOPE),
() => Flag.String("secrets-scope:custom").pipe(Flag.map(parseSecretsScopeCustom), Flag.withMetavar("SECRET_NAMES")))
.pipe(
Flag.withDescription(
"Controls whether secrets are available, overriding `secrets_scope` in the project config file for this deploy. Falls back to the recorded value, then all.",
),
Flag.optional,
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MINOR · flag-registration · source: claude+codex

The new value-consuming --secrets-scope:custom spelling is missing from shared argv metadata and both commands' permission declarations.

Evidence: push.command.ts:53 and new.command.ts:50 declare the custom flag. value-consuming-flags.ts:77 registers only secrets-scope; push.command.ts:110 and new.command.ts:121 also list only secrets-scope. value-consuming-flags.unit.test.ts:66 excludes colons from its name regex.

Suggested fix: Register the custom spelling in the value-consuming set and both permission declarations, widen the coverage regex, and verify both alternatives through the real parser and introspection helpers.

Comment on lines +89 to +111
const COMPUTE_SECRETS_SCOPE = ["all", "supabase", "none"] as const;
type ComputeSecretsScope = (typeof COMPUTE_SECRETS_SCOPE)[number];

/** The `spec` a deploy sends. Mirrors the API's own field names exactly. */
export interface ComputeDeploySpec {
readonly runtime?: string;
readonly size: string;
readonly exposure: string;
readonly secrets_scope?: ComputeSecretsScope | {
readonly secret_name: string;
}[];
readonly instances: number;
}

export function parseComputeSecretsScopeToAPIFormat(value: string | string[]): ComputeDeploySpec['secrets_scope'] | undefined {
if (typeof value === 'string' && COMPUTE_SECRETS_SCOPE.includes(value as ComputeSecretsScope)) {
return value as ComputeSecretsScope;
}

if (Array.isArray(value) && value.every(i => typeof i === 'string')) {
return value.map((secret_name) => ({ secret_name }))
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚪ NIT · duplication · source: claude

The built-in secrets-scope literals are duplicated, and the API converter unnecessarily revalidates already resolved values with a possible undefined result.

Evidence: compute-api.ts:89-90 duplicates compute-runtimes.ts:135. Its converter at lines 103-111 accepts broad strings and can fall through, while push.handler.ts:364-369 resolves a ComputeSecretsScope before calling it at line 441.

Suggested fix: Share the built-in literals and make the converter total over the resolved scope type, preserving the distinct API representation for custom names.

Comment on lines +465 to +472
schedule: input.pollSchedule,
retrySchedule: input.pollRetrySchedule,
refSuffix: input.refSuffix,
onPoll: (polled) =>
polled.buildState === "building"
? deploying.message("Building compute...")
: Effect.void,
}).pipe(Effect.tapError(() => deploying.fail()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚪ NIT · formatting · source: claude

The added code and unrelated reindentation do not follow the repository's formatter style.

Evidence: push.handler.ts:214,369 omits semicolons and lines 465-472 change continuation indentation. compute-api.ts:103-109 and compute-runtimes.ts:155-178 introduce single quotes and missing semicolons. Similar reindentation appears in new.handler.ts:338-351 and new.integration.test.ts:937-938.

Suggested fix: Run the root fmt:fix script and retain only intentional changes.

Comment thread packages/config/src/compute.ts Resolved

@7ttp 7ttp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

was having a look at it, and stumbled upon couple of things that could be improved

leaving them in-line:

Comment on lines +530 to +533
const settledSecretsScope =
typeof settled.spec.secrets_scope === "string"
? (settled.spec.secrets_scope as string)
: settled.spec.secrets_scope?.map(({ secret_name }) => secret_name);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

nit: this only lives in the text branch, so push -o json has exposure but no secrets_scope, while new -o json has both.
could hoist it above the if and spread it into the returned payload, like url? 🤔

"Which secrets should be available for this compute?",
defaultFirst(
[...COMPUTE_SECRETS_SCOPE_ENUM],
DEFAULT_COMPUTE_SECRETS_SCOPE as ComputeSecretsScopeEnum,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

maybe for later: a few new as casts (here, L237, push.handler L217, L238 and L532, compute-api L108-L109).
typing ComputeSecretsScope with ReadonlyArray<string> and the default as the literal "all" should let all of them go.

Comment thread packages/config/src/compute.ts Resolved

@jgoux jgoux left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A few issues to fix before merge; the first one fails the unit suite.

@kallebysantos
kallebysantos force-pushed the ks/feat-compute-add-secrets-scope branch from 2809b88 to 361fc79 Compare November 10, 2026 21:23

This branch has not been deployed

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants