Skip to content

feat(api): add canon consistency and search - #28

Merged
mcfarhat merged 2 commits into
developfrom
trello-next-3
Sep 6, 2026
Merged

mcfarhat merged 2 commits into
developfrom
trello-next-3

Conversation

@KareemN1936

Copy link
Copy Markdown
Collaborator

Summary

  • Fix the Prisma upgrade migration guard so it reruns the base migration chain after resolving the historical failed migration, allowing late migration collisions to be caught.
  • Add deterministic proposal consistency checks against the latest World Bible and published canon, stored as AI reports and surfaced before voting in the proposal UI.
  • Add a Postgres full-text search projection over worlds and published lore entries, /search API, GIN-backed migration, write-path projection updates, and
    pm run search:reindex --workspace=@hivelore/api.

Trello

Verification

  • npm run typecheck --workspace=@hivelore/api
  • npm run typecheck --workspace=@hivelore/web
  • npm run lint --workspace=@hivelore/api
  • npm run lint --workspace=@hivelore/web
  • npm run test --workspace=@hivelore/api
  • npm run test --workspace=@hivelore/web
  • npm run db:validate
  • git diff --check

Note: the API test suite skips the live PostgreSQL concurrency test when TEST_DATABASE_ADMIN_URL is not configured.

@KareemN1936

Copy link
Copy Markdown
Collaborator Author

Implemented the three selected Web 5 cards in this PR:

  • Trello #45: upgrade migration guard now reruns the base branch migration chain after resolving the historical failed migration before applying the repaired branch history.
  • Trello feat(profile): show reputation badges and history #27: proposal voting UI now runs a deterministic consistency check before voting; results are stored as AIReport rows and existing AI-warning handling surfaces major conflicts.
  • Trello #34: added SearchIndex full-text projection, GIN-backed search vector migration, /search API, write-path updates, and search reindex command.

Verification run locally:

  • npm run typecheck --workspace=@hivelore/api
  • npm run typecheck --workspace=@hivelore/web
  • npm run lint --workspace=@hivelore/api
  • npm run lint --workspace=@hivelore/web
  • npm run test --workspace=@hivelore/api
  • npm run test --workspace=@hivelore/web
  • npm run db:validate
  • git diff --check

The API suite reports one skipped test because TEST_DATABASE_ADMIN_URL is not configured for the live PostgreSQL concurrency test.

@KareemN1936

Copy link
Copy Markdown
Collaborator Author

Rebased onto latest origin/develop after resolving the app route registration conflict by keeping both profile and search routes. PR is now mergeable.

Post-rebase verification:

  • npm run typecheck --workspace=@hivelore/api
  • npm run typecheck --workspace=@hivelore/web
  • npm run lint --workspace=@hivelore/api
  • npm run lint --workspace=@hivelore/web
  • npm run test --workspace=@hivelore/api
  • npm run test --workspace=@hivelore/web
  • npm run db:validate
  • git diff --check

@github-actions

github-actions Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Vercel preview is ready:

https://hivelore-la8qo17xz-kareemn1936s-projects.vercel.app

Commit: 86fda6a

@KareemN1936

Copy link
Copy Markdown
Collaborator Author

@mcfarhat Dr. Mohammad Farhat, I’m waiting on your review/merge for these three Trello cards currently in Code Review: #45, #27, and #34. The PR is mergeable and checks are passing. Thank you.

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

Approving. Three cards' worth of work and it holds up — reviewed against the code and a real Postgres, not just read.

Search — the part I pushed hardest on

Raw SQL taking user input is where this could have gone badly, and it doesn't:

  • $queryRaw tagged template, not $queryRawUnsafe, so ${q} is a bound parameter — no injection surface
  • websearch_to_tsquery, which is the right choice over to_tsquery: it's the user-facing parser and won't throw on malformed input like a stray & or unbalanced quote
  • pagination bounded twice over — zod max(50) at the route and Math.min(Math.max(...), MAX_PAGE_SIZE) in the lib, with q capped at 120 chars. No route to an unbounded LIMIT.

The migration is the strongest piece. Maintaining the tsvector in a trigger rather than application code means no future write path can forget to update it, the setweight A/B correctly ranks title above content, existing rows are backfilled in the same migration, and the GIN index is there. That's how this should be done.

Consistency check

Deterministic, no LLM call — no key, no latency, no spend, and reproducible, which matters for something attached to canon voting.

Crucially it's a separate /ai-consistency endpoint; the vote path never calls it. So a false positive from a regex heuristic cannot block a vote at the API level — the UI asks for acknowledgement instead. That's the right shape for advisory tooling, and the decision I'd have argued for.

The greedy {2,80} capture makes the matcher low-recall rather than noisy: it'll miss contradictions more often than invent them. For a warning shown next to a vote, failing quiet is the correct direction.

One observation rather than a request: every finding is hardcoded severity: 'high'. If this ever gains a second category, that field will need to mean something.

Migration guard (R4) — approving on reasoning, and I want to be honest about why

Re-running migrate deploy on the base schema after migrate resolve --rolled-back is exactly the step I identified as missing, and it's a no-op when nothing failed, so it cannot regress anything.

But I could not demonstrate it catching a regression. I stood up a real Postgres and tried an A/B: inject a collision against ProposalComment (migration 16 of develop's 19) and compare the guard with and without the fix. Both runs failed identically — because the base chain applied all 19 migrations cleanly, so the resolve path was never entered and Re-running base branch… never printed in either run. The P3018 in my logs came from my own injected migration in the branch stage, not from the base chain.

So the failure mode the fix guards against doesn't reproduce in a clean environment today. Either develop's history has since been repaired, or my original diagnosis of the mechanism was wrong. I'm approving this change because it is correct and safe, not because I proved it works — and I'd rather say so than imply a verification I don't have.

Verified locally

proposal-consistency 2/2, search-index 4/4, and the full upgrade guard passes end-to-end against a real database. CI green on 69b87d8, the current head.

@mcfarhat
mcfarhat merged commit 4344dd8 into develop Sep 6, 2026
2 checks passed
@mcfarhat
mcfarhat deleted the trello-next-3 branch September 6, 2026 10:30
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