Skip to content

fix: pass appid through plan-check RPC so RBAC keys can upload#2282

Merged
riderx merged 7 commits into
mainfrom
fix/plan-check-passthrough-appid
May 19, 2026
Merged

fix: pass appid through plan-check RPC so RBAC keys can upload#2282
riderx merged 7 commits into
mainfrom
fix/plan-check-passthrough-appid

Conversation

@WcaleNieWolny
Copy link
Copy Markdown
Contributor

@WcaleNieWolny WcaleNieWolny commented May 18, 2026

Summary

  • Adds a 3-arg overload (appid parameter) to is_allowed_action_org_action and is_paying_and_good_plan_org_action, threading appid into check_min_rights.
  • Updates the CLI's checkPlanValidUpload to pass appid (it already received it but was discarding it).
  • Updates the generated Supabase types to reflect the new overload.

Bug

The CLI's checkPlanValidUpload calls is_allowed_action_org_action(orgid, ['storage']) without an app_id. The call chain reaches rbac_check_permission_direct with p_app_id = NULL. For an API key with limited_to_apps set (typical for RBAC-managed keys), the app-scope restriction block:

IF array_length(v_api_key.limited_to_apps, 1) > 0 THEN
  IF v_effective_app_id IS NULL OR NOT (v_effective_app_id = ANY(v_api_key.limited_to_apps)) THEN
    -- deny: RBAC_CHECK_PERM_APIKEY_APP_RESTRICT

…denies because array_length > 0 AND v_effective_app_id IS NULL. The CLI surfaces this RBAC denial as the misleading "Plan upgrade required for upload" error, even though the org's plan is perfectly healthy.

Safety invariant preserved

A key with limited_to_apps = [A] still cannot perform app-B operations: rbac_check_permission_direct still enforces limited_to_apps whenever an app_id is supplied. Org-scope reads now correctly thread the caller's app_id (when known) so the restriction has the context it needs.

Backward compatibility

Both is_allowed_action_org_action(orgid, actions) and is_paying_and_good_plan_org_action(orgid, actions) keep their existing 2-arg signatures. The new 3-arg overloads sit alongside them, so older deployed clients keep working unchanged.

Workaround for affected users on old CLI

Recreate the API key without limited_to_apps (scope by org only), or remove the app restriction on the existing key. This unblocks them until they upgrade.

Test plan

  • bun run cli:lint — clean
  • bun run cli:typecheck — clean
  • bun run cli:build — succeeds
  • bun run cli:test — 13/13 passing
  • Manual smoke test: upload a bundle with an RBAC-managed key that has limited_to_apps set to confirm the upload now succeeds
  • Verify the same RBAC key is still denied when calling for a different app (safety invariant)
  • Confirm a key with limited_to_apps = [A] is still denied if attempting to use it for app B's upload (app.upload_bundle path remains restricted)

Out of scope

Other call-sites of is_allowed_action_org_action / is_allowed_action_org (bandwidth, MAU, dashboard reads) may have the same trap. Worth a follow-up audit, but not bundled here to keep this PR surgical.

Summary by CodeRabbit

  • Bug Fixes

    • Clearer error handling and messaging when upload plan validation fails.
  • Improvements

    • Plan validation now respects app-specific checks for uploads and access, enforcing API keys limited to a specific app.
  • Tests

    • Added integration tests covering app-scoped plan checks and RBAC behavior.

Review Change Stack

The CLI's checkPlanValidUpload calls is_allowed_action_org_action
without app_id, so check_min_rights -> rbac_check_permission_direct
receives p_app_id = NULL. For an API key with limited_to_apps set
(typical for RBAC-managed keys), the app-scope restriction in
rbac_check_permission_direct denies the call because
array_length(limited_to_apps, 1) > 0 AND v_effective_app_id IS NULL.

The CLI surfaces this RBAC denial as "Plan upgrade required for
upload" even though the org's plan is healthy.

This change adds a 3-arg overload to both is_allowed_action_org_action
and is_paying_and_good_plan_org_action that accepts appid and threads
it through check_min_rights, then updates the CLI upload path to pass
appid when it has one. The existing 2-arg signatures are preserved so
older clients continue to work.

Reproduced via app@matsuri-tech.com / tech.matsuri.cleaning with an
RBAC-managed "codemagic" key (mode=NULL, limited_to_apps=[that app]).
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 18, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

The PR extends plan validation to accept an optional app-scope context. A new migration adds 3-argument overloads to is_paying_and_good_plan_org_action and is_allowed_action_org_action that thread appid through RBAC checks. The CLI's checkPlanValidUpload is updated to pass appId in the RPC call and explicitly handle failures.

Changes

Plan validation app-scope context

Layer / File(s) Summary
Database plan-check functions with appid propagation
supabase/migrations/20260518071442_plan_check_passthrough_appid.sql
Defines 3-argument overloads of is_paying_and_good_plan_org_action and is_allowed_action_org_action that thread appid into check_min_rights, return boolean based on usage/stripe status, and set ownership and execute grants for both functions.
Client RPC invocation with appid and error handling
cli/src/utils.ts
Client checkPlanValidUpload now passes optional appId alongside orgid and actions: ['storage'] in the RPC call, checks the result for errors, logs a formatted message, and throws on failure before continuing to plan validation logic.
Integration tests for appid passthrough
tests/plan-check-appid-passthrough.test.ts
Adds a Vitest integration test that provisions RBAC-limited API key, org, and apps; asserts 2-arg RPC denies storage, 3-arg RPC allows when appid matches, and 3-arg RPC denies when appid does not match.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Cap-go/capgo#2080: Both PRs change authorization logic around public.check_min_rights—the main PR adds appid passthrough so plan/RBAC checks call check_min_rights with appid, while the retrieved PR updates check_min_rights (and tests) to correctly apply RBAC v2 API key password-policy/2FA gates.
  • Cap-go/capgo#1967: Both PRs modify the same org plan status RPC (public.is_paying_and_good_plan_org_action) and its RBAC/SECURITY DEFINER execution pathway—main extends it with appid passthrough/overloads while the retrieved PR hardens access by restricting who can call it.
  • Cap-go/capgo#2061: Both adjust RBAC authorization logic to handle app identity through check_min_rights; related changes enforce app scoping for API-key contexts.

Poem

🐰 App IDs hop through the RBAC gates,
Plan checks now dance with app-scoped fates,
Error logs bloom when calls go wrong,
The CLI and database sing in song!
thump-thump goes the validation strong! 🐾

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: passing appid through plan-check RPC to fix RBAC key upload issues. It is specific, related to the primary change, and avoids vague terms.
Description check ✅ Passed The description provides comprehensive coverage of the change including a detailed summary, bug explanation, safety invariants, backward compatibility, test plan, and scope. It addresses the required template sections adequately.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/plan-check-passthrough-appid

Comment @coderabbitai help to get the list of available commands and usage tips.

@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq Bot commented May 18, 2026

Merging this PR will not alter performance

✅ 43 untouched benchmarks
⏩ 2 skipped benchmarks1


Comparing fix/plan-check-passthrough-appid (54a66e4) with main (107e6ed)

Open in CodSpeed

Footnotes

  1. 2 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cli/src/utils.ts (1)

846-855: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle RPC errors before treating this as a bad plan.

If this new RPC fails, validPlan is falsy and the user still gets “Plan upgrade required for upload”. That keeps permission/migration failures indistinguishable from actual billing failures.

🔧 Proposed fix
-  const { data: validPlan } = await supabase.rpc('is_allowed_action_org_action', { orgid: orgId, actions: ['storage'], appid: appId })
+  const { data: validPlan, error: validPlanError } = await supabase.rpc('is_allowed_action_org_action', {
+    orgid: orgId,
+    actions: ['storage'],
+    appid: appId,
+  })
+  if (validPlanError) {
+    const message = `Cannot validate upload plan: ${formatError(validPlanError)}`
+    log.error(message)
+    throw new Error(message)
+  }
   if (!validPlan) {

As per coding guidelines: "For user-visible error messages, format errors with formatError(...) instead of dumping raw exceptions when possible."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@cli/src/utils.ts` around lines 846 - 855, The RPC call to
supabase.rpc('is_allowed_action_org_action', ...) ignores RPC errors and treats
any falsy validPlan as a billing issue; change the destructuring to capture the
RPC error (e.g., { data: validPlan, error }) and handle it first: if error
exists log and throw the formatted error using formatError(error) so
permission/migration failures surface correctly, otherwise proceed to check if
!validPlan and keep the existing user-facing log.error/redirect behavior; update
references around the supabase.rpc call, validPlan, and the user-facing
log.error to reflect this flow.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@cli/src/types/supabase.types.ts`:
- Around line 3789-3804: The RPC overload for is_paying_and_good_plan_org_action
is out of sync with the DB change that added an appid variant (similar to
is_allowed_action_org_action); update the RPC typings to add the overload that
accepts Args { actions: Database["public"]["Enums"]["action_type"][], appid:
string | null, orgid: string } and Returns: boolean for
is_paying_and_good_plan_org_action (match the pattern used by
is_allowed_action_org_action), then regenerate the Supabase TypeScript schema by
running the project type generation command (bun types) so the file and DB
surface stay in sync.

In `@supabase/migrations/20260518071442_plan_check_passthrough_appid.sql`:
- Line 25: In the SECURITY DEFINER function in this migration
(plan_check_passthrough_appid.sql) fully qualify the PostgreSQL built-ins:
replace uses of current_setting and now with pg_catalog.current_setting and
pg_catalog.now respectively, and ensure the function sets an empty search_path;
update any call sites inside the function that reference current_setting or now
to use the pg_catalog-qualified names to comply with the repo rule and prevent
SQL injection.
- Around line 125-139: The migration currently REVOKEs ALL privileges for anon
on the new 3-argument overload of public.is_allowed_action_org_action("orgid"
uuid, "actions" public.action_type [], "appid" character varying), which
prevents CLI/API-key RPCs (that run as anon) from reaching the wrapper; restore
access by adding a GRANT EXECUTE ON FUNCTION
public.is_allowed_action_org_action("orgid" uuid, "actions" public.action_type
[], "appid" character varying) TO anon so the CLI path can call the overload
before its body runs.

---

Outside diff comments:
In `@cli/src/utils.ts`:
- Around line 846-855: The RPC call to
supabase.rpc('is_allowed_action_org_action', ...) ignores RPC errors and treats
any falsy validPlan as a billing issue; change the destructuring to capture the
RPC error (e.g., { data: validPlan, error }) and handle it first: if error
exists log and throw the formatted error using formatError(error) so
permission/migration failures surface correctly, otherwise proceed to check if
!validPlan and keep the existing user-facing log.error/redirect behavior; update
references around the supabase.rpc call, validPlan, and the user-facing
log.error to reflect this flow.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7f3f15fd-feb8-4ec9-ade0-c399cfc2abd3

📥 Commits

Reviewing files that changed from the base of the PR and between 58c8448 and 55765df.

📒 Files selected for processing (3)
  • cli/src/types/supabase.types.ts
  • cli/src/utils.ts
  • supabase/migrations/20260518071442_plan_check_passthrough_appid.sql

Comment thread cli/src/types/supabase.types.ts Outdated
result boolean;
has_credits boolean;
BEGIN
SELECT current_setting('role', true) INTO caller_role;
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.

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Fully qualify the pg_catalog calls in this SECURITY DEFINER function.

current_setting on Line 25 and now on Line 54 are still unqualified. This repo’s migration rule requires fully qualified references inside PostgreSQL functions.

🔧 Proposed fix
-  SELECT current_setting('role', true) INTO caller_role;
+  SELECT pg_catalog.current_setting('role', true) INTO caller_role;
...
-  SELECT (si.trial_at > now()) OR (si.status = 'succeeded' AND NOT (
+  SELECT (si.trial_at > pg_catalog.now()) OR (si.status = 'succeeded' AND NOT (

As per coding guidelines: "Every PostgreSQL function must set an empty search_path and use fully qualified names for all references to prevent SQL injection vulnerabilities."

Also applies to: 54-54

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@supabase/migrations/20260518071442_plan_check_passthrough_appid.sql` at line
25, In the SECURITY DEFINER function in this migration
(plan_check_passthrough_appid.sql) fully qualify the PostgreSQL built-ins:
replace uses of current_setting and now with pg_catalog.current_setting and
pg_catalog.now respectively, and ensure the function sets an empty search_path;
update any call sites inside the function that reference current_setting or now
to use the pg_catalog-qualified names to comply with the repo rule and prevent
SQL injection.

Comment thread supabase/migrations/20260518071442_plan_check_passthrough_appid.sql Outdated
Addresses CodeRabbit review feedback on the appid passthrough change:

1. GRANT EXECUTE ... TO anon on the new 3-arg is_allowed_action_org_action
   overload. The CLI authenticates per-call via the capgkey header and
   connects with the Supabase anon key, so PostgREST sets role = anon.
   Without this grant the upload path would 403 before the function body
   even runs. The existing 2-arg overload already grants to anon.

2. Capture and surface RPC errors in checkPlanValidUpload. Previously a
   permission/migration failure was indistinguishable from a real billing
   failure - both surfaced as "Plan upgrade required for upload". Now
   non-billing errors throw with formatError() so they can be diagnosed.

3. Mirror the appid overload in the supabase.types.ts entry for
   is_paying_and_good_plan_org_action to match the DB-level signature.
   Not called directly from the CLI, but keeps the types accurate.

Skipped: CodeRabbit also suggested pg_catalog-qualifying current_setting
and now(). No repo-wide rule for this; matches the existing
is_paying_and_good_plan_org_action style. With SET search_path = ''
the pg_catalog schema is still implicitly first in the resolution order.
@WcaleNieWolny
Copy link
Copy Markdown
Contributor Author

Triaged CodeRabbit's review and addressed in fc2af0feb:

# Comment Action Where
1 Outside-diff: checkPlanValidUpload ignores RPC error, treats falsy validPlan as bad plan ✅ Fixed — destructure error, throw with formatError() so permission/migration failures are distinguishable from billing failures cli/src/utils.ts
2 Types: companion overload for is_paying_and_good_plan_org_action missing ✅ Fixed — added the 3-arg overload union to mirror is_allowed_action_org_action cli/src/types/supabase.types.ts
3 Migration: REVOKE from anon blocks CLI which runs as anon ✅ Fixed — replaced the REVOKE with GRANT EXECUTE ... TO anon, matching the existing 2-arg overload's grants (see 20260427105151_harden_security_definer_execute_grants.sql). Without this the upload path would 403 before the function body runs. Good catch — would have shipped a broken fix. supabase/migrations/...passthrough_appid.sql
4 Migration: pg_catalog.current_setting / pg_catalog.now() qualification ⏭️ Skipped intentionally

On #4: there's no explicit repo rule for pg_catalog qualification, and the function I'm overloading (is_paying_and_good_plan_org_action from 20260427105817) uses bare current_setting('role', true) and now(). Matching the existing style preserves consistency with the function we're extending. Since the function declares SET search_path = '', pg_catalog is still implicitly first in the resolution order, so the unqualified calls always resolve to the built-ins regardless of session search_path. Happy to add the prefix as a follow-up if a maintainer wants the whole RPC chain hardened in one pass.

CI re-running on fc2af0feb.

Confirmed empirically by spinning up local supabase, applying the
migration, and running bunx supabase gen types typescript --local:
the generator does NOT emit the 3-arg overload for
is_allowed_action_org_action or is_paying_and_good_plan_org_action,
even though both overloads exist in the DB and PostgREST routes to
each correctly at runtime. (Curiously, is_allowed_capgkey - which has
the same overload shape - does get both variants emitted. Looks like
a gen-types limitation we cannot easily fix from the migration.)

Since the next auto-sync (chore(auto-sync): update supabase schema
and generated types) would just revert any manual overload edit, this
commit:

1. Restores cli/src/types/supabase.types.ts to match what the
   generator produces (no manual overloads).
2. Casts the 3-arg args object to `never` at the call site so
   TypeScript accepts it. The runtime call still routes to the 3-arg
   DB function via PostgREST.

This decouples the CLI from gen-types' overload-handling quirk and
keeps the file auto-sync-stable.
@WcaleNieWolny
Copy link
Copy Markdown
Contributor Author

Follow-up on types: I started a local Supabase, applied all migrations including the new one, and ran bunx supabase gen types typescript --local. Confirmed empirically that the generator does not emit the new 3-arg overload for either is_allowed_action_org_action or is_paying_and_good_plan_org_action, even though:

  • Both 3-arg functions exist in pg_proc (verified via \df inside the local DB).
  • PostgREST routes correctly to either overload depending on whether appid is in the request body (tested with curl against both shapes; both returned false for a bogus orgid, proving the function ran).
  • pg-meta's /pg/functions endpoint returns both overloads.
  • Function grants are identical to is_allowed_capgkey, which does get its overload emitted.

Looks like a supabase gen types quirk specific to certain overload shapes — I couldn't determine the trigger from the surface.

Since the repo's chore(auto-sync) job runs the same generator, any manual overload I add to supabase.types.ts will be reverted on the next sync. To avoid that fragility, in d2b554e3a I:

  1. Reverted the manual type overloads so cli/src/types/supabase.types.ts matches what the generator produces (no diff vs origin/main).
  2. Cast the 3-arg args to never at the single call site in cli/src/utils.ts, so TS accepts the extra appid while the runtime call still routes to the 3-arg DB function via PostgREST.

This keeps the build green regardless of what the auto-sync does next, and isolates the gen-types quirk to one well-commented line of code. The DB migration is unchanged — the 3-arg overload is the source of truth.

Lint / typecheck / build / tests all green locally.

Three assertions, all running against PostgREST as anon with a capgkey
header (the same path the CLI takes for uploads):

1. The 2-arg is_allowed_action_org_action call still denies when the
   key has limited_to_apps set and use_new_rbac is on for the org.
   This is the original bug repro - the CLI's checkPlanValidUpload
   called this variant and tripped the RBAC app-scope restriction.

2. The new 3-arg overload with a matching appid returns true. This is
   the fix - threading appid into check_min_rights gives RBAC the
   context it needs to satisfy the limited_to_apps check.

3. The 3-arg overload with a *non-matching* appid (different app in
   the same org) still denies. This guards the safety invariant: a
   key restricted to app A still cannot be used to authorize uploads
   for app B, regardless of org membership.

Test setup notes:
- The apikeys_force_server_key BEFORE trigger overrides whatever we
  pass in for `key` with a server-generated UUID. We read the actual
  plaintext back from INSERT ... RETURNING (which executes before the
  DEFERRABLE INITIALLY DEFERRED apikeys_strip_plain_key_for_hashed
  trigger runs at commit), so we hold the real key to send via the
  capgkey header.
- Two same-org apps prove that the rejection in test #3 comes from
  limited_to_apps, not from the cross-org guard in check_min_rights.

Verified the test actually fails when the migration is rolled back:
PostgREST returns PGRST202 ("Could not find the function
public.is_allowed_action_org_action(actions, appid, orgid)") for the
two 3-arg cases. With the migration applied, all three pass.
@WcaleNieWolny
Copy link
Copy Markdown
Contributor Author

Added a regression test in tests/plan-check-appid-passthrough.test.ts (commit f693c3e61). Three assertions, all running against PostgREST as anon with a capgkey header — the exact path the CLI takes:

  1. 2-arg call denies — original bug repro. Confirms is_allowed_action_org_action(orgid, ['storage']) returns false for an RBAC-managed key with limited_to_apps set, against an org with use_new_rbac = true.
  2. 3-arg call with matching appid allows — the fix. Confirms the appid passthrough lets RBAC's app-scope restriction find the right context.
  3. 3-arg call with non-matching appid still denies — safety invariant. Two same-org apps; the key is restricted to app A, the call asks for app B, still rejected. Proves the rejection comes from limited_to_apps, not from the cross-org check in check_min_rights.

Validation that the test is actually testing the fix

I rolled the migration back locally (dropped the 3-arg overload) and re-ran the test. PostgREST returned PGRST202: Could not find the function public.is_allowed_action_org_action(actions, appid, orgid) for both 3-arg cases — i.e., the test would catch a regression if the migration were ever reverted. With the migration applied, all 3 pass.

Test setup gotcha worth noting

The apikeys_force_server_key BEFORE trigger overrides whatever you insert for key with its own UUID. The plaintext is only readable from INSERT ... RETURNING (which runs before the DEFERRABLE INITIALLY DEFERRED apikeys_strip_plain_key_for_hashed trigger fires at commit). The test reads the real key back from the RETURNING row before sending it via the capgkey header.

Local: bun run supabase:with-env -- bunx vitest run tests/plan-check-appid-passthrough.test.ts → 3/3 passing in ~400ms.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
tests/plan-check-appid-passthrough.test.ts (1)

248-286: ⚡ Quick win

Use it.concurrent for all three test cases in this file.

Line 248, Line 261, and Line 273 use it(...); switch them to it.concurrent(...) to match the test parallelization rule for .test.ts files.

Suggested diff
-  it('denies the 2-arg call (regression of the original bug)', async () => {
+  it.concurrent('denies the 2-arg call (regression of the original bug)', async () => {
@@
-  it('allows the 3-arg call when appid matches limited_to_apps (the fix)', async () => {
+  it.concurrent('allows the 3-arg call when appid matches limited_to_apps (the fix)', async () => {
@@
-  it('still denies the 3-arg call when appid does not match limited_to_apps (safety invariant)', async () => {
+  it.concurrent('still denies the 3-arg call when appid does not match limited_to_apps (safety invariant)', async () => {

As per coding guidelines: tests/**/*.test.ts: “Design all tests for parallel execution across files; use it.concurrent() instead of it() to run tests in parallel within the same file for faster CI/CD”.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/plan-check-appid-passthrough.test.ts` around lines 248 - 286, Change
the three synchronous test declarations to run concurrently: replace it(...)
with it.concurrent(...) for the tests whose descriptions are "denies the 2-arg
call (regression of the original bug)", "allows the 3-arg call when appid
matches limited_to_apps (the fix)", and "still denies the 3-arg call when appid
does not match limited_to_apps (safety invariant)"; update each test declaration
in the file tests/plan-check-appid-passthrough.test.ts so the calls to
createCapgkeyClient(...) and subsequent rpc(...) assertions run under
it.concurrent to comply with the tests/**/*.test.ts parallelization guideline.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@tests/plan-check-appid-passthrough.test.ts`:
- Around line 248-286: Change the three synchronous test declarations to run
concurrently: replace it(...) with it.concurrent(...) for the tests whose
descriptions are "denies the 2-arg call (regression of the original bug)",
"allows the 3-arg call when appid matches limited_to_apps (the fix)", and "still
denies the 3-arg call when appid does not match limited_to_apps (safety
invariant)"; update each test declaration in the file
tests/plan-check-appid-passthrough.test.ts so the calls to
createCapgkeyClient(...) and subsequent rpc(...) assertions run under
it.concurrent to comply with the tests/**/*.test.ts parallelization guideline.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 99574c97-4871-4d6f-ae5b-1c7b8641976d

📥 Commits

Reviewing files that changed from the base of the PR and between d2b554e and f693c3e.

📒 Files selected for processing (1)
  • tests/plan-check-appid-passthrough.test.ts

Supabase generated types mark apps.id, apikeys.rbac_id, and
apikeys.key as nullable, so assigning their RETURNING values to
local string variables tripped vue-tsc in CI (TS2322). Adds explicit
null checks at each insert site - they double as documentation that
the test's invariants depend on those columns being populated, and
fail loudly with a clear message if a future schema change makes them
nullable in practice.
@sonarqubecloud
Copy link
Copy Markdown

@riderx riderx merged commit 59cc08e into main May 19, 2026
55 of 56 checks passed
@riderx riderx deleted the fix/plan-check-passthrough-appid branch May 19, 2026 08:07
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