Skip to content

fix(db): reconcile live database drift and harden security without RAG regression - #300

Merged
BigSimmo merged 21 commits into
mainfrom
cursor/fix-all-db-issues-5f13
Jul 6, 2026
Merged

fix(db): reconcile live database drift and harden security without RAG regression#300
BigSimmo merged 21 commits into
mainfrom
cursor/fix-all-db-issues-5f13

Conversation

@BigSimmo

Copy link
Copy Markdown
Owner

Summary

Reconciles live Supabase drift on sjrfecxgysukkwxsowpy, hardens security boundaries, and fixes CI blockers — without changing RAG scoring, ranking, or chunking behavior.

Changes

  • Migrations: 20260705133000 (search_document_chunks owner scope), 20260705220000 (jobs table, RPCs, embedding-fields grants, eval RLS)
  • Edge: indexing-v3-agent JSONB status RPC parsing fix
  • App: health deep probe gating, owner-scope retrieval tightening, document label governance advisory
  • Tests/docs: schema mirror tests, public access deep checks, migration reconciliation docs

Verification

CI fixes in this branch

CommitFix
6f1d525e3Prettier on 4 files blocking format check
09b3567c8TS2339 — add allowGlobalSearch? to fetchBestDocumentLookupChunks args type

Clinical Governance Preflight

  • Source-backed claims still require linked source verification before clinical use
  • No patient-identifiable document workflow introduced
  • Supabase target remains Clinical KB Database (sjrfecxgysukkwxsowpy)
  • Service-role keys and private document access remain server-only
  • No RAG scoring/ranking/chunking changes in this PR

Merge note

Branch may conflict with main where overlapping access-rollout work landed via other PRs (#291, #297). Resolve at merge without importing unrelated UI commits onto this branch.

Operator follow-ups (not in this PR)

  • Set HEALTH_DEEP_PROBE_SECRET in production
  • Publishable key rotation
  • Auth server connection cap (Supabase dashboard)
Open in WebOpen in Cursor

BigSimmo added 10 commits July 5, 2026 20:02
- Degrade invalid bearer tokens to anonymous scope instead of 401
- Allow public document read routes (list, detail, signed-url, search, images)
- Align registry routes with medications/differentials auth-signal short-circuit
- Let DocumentViewer load public sources without requiring sign-in
- Add regression tests and update access-control expectations
Create missing retrieval-support indexes (trgm, composite btree, partial
miss log) that were absent or only present under legacy names on live.
Update search_schema_health() to accept verified functional equivalents
during rollout. Set search_path for pg_trgm gin_trgm_ops in extensions.
Verified on linked project: search_schema_health() ok=true, missing=[].
- Re-apply indexing_v3_agent_jobs table and claim/update RPCs on live
- Codify match_document_embedding_fields_text with service_role-only execute
- Enable RLS on rag_visual_eval_* tables
- Fix edge function JSONB status RPC parsing
- Harden owner-scope and health deep-probe gating
- Restore .env.example; remove unused postgres npm dep
- Make gold-label governance advisory-only
- Re-apply indexing_v3_agent_jobs table and claim/update RPCs on live
- Codify match_document_embedding_fields_text with service_role-only execute
- Enable RLS on rag_visual_eval_* tables
- Fix edge function JSONB status RPC parsing
- Harden owner-scope and health deep-probe gating
- Restore .env.example; remove unused postgres npm dep
- Make gold-label governance advisory-only
@supabase

supabaseBot commented Jul 5, 2026

Copy link
Copy Markdown

Updates to Preview Branch (cursor/fix-all-db-issues-5f13) ↗︎

DeploymentsStatusUpdated
DatabaseMon, 06 Jul 2026 04:35:03 UTC
ServicesMon, 06 Jul 2026 04:35:03 UTC
APIsMon, 06 Jul 2026 04:35:03 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.

TasksStatusUpdated
ConfigurationsMon, 06 Jul 2026 04:35:05 UTC
MigrationsMon, 06 Jul 2026 04:35:09 UTC
SeedingMon, 06 Jul 2026 04:35:10 UTC
Edge FunctionsMon, 06 Jul 2026 04:35:13 UTC

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

@BigSimmo
BigSimmoforce-pushed the cursor/fix-all-db-issues-5f13 branch from 09b3567 to 8ab94eaCompareJuly 5, 2026 19:11
cursoragentand others added 3 commits July 5, 2026 19:32
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
Co-authored-by: BigSimmo <BigSimmo@users.noreply.github.com>
@BigSimmo
BigSimmo marked this pull request as ready for review July 6, 2026 02:34
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

CopilotAI 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.

Pull request overview

This PR reconciles observed drift between the repository and the live Supabase project schema, tightens owner-scoped retrieval boundaries, and hardens operational endpoints (health + indexing agent RPC parsing) while aiming to avoid any RAG scoring/ranking/chunking changes.

Changes:

  • Codifies live database drift via new/idempotent migrations and updates supabase/schema.sql to match (jobs table/RPCs, embedding-fields RPC grants, visual eval tables + RLS, search_document_chunks scope).
  • Hardens /api/health?deep=1 by requiring an operator secret header for the deep Supabase probe, and updates deep public-access tests accordingly.
  • Fixes indexing-v3-agent edge function handling of JSONB-returning status RPCs via robust result parsing.

Reviewed changes

Copilot reviewed 15 out of 15 changed files in this pull request and generated 2 comments.

Show a summary per file
FileDescription
tests/supabase-schema.test.tsAdds assertions to ensure schema + key migrations mirror live drift fixes and owner-scope tightening.
tests/public-access-deep.test.tsUpdates health deep-probe expectations to reflect new secret-gated behavior.
supabase/schema.sqlMirrors drift reconciliation (drop/recreate function signature, adds search_document_chunks, embedding-fields RPC, visual eval tables + RLS/policies, grants).
supabase/migrations/20260705220000_reconcile_live_database_drift.sqlNew idempotent migration to re-apply missing live objects and lock down permissions/RLS.
supabase/migrations/20260705210000_retrieval_owner_filter_sentinel.sqlAdds a defensive DROP to handle signature/OUT-column drift before CREATE OR REPLACE.
supabase/migrations/20260705133000_tighten_search_document_chunks_owner_scope.sqlDocuments/codifies live owner-scope tightening and revokes public/anon/auth execute.
supabase/functions/indexing-v3-agent/index.tsUses typed RPC rows + parsing helper for JSONB-returning job-status RPCs.
src/lib/env.tsAdds SUPABASE_DB_URL and HEALTH_DEEP_PROBE_SECRET to the validated env schema.
src/lib/document-label-governance.tsTreats missing gold-label rows as non-blocking (advisory) in the overall pass/fail result.
src/app/api/health/route.tsAdds constant-time header token check for deep health probe authorization; returns 503 on unauthorized deep probe.
scripts/check-document-label-governance.tsClarifies CLI output that missing gold-label rows are advisory.
package.jsonRemoves the postgres dependency.
docs/supabase-migration-reconciliation.mdDocuments the newly codified live drift and how it’s reconciled.
docs/process-hardening.mdAdds a dated log entry describing drift reconciliation and follow-ups.
.env.exampleAdds SUPABASE_DB_URL and HEALTH_DEEP_PROBE_SECRET examples for operators/devs.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment threadsrc/app/api/health/route.ts
Comment thread.env.example Outdated
BigSimmoand others added 2 commits July 6, 2026 12:15
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@BigSimmo

Copy link
Copy Markdown
OwnerAuthor

@copilot resolve the merge conflicts in this pull request

CopilotAI commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

@copilot resolve the merge conflicts in this pull request

Done — merged origin/main into this branch. The only conflict was in tests/supabase-schema.test.ts where both branches added a test in the same location. I kept both:

  • This branch: "mirrors tightened search_document_chunks owner scope in schema and migration"
  • main: "surfaces stale commit generation RPCs through search_schema_health"

Resolved in merge commit 3fc7de8.

@BigSimmo
BigSimmo merged commit ea569a7 into mainJul 6, 2026
5 checks passed
@BigSimmo
BigSimmo deleted the cursor/fix-all-db-issues-5f13 branch July 8, 2026 16:25
BigSimmo added a commit that referenced this pull request Aug 9, 2026
…1786)
* feat(design-system): build ErrorState, the gate with nothing behind it
GATES.md §3 lists the prohibition "Render '0 matches' after a failed
request" with the gate "ErrorState adoption + check", status planned.
Measured at origin/main 199b303, ErrorState existed nowhere in src or
tests — only in COMPONENTS.md, GATES.md and SPEC.md. This builds it.
The invariant is clinical, not cosmetic. A search that failed has no count
to report, so reporting zero is a false statement about the corpus: on the
services page "0 matches" asserts there are no crisis services when the
search never ran, and on favourites it reads as "you have saved nothing"
rather than "we could not load them". COMPONENTS.md:322 draws the same line
from the other side — "no result count is available" is not a MissingValue.
The component therefore takes no count and no children. There is no prop
through which a number can arrive, and the generated dtsPropsFor entry now
records that as the published API. The one remaining route, a caller writing
a count into title or body, is covered by a development-time tripwire that
matches a figure against a counted noun ("0 matches", "no results") so an
error code or a duration does not trip it. It warns and never throws: on the
one screen already reporting a failure, a thrown error is a blank page.
Requirements came from the surfaces that hand-roll this guard today. Three
do, and their comments state the rule outright:
search-results-header-band.tsx:210 ("no number may reach the DOM"),
services-navigator-page.tsx:634 ("a blocked registry must not reach the band
as '0 matches'") and favourites-command-library-page.tsx:1182. They are
correct, just not shared; converting them is a live-look change and
deliberately not here.
Three further sites carried into this task as hand-rolled guards are not
that, measured at this HEAD, and are recorded so the next reader does not
convert them: differentials-home.tsx:716,729 renders "0 matches"/"No
matches" when sourcesChecked is true, i.e. a legitimate zero after a search
that SUCCEEDED; specifiers-home-page.tsx:211 is a comment about not showing
a stale zero above real catalogue results, and lives in
src/components/specifiers/, not clinical-dashboard/; document-search-results
gates on recordStatus for loading, not for a failed count.
Registered per gates 11 and 12: source, design-sync export, preview, prop
contract, publication test entry, behavioural DOM tests, adoption-contract
family, and both generators regenerated (54 components, 59 roots).
Uses the shared floatingControl recipe rather than a hand-rolled control, so
the tap floor, focus ring and forced-colors border come from one owner. Adds
zero arbitrary padding/gap/radius/line-height, so the ratchet landed in the
previous commit is unaffected and the two stay separately revertible.
Scope: ErrorState only. OfflineState, PermissionDeniedState, NotFoundState
and UnavailableState share the pattern but have no gate pointing at them.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* feat(design-system): ratchet raw gap literals, the family #1780 left uncovered
#1780 landed rawPaddingLiterals, rawRadiusLiterals and rawLineHeightLiterals
for #262 part 3. Gap was the one remaining spacing surface a hand-picked
value could hide in: gap-[9px] and `gap: 18px` were counted by no ratchet at
all. This adds rawGapLiterals on that commit's own predicate and wiring.
Measured against origin/main ef9bb51: 34 sites across 9 files — 21 Tailwind
utilities, every one under src/components/therapy-compass/, plus 13 CSS
declarations in globals.css that a utility-only scan misses. Covering both
spellings is the same reason #1780 counts both: otherwise a literal escapes by
moving from a class into globals.css.
Kept as its own metric rather than folded into rawPaddingLiterals so the
therapy-compass cleanup can be paid down and re-pinned independently of the
padding debt, which is spread across fifteen unrelated files.
Reuses RAW_LITERAL_VALUE unchanged, so a value containing a CSS function
(env(, clamp(, max(, calc() stays a sanctioned computed form and is exempt.
Also corrects the §3 prohibition row, which #1780 left reading
"implemented-partial (colour/shadow/tap literals only)" and which named none
of the metrics it had just shipped. A row that understates shipped work is
what sends the next session to rebuild it — this change was itself started as
a duplicate of #262 part 3 for exactly that reason.
Mutation-verified in both halves, each naming the metric and the path:
a gap-[3px] utility gives "rawGapLiterals increased from 34 to 35" plus
"at src/components/ui/missing-value.tsx increased from 0 to 1"; a
`gap: 19px` declaration gives the same total plus "at src/app/globals.css
increased from 13 to 14".
Baseline diff is additive only. legacyShadowAliases measures 218 against its
pinned 220 on main; that slack is left exactly as found.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* docs(issues): capture the ErrorState and duplicate-work follow-ups
Four rows (#298-#301), added with npm run issues:add. Ids 295-297 were
claimed by main while this branch was open, which is ledger #156's
read-modify-write race behaving exactly as recorded.
- #298 (P2 task) the ErrorState enforcement check. GATES.md still reads
"planned" for the 0-matches prohibition and nothing in scripts/ or
eslint-rules/ references ErrorState, so the component exists but is not
required. Deliberately not flipped to implemented.
- #299 (P3 task) adopting ErrorState at the three surfaces that genuinely
hand-roll the guard. Live-look change, downstream of the redesign.
- #300 (P2 issue) three sites miscarried into M4 as guards that are not,
so the next reader does not convert them. differentials-home renders its
zero after a search that SUCCEEDED.
- #301 (P3 issue) two sessions built #262 part 3 in parallel because the
§3 row understated what had shipped. Proposes asserting that every
baseline metric key appears in GATES.md.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
* fix(design-system): restrict the ErrorState copy tripwire to development
Codex review on #1786 (P2). The doc comment described the tripwire as
development-only, but the emitter only silenced NODE_ENV === "test", so a
production caller supplying count-bearing title/body copy had the full
caller-provided string written to console.warn. On a clinical surface that
copy can quote the query — "0 results for <query>" — which turns a copy
defect into a disclosure risk. Nobody reads a production browser console
for design-system warnings, so the emit is now development-only and an
unset NODE_ENV is treated as production: fail quiet.
The gate is an exported predicate rather than an inline comparison because
an inline comparison is untestable here. Vite statically replaces
process.env.NODE_ENV inside src/ modules, so under Vitest the check
compiles to `"test" === "development"` and no stubEnv can move it. The
review asked for a production console-spy check; written that way it would
have passed while proving nothing, staying silent for the wrong reason and
continuing to pass even if the guard were deleted. shouldEmitErrorStateDiagnostic
is asserted directly instead — development true; production, test and unset
false — with the console spy kept alongside as the weaker check that catches
an emitter which warns unconditionally.
Verified: typecheck 0 errors, lint 0, format:check 0,
check:design-system-contract 0, Tests 70 passed (70) across
error-state.dom and design-sync-visual-exports.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
BigSimmo added a commit that referenced this pull request Aug 13, 2026
… queue text (#1890)
* docs(issues): retire 22 non-actionable ledger rows and correct the #231 queue text
A yield review of all 114 open rows against current main. The queue had become
roughly 60 tasks and 50 notes; this removes the notes and fixes two places where
the ledger was actively misdirecting.
The correction that matters most: the recommended-queue entry for #231, the top
clinical P1, told every session to "measure and fix the fast-route budget /
generation timeout" — an approach #231's own detail records as tested and
rejected, because the decisive 40-second probe completed generation in 25.272s
with route_deadline_exceeded=false and still failed quality. The session-start
hook prints the queue, not the row, so the refuted text was the text agents read.
Closed 22 rows:
- #304 was already done on main (commit d182844 refreshed the ranking
snapshot; generatedAt is 0 days old, not 2026-07-20), yet sat in the queue
advertising a freshness fuse that is not armed.
- #241#244#272#294#300#257 were standing cautions whose own text says
"no action". Each one's knowledge now lives in the code it protects, so
closing the row loses nothing.
- #196-#200 are five steps of the disaster-recovery checklist that is
canonical in docs/operator-backlog.md, with no trigger until a restore.
- #86#188 were index rows over children that are individually findable.
- #250#253#254 were superseded; #250 and #253 say so themselves.
- #156#301#152#236#260 merged into #168, #292 and #169 respectively —
each pair or group was one problem recorded two to four times.
Demoted 20 rows with a stated reason (premature ops for a single-user
prototype, upstream-blocked, measurement-gated, or design-system adoption
competing with an open clinical P1). The Pri cell is unchanged because the
writer has no --pri flag — which is now #313.
Added three rows for mechanism gaps this sweep exposed: rows outliving their
own completion (#312), the missing --pri flag (#313), and the queue being able
to contradict the row it cites with no guard (#314).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuYJz8hauCsCdx8r4fXiZU
* docs(ledger): record the ledger yield review handoff
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DuYJz8hauCsCdx8r4fXiZU
* Keep recovery work visible and pin forced colors
---------
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for freeto 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.

4 participants

@BigSimmo@cursoragent