Skip to content

Commit ba28f64

Browse files
gregbergeclaude
andauthored
fix(backend): widen and encrypt github_installations.githubToken (#2347)
GitHub installation access tokens have grown beyond 255 characters, overflowing the varchar(255) "githubToken" column and throwing "value too long for type character varying(255)" on patch. Widen the column to text and encrypt it at rest (random IV), matching GithubAccount.accessToken. The Model base is retro-compatible: writes always encrypt, and reads fall back to plaintext for not-yet-migrated values, so the migration can deploy before the code. Short-lived tokens re-encrypt naturally on refresh, so no backfill is needed. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 93ec04c commit ba28f64

3 files changed

Lines changed: 24 additions & 2 deletions

File tree

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* @param { import("knex").Knex } knex
3+
*/
4+
export async function up(knex) {
5+
// GitHub installation access tokens have grown beyond 255 characters, which
6+
// overflowed the default varchar(255) column. Widen it to text.
7+
await knex.schema.alterTable("github_installations", (table) => {
8+
table.text("githubToken").alter();
9+
});
10+
}
11+
12+
/**
13+
* @param { import("knex").Knex } knex
14+
*/
15+
export async function down(knex) {
16+
await knex.schema.alterTable("github_installations", (table) => {
17+
table.string("githubToken").alter();
18+
});
19+
}

apps/backend/db/structure.sql

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ CREATE TABLE public.github_installations (
944944
"updatedAt" timestamp with time zone NOT NULL,
945945
"githubId" integer NOT NULL,
946946
deleted boolean DEFAULT false NOT NULL,
947-
"githubToken" character varying(255),
947+
"githubToken" text,
948948
"githubTokenExpiresAt" timestamp with time zone,
949949
app text DEFAULT 'main'::text NOT NULL,
950950
proxy boolean DEFAULT false NOT NULL,
@@ -5199,4 +5199,5 @@ INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('2026061
51995199
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260620120000_pending-review-unique.js', 1, NOW());
52005200
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260625120000_project-ignore-config.js', 1, NOW());
52015201
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260627120000_add-screenshots-has-parent-index.js', 1, NOW());
5202-
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260628120000_build-review-automatic.js', 1, NOW());
5202+
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260628120000_build-review-automatic.js', 1, NOW());
5203+
INSERT INTO public.knex_migrations(name, batch, migration_time) VALUES ('20260709120000_github-installation-token-text.js', 1, NOW());

apps/backend/src/database/models/GithubInstallation.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import { timestampsSchema } from "../util/schemas";
44
export class GithubInstallation extends Model {
55
static override tableName = "github_installations";
66

7+
static override encryptedAttributes = ["githubToken"];
8+
79
static override jsonSchema = {
810
allOf: [
911
timestampsSchema,

0 commit comments

Comments
 (0)