Skip to content

fix: external_report_files has no foreign key (2.1.1) - #12

Merged
BackStacked merged 5 commits into
mainfrom
claude/project-thread-86xth5
Nov 9, 2026
Merged

BackStacked merged 5 commits into
mainfrom
claude/project-thread-86xth5

Conversation

@BackStacked

Copy link
Copy Markdown
Contributor

What and why

In 2.1.0, external_report_files.id was a foreign key to external_reports. The api stores the partner PDF first and creates the external report with the file's id only after extraction. Extraction runs inline, or in a worker job whose payload carries just the file id. On PostgreSQL, every import therefore fails with external_report_files_id_fkey. This shows up on api#23's CI.

Two separate pushes made 2.1.0 miss the fix: the fix (b30ee5e) landed on the branch after #11 had already merged.

  • src/pg/models.ts: id is now a plain UUID primary key with no foreign key. Mongo never had one.
  • src/core/types.ts and docs/EXTERNAL-REPORTS.md: document that the file is stored before its report.
  • scripts/test.ts: a new contract check stores a PDF before its report exists, on both backends. This check would have caught the bug.
  • Version 2.1.1.

TEST_BACKENDS=pg npm test: 100 passed, 0 failed. Mongo is not run locally; CI runs it.

A database that already ran sync() on 2.1.0 keeps the constraint, so drop it by hand: ALTER TABLE external_report_files DROP CONSTRAINT external_report_files_id_fkey;. None should exist yet, because the api has not been deployed with 2.1.0.

Release: after merge, tag v2.1.1.


Generated by Claude Code

Five new repositories, on PostgreSQL and MongoDB, for the api's report-reader imports:

- externalReports (external_reports): one row per partner PDF, sourceSha256 unique per
  organisation, the ExtractedReport JSON as is, status, warnings
- externalReportFiles (external_report_files): the PDF bytes, apart so lists never load them
- externalSignatories (external_signatories): the partner signature registry; listForOrg is
  cached per organisation through the cache layer and cleared on every write
- externalSignatures (external_signatures): the PNG per (organisation, PDF, signature)
- reportProvenance (report_provenance): one per report, where its results came from

Bytes go in as Uint8Array and come out as Buffer on both drivers. New tables and
collections only; sync() creates them. Contract tests on both backends; TEST_BACKENDS=pg
runs PostgreSQL only. docs/EXTERNAL-REPORTS.md describes the storage.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jBohmYiwjQLWmN2duiZcA
…ore its report)

The api stores the PDF first and extracts it (inline or in a worker job whose payload
carries only the file id); the external report then takes the file's id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jBohmYiwjQLWmN2duiZcA
…ore its report)

The api stores the PDF first and extracts it (inline or in a worker job whose payload
carries only the file id); the external report then takes the file's id.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018jBohmYiwjQLWmN2duiZcA
@BackStacked
BackStacked merged commit fdf51ac into main Nov 9, 2026
1 check passed
@BackStacked
BackStacked deleted the claude/project-thread-86xth5 branch November 9, 2026 12:48
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