Skip to content

fix: resolve design-audit regression hardening for merge#815

Closed
BigSimmo wants to merge 13 commits into
mainfrom
codex/main-merge-safe-final-20260718-resubmit
Closed

fix: resolve design-audit regression hardening for merge#815
BigSimmo wants to merge 13 commits into
mainfrom
codex/main-merge-safe-final-20260718-resubmit

Conversation

@BigSimmo

@BigSimmo BigSimmo commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Summary

  • Resolved the design-audit remediation branch rebase state by syncing with latest main and preserving the same functional fixes.
  • Affected surfaces: Therapy Compass and diagnostics/search surfaces, differential and favourites command flows, clinical notes route controls, visual evidence handling, route error handling, and related route/interaction test coverage.
  • Outcome: no functional regressions found in the touched changed files from local verification in this branch.

Verification

  • npm run typecheck
  • npm run lint
  • npm run test -- tests/site-map.test.ts tests/ui-accessibility.spec.ts tests/ui-tools.spec.ts tests/audit-navigation-auth-regressions.test.ts tests/rag-variant-early-exit.test.ts (3 files executed after final merge sync) ✅
  • UI verification not run: local browser gates were not executed in this branch re-sync cycle to avoid duplicate heavy UI runs; focused server-side/regression checks passed.
  • npm run verify:pr-local not run (would duplicate repository baseline gate).

Clinical Governance Preflight

  • Not required for this merge resubmission because this branch does not change ingestion, source governance, ranking, or clinical answer-generation logic.

Risk and rollout

  • Low risk: verification-focused merge sync commit only (ClinicalDashboard/route-error-boundary conflict-clean merges plus existing design-audit remediation).
  • Rollout plan: merge after green checks and monitor the Production UI check post-merge.

Summary by CodeRabbit

BigSimmo and others added 12 commits July 18, 2026 06:07
Restore dashboard H1 expectations to Clinical Guide, mock service-detail
registry records so 13YARN/City East load, drop forms assertions that
conflicted with the live Refine/pathway UI, restore mode-menu click
safety handlers, and correct the presentations redirect sitemap slug.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
…lback

Suite-wide reducedMotion collapses CSS transition duration, so the
phone dock duration assertion could not pass in Production UI. Prefer
whitespace-empty presentations `query` falling through to `q`. Drop the
Chromium no-preference override again now that the duration assert is gone.

Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@supabase

supabase Bot commented Jul 18, 2026

Copy link
Copy Markdown

Updates to Preview Branch (codex/main-merge-safe-final-20260718-resubmit) ↗︎

Deployments Status Updated
Database Sat, 18 Jul 2026 06:40:34 UTC
Services Sat, 18 Jul 2026 06:40:34 UTC
APIs Sat, 18 Jul 2026 06:40:34 UTC

Tasks are run on every commit but only new migration files are pushed.
Close and reopen this PR if you want to apply changes from existing seed or migration files.

Tasks Status Updated
Configurations Sat, 18 Jul 2026 06:40:35 UTC
Migrations Sat, 18 Jul 2026 06:40:38 UTC
Seeding ⏸️ Sat, 18 Jul 2026 06:40:27 UTC
Edge Functions ⏸️ Sat, 18 Jul 2026 06:40:27 UTC

❌ Branch Error • Sat, 18 Jul 2026 06:40:39 UTC

ERROR: Unsafe supabase_admin default privileges; migration blocked. (SQLSTATE 42501)
{"safe": false, "entries": ["function:PUBLIC:execute", "function:anon:execute", "function:authenticated:execute", "function:postgres:execute", "function:service_role:execute", "function:supabase_admin:execute", "sequence:anon:select", "sequence:anon:update", "sequence:anon:usage", "sequence:authenticated:select", "sequence:authenticated:update", "sequence:authenticated:usage", "sequence:postgres:select", "sequence:postgres:update", "sequence:postgres:usage", "sequence:service_role:select", "sequence:service_role:update", "sequence:service_role:usage", "sequence:supabase_admin:usage", "table:anon:delete", "table:anon:insert", "table:anon:maintain", "table:anon:references", "table:anon:select", "table:anon:trigger", "table:anon:truncate", "table:anon:update", "table:authenticated:delete", "table:authenticated:insert", "table:authenticated:maintain", "table:authenticated:references", "table:authenticated:select", "table:authenticated:trigger", "table:authenticated:truncate", "table:authenticated:update", "table:postgres:delete", "table:postgres:insert", "table:postgres:maintain", "table:postgres:references", "table:postgres:select", "table:postgres:trigger", "table:postgres:truncate", "table:postgres:update", "table:service_role:delete", "table:service_role:insert", "table:service_role:maintain", "table:service_role:references", "table:service_role:select", "table:service_role:trigger", "table:service_role:truncate", "table:service_role:update", "table:supabase_admin:delete", "table:supabase_admin:insert", "table:supabase_admin:maintain", "table:supabase_admin:references", "table:supabase_admin:select", "table:supabase_admin:trigger", "table:supabase_admin:truncate", "table:supabase_admin:update"], "role_exists": true, "schema_exists": true}
At statement: 3
do $$
declare
  v_status jsonb;
begin
  if not exists (select 1 from pg_catalog.pg_roles where rolname = 'supabase_admin') then
    raise notice 'role supabase_admin does not exist; default-privilege assertion is not applicable';
    return;
  end if;

  begin
    -- Local/Superuser-capable environments can assume the target role even
    -- when the migration role cannot use ALTER DEFAULT PRIVILEGES FOR ROLE
    -- directly. Hosted environments that cannot assume it fall through to the
    -- catalog assertion and block with operator instructions.
    execute 'set local role supabase_admin';
    -- Revokes must be global: per-schema ACLs cannot subtract privileges from
    -- built-in or previously granted global defaults.
    alter default privileges for role supabase_admin
      revoke all privileges on tables from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin in schema public
      revoke all privileges on tables from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin
      revoke all privileges on sequences from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin in schema public
      revoke all privileges on sequences from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin
      revoke execute on functions from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin in schema public
      revoke execute on functions from public, anon, authenticated, service_role;
    alter default privileges for role supabase_admin in schema public
      grant select, insert, update, delete on tables to service_role;
    alter default privileges for role supabase_admin in schema public
      grant usage, select on sequences to service_role;
    alter default privileges for role supabase_admin in schema public
      grant execute on functions to service_role;
    execute 'reset role';
  exception when insufficient_privilege then
    begin execute 'reset role'; exception when others then null; end;
    raise notice 'current role % cannot remediate supabase_admin default privileges; asserting the catalog postcondition', current_user;
  end;

  v_status := public.default_privileges_status('supabase_admin', 'public');
  if not coalesce((v_status->>'safe')::boolean, false) then
    raise exception using
      errcode = '42501',
      message = 'Unsafe supabase_admin default privileges; migration blocked.',
      detail = v_status::text,
      hint = E'Run these six statements as supabase_admin, then retry the migration:\n'
        'DO $remediate$ BEGIN ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin REVOKE ALL PRIVILEGES ON TABLES FROM PUBLIC, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL PRIVILEGES ON TABLES FROM PUBLIC, anon, authenticated, service_role; END $remediate$;\n'
        'DO $remediate$ BEGIN ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin REVOKE ALL PRIVILEGES ON SEQUENCES FROM PUBLIC, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE ALL PRIVILEGES ON SEQUENCES FROM PUBLIC, anon, authenticated, service_role; END $remediate$;\n'
        'DO $remediate$ BEGIN ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC, anon, authenticated, service_role; ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public REVOKE EXECUTE ON FUNCTIONS FROM PUBLIC, anon, authenticated, service_role; END $remediate$;\n'
        'ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT SELECT, INSERT, UPDATE, DELETE ON TABLES TO service_role;\n'
        'ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT USAGE, SELECT ON SEQUENCES TO service_role;\n'
        'ALTER DEFAULT PRIVILEGES FOR ROLE supabase_admin IN SCHEMA public GRANT EXECUTE ON FUNCTIONS TO service_role;';
  end if;
end;
$$

View logs for this Workflow Run ↗︎.
Learn more about Supabase for Git ↗︎.

@coderabbitai

coderabbitai Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR updates sitemap generation and documentation, GitHub Actions workflow discovery, RAG cancellation and enrichment paths, Supabase cleanup and query-correction functions, service navigation UI behavior, and associated regression tests and configuration.

Changes

Route and workflow discovery

Layer / File(s) Summary
Sitemap and workflow discovery
scripts/generate-site-map.ts, docs/site-map.md, scripts/check-github-action-pins.mjs, tests/site-map.test.ts
Public utility handlers are separated from API routes, redirects are rediscovered, sitemap sections are updated, and workflow pin checking handles missing directories and YAML files.
Documentation indexes
docs/codebase-index.md, docs/branch-review-ledger.md
Route/schema documentation and the review ledger receive updated entries.

UI and navigation

Layer / File(s) Summary
Navigation and service interface behavior
src/app/..., src/components/forms/..., src/components/services/..., tests/audit-*.test.ts, tests/ui-*.spec.ts
Query fallback handling, forms content, service selection panels, accessibility controls, mobile layout coverage, and related mocks/assertions are updated.

RAG and database

Layer / File(s) Summary
RAG cancellation and enrichment flow
src/lib/rag.ts, src/lib/rag-candidate-sources.ts, tests/rag-variant-early-exit.test.ts
Abort plumbing is simplified, retrieval APIs stop accepting external signals, and metadata/visual-evidence attachment uses direct asynchronous queries and fallback behavior.
RAG database correction and cleanup
supabase/migrations/*, supabase/schema.sql, supabase/drift-manifest.json
Registry cleanup triggers, title-word vocabulary storage, trigram indexes, query correction, permissions, and schema metadata are updated.
Regression and schema validation
tests/supabase-schema.test.ts
Migration fixtures and assertions validate cleanup, vocabulary synchronization, query-correction probes, index replacement, and ACL checks.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

Suggested labels: codex

Suggested reviewers: copilot, cursoragent

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description is too sparse and misses the required Summary, Verification, Risk, Clinical Governance, and Notes sections. Fill in the repository template with a Summary, verification checkboxes or reasons not run, Risk and rollout, Clinical Governance Preflight, and Notes.
Docstring Coverage ⚠️ Warning Docstring coverage is 73.91% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the PR’s main theme of merge hardening and regression fixes, though it is somewhat broad.
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.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/main-merge-safe-final-20260718-resubmit

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

@coderabbitai coderabbitai 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.

Actionable comments posted: 5

Caution

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

⚠️ Outside diff range comments (2)
scripts/generate-site-map.ts (1)

152-185: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Exclude route.tsx from route-handler discovery scripts/generate-site-map.ts:152-185 Next.js route handlers are route.ts|js only, so treating route.tsx as routable can add unsupported URLs like /icons/[variant] to the sitemap.

🤖 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 `@scripts/generate-site-map.ts` around lines 152 - 185, Update route-handler
discovery in discoverRoutes to collect only route.ts files, and adjust
fileToRoute validation for the non-page kind accordingly; keep page.tsx
discovery unchanged and ensure route.tsx is excluded from sitemap generation.

Source: Coding guidelines

src/lib/rag.ts (1)

2445-2527: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Thread args.signal through the retrieval stack

src/lib/rag.ts#L2445-L2527 should pass args.signal into fetchEnabledRagAliases and every candidate helper. src/lib/rag-candidate-sources.ts already aborts inside callVersionedRetrievalRpc, but searchTextChunkCandidates, searchDocumentLookupFastPath, searchTableFactCandidates, searchEmbeddingFieldCandidates, searchIndexUnitCandidates, and withMemoryBoostedCandidates don’t accept/forward a signal, so canceled searches still run the Supabase RPCs.

🤖 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 `@src/lib/rag.ts` around lines 2445 - 2527, Thread args.signal through the
retrieval stack: pass it to fetchEnabledRagAliases in searchChunksWithTelemetry
and to every candidate helper invocation, including searchTextChunkCandidates,
searchDocumentLookupFastPath, searchTableFactCandidates,
searchEmbeddingFieldCandidates, searchIndexUnitCandidates, and
withMemoryBoostedCandidates. Update these helper signatures and their
Supabase/RPC forwarding paths in src/lib/rag-candidate-sources.ts (including the
affected lines 185-207) so callVersionedRetrievalRpc receives the signal and
canceled searches abort promptly.
🤖 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 `@src/lib/rag.ts`:
- Line 2445: Thread args.signal through the retrieval flow: pass it to
fetchEnabledRagAliases at the call site, add signal parameters to
searchTextChunkCandidates, attachDocumentRankingMetadata, and
attachPageVisualEvidence, and propagate it into their underlying database/RPC
calls so cancellation stops active work rather than only being checked
afterward.

In `@supabase/migrations/20260717010000_harden_rag_scalability_patch.sql`:
- Around line 54-55: Update the tokenization before the foreach loop to match
clinical search boundaries: lowercase the input, split camelCase transitions,
and treat non-word delimiters such as hyphens as separators instead of only
splitting whitespace. Preserve the resulting token iteration used for
correction.
- Around line 63-94: Update the query’s caller and matching logic to accept
owner/public-scope parameters, then restrict rag_aliases and
document_title_words through joined documents to the caller’s accessible corpus
before similarity matching. Ensure both alias and canonical terms use the
rag_aliases scope filter, title words use the documents scope filter, and
preserve the existing similarity thresholds and ranking.

In `@tests/site-map.test.ts`:
- Around line 64-98: Strengthen the test around the expectedProductHandlers loop
so each handler is asserted directly within the public-utility section rather
than only excluded from apiSection and productSection. Reuse the
route/file/target values from expectedProductHandlers and verify the
corresponding entries appear in the section headed by the public-utility marker.

In `@tests/supabase-schema.test.ts`:
- Around line 1208-1214: Update the ACL assertions in the test containing
`default_privileges_status` to inspect only the migration segment returned by
the new segment helper, rather than the entire `sql` string. Apply this scoped
value to each `pg_catalog.acldefault`, `pg_catalog.aclexplode`, `bool_or`, and
ACL entry assertion while preserving the existing expected predicates.

---

Outside diff comments:
In `@scripts/generate-site-map.ts`:
- Around line 152-185: Update route-handler discovery in discoverRoutes to
collect only route.ts files, and adjust fileToRoute validation for the non-page
kind accordingly; keep page.tsx discovery unchanged and ensure route.tsx is
excluded from sitemap generation.

In `@src/lib/rag.ts`:
- Around line 2445-2527: Thread args.signal through the retrieval stack: pass it
to fetchEnabledRagAliases in searchChunksWithTelemetry and to every candidate
helper invocation, including searchTextChunkCandidates,
searchDocumentLookupFastPath, searchTableFactCandidates,
searchEmbeddingFieldCandidates, searchIndexUnitCandidates, and
withMemoryBoostedCandidates. Update these helper signatures and their
Supabase/RPC forwarding paths in src/lib/rag-candidate-sources.ts (including the
affected lines 185-207) so callVersionedRetrievalRpc receives the signal and
canceled searches abort promptly.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: a8f45492-4c34-4c20-a045-89087bb4dff0

📥 Commits

Reviewing files that changed from the base of the PR and between bf3c855 and df3e418.

📒 Files selected for processing (25)
  • docs/branch-review-ledger.md
  • docs/codebase-index.md
  • docs/site-map.md
  • scripts/check-github-action-pins.mjs
  • scripts/generate-site-map.ts
  • src/app/differentials/presentations/route.ts
  • src/app/layout.tsx
  • src/app/page.tsx
  • src/components/forms/forms-home-page.tsx
  • src/components/services/services-navigator-page.tsx
  • src/lib/rag-candidate-sources.ts
  • src/lib/rag.ts
  • supabase/drift-manifest.json
  • supabase/migrations/20260714180000_patch_rag_and_corrector_scalability.sql
  • supabase/migrations/20260714190000_document_table_facts_trgm_idx.sql
  • supabase/migrations/20260717010000_harden_rag_scalability_patch.sql
  • supabase/schema.sql
  • tests/audit-content-services-regressions.test.ts
  • tests/audit-navigation-auth-regressions.test.ts
  • tests/rag-variant-early-exit.test.ts
  • tests/site-map.test.ts
  • tests/supabase-schema.test.ts
  • tests/ui-smoke.spec.ts
  • tests/ui-tools.spec.ts
  • tsconfig.json

Comment thread src/lib/rag.ts
if (queryAnalysis.corpusGrounding) telemetry.corpus_grounding = queryAnalysis.corpusGrounding;

const ragAliases = await fetchEnabledRagAliases(supabase, args.ownerId, args.accessScope, args.signal);
const ragAliases = await fetchEnabledRagAliases(supabase, args.ownerId, args.accessScope);

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.

🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## File outline\n'
ast-grep outline src/lib/rag.ts --view expanded || true

printf '\n## Relevant line ranges\n'
sed -n '2400,2565p' src/lib/rag.ts | cat -n

printf '\n## Search for signal usage and related helpers\n'
rg -n "args\.signal|AbortSignal|fetchEnabledRagAliases|fetch.*RagAliases|retrieve.*signal|signal:" src/lib/rag.ts

Repository: BigSimmo/Database

Length of output: 18416


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## fetchEnabledRagAliases definition and call sites\n'
rg -n "function fetchEnabledRagAliases|const fetchEnabledRagAliases|export .*fetchEnabledRagAliases|fetchEnabledRagAliases\\(" src/lib -A 6 -B 6

printf '\n## searchTextChunkCandidates definition and signal threading\n'
rg -n "function searchTextChunkCandidates|const searchTextChunkCandidates|searchTextChunkCandidates\\(" src/lib -A 8 -B 8

printf '\n## attachDocumentRankingMetadata / attachPageVisualEvidence signal handling\n'
rg -n "function attachDocumentRankingMetadata|attachDocumentRankingMetadata\\(|function attachPageVisualEvidence|attachPageVisualEvidence\\(" src/lib -A 8 -B 8

printf '\n## helper signatures around AbortSignal in rag.ts\n'
sed -n '420,520p' src/lib/rag.ts | cat -n

Repository: BigSimmo/Database

Length of output: 20502


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n## fetchEnabledRagAliases implementation\n'
sed -n '116,180p' src/lib/rag-retrieval-variants.ts | cat -n

printf '\n## searchTextChunkCandidates implementation\n'
sed -n '185,310p' src/lib/rag-candidate-sources.ts | cat -n

printf '\n## attachDocumentRankingMetadata implementation\n'
sed -n '1543,1642p' src/lib/rag.ts | cat -n

printf '\n## attachPageVisualEvidence implementation\n'
sed -n '1645,1765p' src/lib/rag.ts | cat -n

Repository: BigSimmo/Database

Length of output: 20282


Thread args.signal through retrieval RPCs. fetchEnabledRagAliases already accepts a signal, but this call drops it, and searchTextChunkCandidates, attachDocumentRankingMetadata, and attachPageVisualEvidence don’t take one either. Cancellation still won’t stop the active DB work until the later abort check.

🤖 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 `@src/lib/rag.ts` at line 2445, Thread args.signal through the retrieval flow:
pass it to fetchEnabledRagAliases at the call site, add signal parameters to
searchTextChunkCandidates, attachDocumentRankingMetadata, and
attachPageVisualEvidence, and propagate it into their underlying database/RPC
calls so cancellation stops active work rather than only being checked
afterward.

Comment on lines +54 to +55
tokens := regexp_split_to_array(lower(input_query), '\s+');
foreach tok in array tokens loop

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Tokenize punctuation consistently with clinical search.

Whitespace splitting leaves inputs such as heart-faliure as one token, while src/lib/clinical-search.ts splits camelCase and non-word delimiters. Use equivalent token boundaries so correction works for punctuated clinical queries.

🤖 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/20260717010000_harden_rag_scalability_patch.sql` around
lines 54 - 55, Update the tokenization before the foreach loop to match clinical
search boundaries: lowercase the input, split camelCase transitions, and treat
non-word delimiters such as hyphens as separators instead of only splitting
whitespace. Preserve the resulting token iteration used for correction.

Comment on lines +63 to +94
select candidate.term, similarity(candidate.term, tok)
into best, best_sim
from (
(
select lower(alias) as term
from public.rag_aliases
where enabled
and length(alias) between 4 and 40
and lower(alias) % tok
order by similarity(lower(alias), tok) desc, lower(alias)
limit 32
)
union all
(
select lower(canonical) as term
from public.rag_aliases
where enabled
and length(canonical) between 4 and 40
and lower(canonical) % tok
order by similarity(lower(canonical), tok) desc, lower(canonical)
limit 32
)
union all
(
select word as term
from public.document_title_words
where length(word) between 4 and 40
and word % tok
order by similarity(word, tok) desc, word
limit 32
)
) candidate

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.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Scope correction vocabulary to the caller’s accessible corpus.

This query considers aliases and title words from every tenant, while callers pass only input_query and min_sim. Private terminology can therefore rewrite another tenant’s query. Add owner/public-scope parameters and filter both rag_aliases and joined documents before similarity matching.

🤖 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/20260717010000_harden_rag_scalability_patch.sql` around
lines 63 - 94, Update the query’s caller and matching logic to accept
owner/public-scope parameters, then restrict rag_aliases and
document_title_words through joined documents to the caller’s accessible corpus
before similarity matching. Ensure both alias and canonical terms use the
rag_aliases scope filter, title words use the documents scope filter, and
preserve the existing similarity thresholds and ranking.

Comment thread tests/site-map.test.ts
Comment on lines +64 to +98
it("keeps public redirect handlers in product routes and API handlers in the API section", () => {
const data = collectSiteMapData();
const productSection = siteMap.slice(
siteMap.indexOf("## Main product routes"),
siteMap.indexOf("## Mode/query routes"),
);
const apiSection = siteMap.slice(siteMap.indexOf("## API routes"), siteMap.indexOf("## Redirects"));
const expectedProductHandlers = [
["/applications", "src/app/applications/route.ts", "/tools"],
[
"/differentials/presentations",
"src/app/differentials/presentations/route.ts",
"/differentials/presentations/[slug]",
],
["/medications", "src/app/medications/route.ts", "/?mode=prescribing"],
] as const;
const redirectSection = siteMap.slice(siteMap.indexOf("## Redirects"));

expect(data.apiRoutes.every((route) => route.route === "/api" || route.route.startsWith("/api/"))).toBe(true);
expect(data.publicRouteHandlers.some((route) => route.route === "/auth/callback")).toBe(true);
expect(data.publicRouteHandlers).toContainEqual({
route: "/icons/[variant]",
file: "src/app/icons/[variant]/route.tsx",
});
expect(apiSection).not.toContain("`/icons/[variant]`");

for (const [route, file, target] of expectedProductHandlers) {
expect(data.publicRouteHandlers).toContainEqual({ route, file });
expect(data.apiRoutes).not.toContainEqual({ route, file });
expect(data.redirects).toContainEqual({ route, file, target });
expect(redirectSection).toContain(`\`${route}\``);
expect(apiSection).not.toContain(`\`${route}\``);
expect(productSection).not.toContain(`\`${route}\``);
}
});

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.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Assert the new public-utility section directly.

The test only proves these handlers appear somewhere outside the API section. Both could move into another section while the test still passes.

Proposed regression assertion
+    const publicUtilitySection = siteMap.slice(
+      siteMap.indexOf("## Public utility route handlers"),
+      siteMap.indexOf("## API routes"),
+    );
     const apiSection = siteMap.slice(siteMap.indexOf("## API routes"), siteMap.indexOf("## Redirects"));
...
+    expect(publicUtilitySection).toContain("`/auth/callback`");
+    expect(publicUtilitySection).toContain("`/icons/[variant]`");
     expect(apiSection).not.toContain("`/icons/[variant]`");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
it("keeps public redirect handlers in product routes and API handlers in the API section", () => {
const data = collectSiteMapData();
const productSection = siteMap.slice(
siteMap.indexOf("## Main product routes"),
siteMap.indexOf("## Mode/query routes"),
);
const apiSection = siteMap.slice(siteMap.indexOf("## API routes"), siteMap.indexOf("## Redirects"));
const expectedProductHandlers = [
["/applications", "src/app/applications/route.ts", "/tools"],
[
"/differentials/presentations",
"src/app/differentials/presentations/route.ts",
"/differentials/presentations/[slug]",
],
["/medications", "src/app/medications/route.ts", "/?mode=prescribing"],
] as const;
const redirectSection = siteMap.slice(siteMap.indexOf("## Redirects"));
expect(data.apiRoutes.every((route) => route.route === "/api" || route.route.startsWith("/api/"))).toBe(true);
expect(data.publicRouteHandlers.some((route) => route.route === "/auth/callback")).toBe(true);
expect(data.publicRouteHandlers).toContainEqual({
route: "/icons/[variant]",
file: "src/app/icons/[variant]/route.tsx",
});
expect(apiSection).not.toContain("`/icons/[variant]`");
for (const [route, file, target] of expectedProductHandlers) {
expect(data.publicRouteHandlers).toContainEqual({ route, file });
expect(data.apiRoutes).not.toContainEqual({ route, file });
expect(data.redirects).toContainEqual({ route, file, target });
expect(redirectSection).toContain(`\`${route}\``);
expect(apiSection).not.toContain(`\`${route}\``);
expect(productSection).not.toContain(`\`${route}\``);
}
});
it("keeps public redirect handlers in product routes and API handlers in the API section", () => {
const data = collectSiteMapData();
const productSection = siteMap.slice(
siteMap.indexOf("## Main product routes"),
siteMap.indexOf("## Mode/query routes"),
);
const publicUtilitySection = siteMap.slice(
siteMap.indexOf("## Public utility route handlers"),
siteMap.indexOf("## API routes"),
);
const apiSection = siteMap.slice(siteMap.indexOf("## API routes"), siteMap.indexOf("## Redirects"));
const expectedProductHandlers = [
["/applications", "src/app/applications/route.ts", "/tools"],
[
"/differentials/presentations",
"src/app/differentials/presentations/route.ts",
"/differentials/presentations/[slug]",
],
["/medications", "src/app/medications/route.ts", "/?mode=prescribing"],
] as const;
const redirectSection = siteMap.slice(siteMap.indexOf("## Redirects"));
expect(data.apiRoutes.every((route) => route.route === "/api" || route.route.startsWith("/api/"))).toBe(true);
expect(data.publicRouteHandlers.some((route) => route.route === "/auth/callback")).toBe(true);
expect(data.publicRouteHandlers).toContainEqual({
route: "/icons/[variant]",
file: "src/app/icons/[variant]/route.tsx",
});
expect(publicUtilitySection).toContain("`/auth/callback`");
expect(publicUtilitySection).toContain("`/icons/[variant]`");
expect(apiSection).not.toContain("`/icons/[variant]`");
for (const [route, file, target] of expectedProductHandlers) {
expect(data.publicRouteHandlers).toContainEqual({ route, file });
expect(data.apiRoutes).not.toContainEqual({ route, file });
expect(data.redirects).toContainEqual({ route, file, target });
expect(redirectSection).toContain(`\`${route}\``);
expect(apiSection).not.toContain(`\`${route}\``);
expect(productSection).not.toContain(`\`${route}\``);
}
});
🤖 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/site-map.test.ts` around lines 64 - 98, Strengthen the test around the
expectedProductHandlers loop so each handler is asserted directly within the
public-utility section rather than only excluded from apiSection and
productSection. Reuse the route/file/target values from expectedProductHandlers
and verify the corresponding entries appear in the section headed by the
public-utility marker.

Comment on lines +1208 to +1214
expect(sql).toContain("create or replace function public.default_privileges_status(");
expect(sql).toContain("pg_catalog.acldefault(ot.object_code, v_role_oid)");
expect(sql).toContain("pg_catalog.aclexplode(ea.acl)");
expect(sql).toContain("bool_or(grantee not in (p_role_name, 'postgres', 'service_role'))");
expect(sql).toContain("entry like 'table:PUBLIC:%'");
expect(sql).toContain("entry like 'sequence:PUBLIC:%'");
expect(sql).toContain("entry = 'function:PUBLIC:execute'");

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.

🔒 Security & Privacy | 🟡 Minor | ⚡ Quick win

Keep ACL assertions scoped to default_privileges_status.

Searching the whole migration can pass when these security predicates occur in comments or another function. Use the new segment helper to preserve the fail-closed guarantee.

Proposed fix
+      const statusFunction = finalSqlSegment(
+        sql,
+        "create or replace function public.default_privileges_status(",
+        "revoke execute on function public.default_privileges_status",
+      );
-      expect(sql).toContain("pg_catalog.acldefault(ot.object_code, v_role_oid)");
-      expect(sql).toContain("pg_catalog.aclexplode(ea.acl)");
+      expect(statusFunction).toContain("pg_catalog.acldefault(ot.object_code, v_role_oid)");
+      expect(statusFunction).toContain("pg_catalog.aclexplode(ea.acl)");
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
expect(sql).toContain("create or replace function public.default_privileges_status(");
expect(sql).toContain("pg_catalog.acldefault(ot.object_code, v_role_oid)");
expect(sql).toContain("pg_catalog.aclexplode(ea.acl)");
expect(sql).toContain("bool_or(grantee not in (p_role_name, 'postgres', 'service_role'))");
expect(sql).toContain("entry like 'table:PUBLIC:%'");
expect(sql).toContain("entry like 'sequence:PUBLIC:%'");
expect(sql).toContain("entry = 'function:PUBLIC:execute'");
const statusFunction = finalSqlSegment(
sql,
"create or replace function public.default_privileges_status(",
"revoke execute on function public.default_privileges_status",
);
expect(sql).toContain("create or replace function public.default_privileges_status(");
expect(statusFunction).toContain("pg_catalog.acldefault(ot.object_code, v_role_oid)");
expect(statusFunction).toContain("pg_catalog.aclexplode(ea.acl)");
expect(sql).toContain("bool_or(grantee not in (p_role_name, 'postgres', 'service_role'))");
expect(sql).toContain("entry like 'table:PUBLIC:%'");
expect(sql).toContain("entry like 'sequence:PUBLIC:%'");
expect(sql).toContain("entry = 'function:PUBLIC:execute'");
🤖 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/supabase-schema.test.ts` around lines 1208 - 1214, Update the ACL
assertions in the test containing `default_privileges_status` to inspect only
the migration segment returned by the new segment helper, rather than the entire
`sql` string. Apply this scoped value to each `pg_catalog.acldefault`,
`pg_catalog.aclexplode`, `bool_or`, and ACL entry assertion while preserving the
existing expected predicates.

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