Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/branch-review-ledger.md
Original file line number Diff line number Diff line change
Expand Up @@ -964,6 +964,8 @@ This file is append-only. Never rewrite or delete an existing review record; app
| 2026-07-25 | PR #1190 / `remediate-dark-mode-audit` | `00eca49b9b0d7e5fbfa5703a15e9e930963984a6` | Cursor review+Bugbot+prlanded+debug (fresh pass, same HEAD) | DO NOT MERGE; NOT LANDED (OPEN, mergeable=CONFLICTING/DIRTY, 468 behind / 2 ahead). Reconfirmed P0: conflict resolution deleted `trustGatedAnswerForClinicalNotes` (0 hits on head; main L584/632/659/1075) — Clinical Notes consumes ungated answer. P1: `src/app/api/answer/route.ts:6` imports nonexistent `@/lib/rag` (tsc TS2307; stream correctly uses `@/lib/rag/rag`). P1: merge-tree conflicts on answer/upload/evidence-panels + 10 paths; literal `<<<<<<<` in docs audit plan; migration timestamp collision risk vs main. Intentional dark-mode delta is only commit `363672602` (~10 files). Salvage: `cursor/pr1190-dark-mode-salvage-f453` cherry-picks that commit onto current main, restores unused-manifest-import cleanup, keeps clinical gate. Close #1190 after salvage lands. | Bugbot; `git grep` gate/import/markers; merge-tree; `tsc` TS2307 proof; gh pr view/checks (PR policy fail). Salvage: tsc clean; visual-evidence+overlay tests 13/13; eslint on changed files. No provider/UI matrix. |
| 2026-07-25 | execute-audit-remediation-plan (PR #1188) | 8b8639113925601e1687bfe4f1f29c44a4308b61 | Bugbot/diff-review: maintainability remediation tip | BLOCK: tip tree carries unresolved conflict markers (answer/upload APIs, clinical-dashboard, services, tests); invalid `async export function sha256Hex` in indexing-v3 utils; ClinicalDashboard still calls removed `renderSystemNotice`; merge-tree vs main conflicts in check-github-action-pins.mjs + ui-primitives.tsx. Intended notices extraction/dynamic imports look mostly sound; search-scope/migration not in three-dot product delta. | `git grep` conflict markers on tip (none on origin/main); `git show` for ClinicalDashboard:3824 + utils.ts:191; `git merge-tree --write-tree origin/main 8b8639113`; no provider-backed checks. |
| 2026-07-25 | PR #1209 / `cursor/pr1186-audit-remediation-c94c` | `4cb22e45dfe46b1975fa15ddd028c7e14ceb5fab` | Close #1186 + babysit #1209 CI | DONE. Closed #1186 as superseded. Synced origin/main (MERGEABLE/CLEAN). Fixed PR-policy RAG impact line. Hosted PR required SUCCESS (Static/Safety/Unit/Build/Production UI/Advisory UI/containers) on pre-ledger tip; docs-only follow-up pushed. Ready to merge; auto-merge not enabled. | gh pr checks; local policy ok; no provider/eval runs. |
| 2026-07-25 | cursor/pr1197-fix-regressions-d06a (PR #1197 fix) | c1e9696de6000440ad5b44e4d2fb2738a858deae | Fix-forward after Bugbot do-not-merge review | FIXED for tip. Synced to origin/main; restored clinical-notes trust gate + boundary tests + summaryMode 400 contract by taking main; removed ISSUE-07 RAG pre-classifier (rag.ts matches main — RAG impact: no retrieval behaviour change). Kept only additive SQL remediation: migration 20260725000000 (real worker URL + ISSUE-05 revokes), schema.sql URL/[REDACTED] fix + ISSUE-05, regenerated drift-manifest. Dropped broken upload authority refs (undefined canonicalAuthority). | Vitest: summaryMode reject + ClinicalNotes boundary 4/4; rag-classifier-memo + rag-tail-latency 17/17; upload smart-title/cleanup 3/3; check:migration-role pass; drift:manifest regenerated via Docker. No provider-backed checks. |
| 2026-07-25 | execute-system-audit-remediation (PR #1197) | c7ae011683614c8de6027347b49e8b3fb79dfa34 | Merge-ready polish: grant reassert + CI green path | READY. Hardened migration/schema to reassert service_role EXECUTE after CREATE OR REPLACE / ISSUE-05 revokes; drift regenerated. Prior regressions remain fixed (trust gate, summaryMode, no RAG pre-classifier). Delta vs main: migration + schema + drift + ledger only. | check:migration-role; drift:manifest; supabase-schema + function-grants Vitest 83/83; awaiting hosted PR required on tip. |
| 2026-07-25 | cursor/pr1190-dark-mode-salvage-f453 (PR #1214) | pending-ci-retrigger | CI unblock after bot sync | Hosted pr-branch-sync merged main onto tip (`68d0ceaab`), leaving CI `action_required` for bot-authored runs. Pushing agent commit to re-trigger non-bot CI before squash-merge; then close #1190. | Local pwa-manifest 8/8; trust gate present; prior unit failure fixed. No provider-backed checks. |

| 2026-07-25 | cursor/pr1190-dark-mode-salvage-f453 (PR #1214) | pending-ci-retrigger-2 | CI unblock + skip-branch-sync | Repeated pr-branch-sync bot merges left CI `action_required`. Applied `skip-branch-sync` label and agent retrigger so required checks can finish for squash-merge; then close #1190. | Hosted CI pending on tip; no provider-backed checks. |
Expand Down
21 changes: 11 additions & 10 deletions supabase/drift-manifest.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"generated_at": "2026-07-24T06:18:38.047Z",
"generated_at": "2026-07-25T15:45:24.778Z",
"generator": "scripts/generate-drift-manifest.ts",
"postgres_image": "supabase/postgres:17.6.1.127",
"schema_sha256": "87e910024d52ea024f4b19c34f6e078ecc48160dc50a483fa785677740673db1",
"replay_seconds": 18,
"postgres_image": "supabase/postgres:17.6.1.127@sha256:be60aee15997daca475b710b734bc6bfe52cd544dcd7e9fd2ff58210b6747d83",
"schema_sha256": "81240cb662ec8a9da27eca60a3908587f565c3eb67981aa0c21961d6b333a3d5",
"replay_seconds": 15,
"snapshot": {
"views": [
{
Expand Down Expand Up @@ -6775,11 +6775,12 @@
"signature": "public.correct_clinical_query_terms(text,real)"
},
{
"schema": "public",
"name": "create_uploaded_document_with_ingestion_job",
"signature": "public.create_uploaded_document_with_ingestion_job(jsonb,integer)",
"language": "plpgsql",
"security_definer": true
"acl": [
"postgres=X/postgres",
"service_role=X/postgres"
],
"def_hash": "54f1ab21c9d7cee9555b187dec088371",
"signature": "public.create_uploaded_document_with_ingestion_job(jsonb,integer)"
},
{
"acl": [
Expand Down Expand Up @@ -6897,7 +6898,7 @@
"postgres=X/postgres",
"service_role=X/postgres"
],
"def_hash": "4a8d38962265b8fde233dc8657773bf1",
"def_hash": "066ef1277bc11fa8092086fc66352d15",
"signature": "public.invoke_ingestion_worker(integer)"
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
-- Audit remediation: correct invoke_ingestion_worker URL fallback + harden grants.
--
-- Context: migration 20260724130100 introduced the GUC-backed worker URL pattern
-- but landed with a literal `[REDACTED]` fallback (from an earlier audit export).
-- Hosted apply of that migration can leave cron ingestion pointing at an invalid
-- base URL when `app.ingestion_worker_base_url` is unset. This follow-up restores
-- the real Clinical KB Database project URL and reasserts fail-closed grants.
--
-- ISSUE-05 / ISSUE-04 reasserts are idempotent with earlier migrations and with
-- supabase/schema.sql. Do not edit the already-applied 20260724130100 blob.

-- ISSUE-08: set GUC + replace function with the real project URL fallback.
do $$
begin
execute format('alter database %I set app.ingestion_worker_base_url = %L',
current_database(), 'https://sjrfecxgysukkwxsowpy.supabase.co');
exception
when insufficient_privilege then
raise notice 'Skipping ALTER DATABASE SET app.ingestion_worker_base_url (insufficient privilege on hosted Supabase); invoke_ingestion_worker falls back to the hardcoded URL.';
end
$$;

create or replace function public.invoke_ingestion_worker(p_limit integer default 25)
returns bigint
language plpgsql
security definer
set search_path = public, extensions, vault, pg_temp
as $$
declare
v_request_id bigint;
v_jwt text;
v_limit integer := greatest(1, least(coalesce("p_limit", 25), 200));
v_base_url text;
begin
select "decrypted_secret" into v_jwt
from "vault"."decrypted_secrets"
where "name" = 'cron_ingestion_jwt'
limit 1;

if v_jwt is null or length(trim(v_jwt)) = 0 then
raise exception 'Missing Vault secret: cron_ingestion_jwt';
end if;

-- Prefer the GUC; fall back to the hardcoded production URL so that
-- existing deployments that have not yet set the GUC continue to work.
v_base_url := coalesce(
nullif(current_setting('app.ingestion_worker_base_url', true), ''),
'https://sjrfecxgysukkwxsowpy.supabase.co'
);

select "net"."http_post"(
url := v_base_url || '/functions/v1/ingestion-worker?limit=' || v_limit::text,
headers := jsonb_build_object(
'Content-Type','application/json',
'Authorization','Bearer ' || v_jwt
),
body := jsonb_build_object('source','pg_cron','worker','ingestion-worker','ts', now()),
timeout_milliseconds := 60000
)
into v_request_id;

return v_request_id;
end;
$$;

-- CREATE OR REPLACE can leave grants ambiguous across platforms; reassert explicitly.
revoke execute on function public.invoke_ingestion_worker(integer) from public, anon, authenticated;
grant execute on function public.invoke_ingestion_worker(integer) to service_role;

-- ISSUE-05: revoke PUBLIC / client-role execute on invoker RPCs (idempotent).
revoke execute on function public.detect_legacy_ivfflat_indexes() from public, anon, authenticated;
revoke execute on function public.document_summary_text(uuid) from public, anon, authenticated;
revoke execute on function public.search_document_chunks(uuid, text, integer, uuid) from public, anon, authenticated;
revoke execute on function public.set_document_embedding_field_content_hash() from public, anon, authenticated;
grant execute on function public.detect_legacy_ivfflat_indexes() to service_role;
grant execute on function public.document_summary_text(uuid) to service_role;
grant execute on function public.search_document_chunks(uuid, text, integer, uuid) to service_role;
grant execute on function public.set_document_embedding_field_content_hash() to service_role;

-- ISSUE-04: Data API table/sequence fail-closed posture (idempotent with schema.sql).
revoke all privileges on all tables in schema public from anon, authenticated;
revoke all privileges on all sequences in schema public from anon, authenticated;
16 changes: 13 additions & 3 deletions supabase/schema.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
-- Medical RAG Knowledge Base schema.
-- Medical RAG Knowledge Base schema.
-- Run this in the Supabase SQL editor or with the Supabase CLI.
-- Tables are RLS protected; the local Next.js API and worker use the service role.
--
Expand Down Expand Up @@ -3476,7 +3476,7 @@ grant execute on function public.purge_expired_rag_query_misses(integer) to serv
do $$
begin
execute format('alter database %I set app.ingestion_worker_base_url = %L',
current_database(), '[REDACTED]');
current_database(), 'https://sjrfecxgysukkwxsowpy.supabase.co');
exception
when insufficient_privilege then
raise notice 'Skipping ALTER DATABASE SET app.ingestion_worker_base_url (insufficient privilege on hosted Supabase).';
Expand Down Expand Up @@ -3506,7 +3506,7 @@ begin

v_base_url := coalesce(
nullif(current_setting('app.ingestion_worker_base_url', true), ''),
'[REDACTED]'
'https://sjrfecxgysukkwxsowpy.supabase.co'
);

select "net"."http_post"(
Expand Down Expand Up @@ -9135,3 +9135,13 @@ begin
end if;
end;
$$;

-- Explicit function revokes (ISSUE-05)
revoke execute on function public.detect_legacy_ivfflat_indexes() from public, anon, authenticated;
revoke execute on function public.document_summary_text(uuid) from public, anon, authenticated;
revoke execute on function public.search_document_chunks(uuid, text, integer, uuid) from public, anon, authenticated;
revoke execute on function public.set_document_embedding_field_content_hash() from public, anon, authenticated;
grant execute on function public.detect_legacy_ivfflat_indexes() to service_role;
grant execute on function public.document_summary_text(uuid) to service_role;
grant execute on function public.search_document_chunks(uuid, text, integer, uuid) to service_role;
grant execute on function public.set_document_embedding_field_content_hash() to service_role;
Loading