What happens
Every migrations/*.sql column storing a raw GitHub-native numeric id (installation id, account/user id, check-run id, comment id) is declared bare INTEGER. That's correct on SQLite/D1 (INTEGER there is just a type-affinity hint; it already stores any 64-bit value without truncation), but on the self-host Postgres backend it's a real, enforced 4-byte column.
GitHub's own ids are a single global counter shared across all of GitHub (not scoped per-repo the way issue/PR numbers are). Comment ids in particular are already well past 2^31 (~2.1B) as of 2026, confirmed live on edge-nl-01:
Failed query: insert into "github_agent_command_answers" (...) values (...)
caused by: value "4945217685" is out of range for type integer [22003]
This surfaced from a @gittensory chat answer-storage insert, but affects every table with the same column shape.
Fix
Added widenGithubIdColumnsToBigint (src/selfhost/pg-adapter.ts), mirroring the existing tuneGithubRateLimitObservationsAutovacuum pattern exactly: a Postgres-only, idempotent ALTER COLUMN ... TYPE bigint batch across every affected table, run unconditionally after migrations on every boot (never touches the original migration files, which are correct as-written for SQLite/D1). SQLite/D1 never runs this at all.
Every statement was dry-run validated against the live production schema (BEGIN; ...; ROLLBACK;) before being committed to code — one candidate table (orb_installations) turned out to have been dropped by a later migration (#60, retiring that pipeline), caught this way rather than shipping a statement that would have silently sunk the entire atomic batch (Postgres runs a multi-statement simple-query string as one implicit transaction).
Test plan
What happens
Every
migrations/*.sqlcolumn storing a raw GitHub-native numeric id (installation id, account/user id, check-run id, comment id) is declared bareINTEGER. That's correct on SQLite/D1 (INTEGER there is just a type-affinity hint; it already stores any 64-bit value without truncation), but on the self-host Postgres backend it's a real, enforced 4-byte column.GitHub's own ids are a single global counter shared across all of GitHub (not scoped per-repo the way issue/PR numbers are). Comment ids in particular are already well past 2^31 (~2.1B) as of 2026, confirmed live on edge-nl-01:
This surfaced from a
@gittensory chatanswer-storage insert, but affects every table with the same column shape.Fix
Added
widenGithubIdColumnsToBigint(src/selfhost/pg-adapter.ts), mirroring the existingtuneGithubRateLimitObservationsAutovacuumpattern exactly: a Postgres-only, idempotentALTER COLUMN ... TYPE bigintbatch across every affected table, run unconditionally after migrations on every boot (never touches the original migration files, which are correct as-written for SQLite/D1). SQLite/D1 never runs this at all.Every statement was dry-run validated against the live production schema (
BEGIN; ...; ROLLBACK;) before being committed to code — one candidate table (orb_installations) turned out to have been dropped by a later migration (#60, retiring that pipeline), caught this way rather than shipping a statement that would have silently sunk the entire atomic batch (Postgres runs a multi-statement simple-query string as one implicit transaction).Test plan
npm run typecheck— cleanD1Database.exec(), no real Postgres needed)npm run test:coverage(full, unsharded) — 719 files / 14210 tests passed, 0 failuresnpm run test:ci(full gate) — greennpm audit --audit-level=moderate— 0 vulnerabilitiesALTERstatements dry-run validated against the live edge-nl-01 Postgres schema (BEGIN/ROLLBACK, no actual change) before mergesrc/selfhost/pg-adapter.tsandsrc/server.tsare both incodecov.yml's ignore list (Postgres runtime adapter / self-host process entry) — patch-coverage gate does not block on this PR