Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/db/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1034,7 +1034,9 @@ export const upstreamDriftReports = sqliteTable(
issueUrl: text("issue_url"),
payloadJson: text("payload_json").notNull().default("{}"),
generatedAt: text("generated_at").notNull(),
updatedAt: text("updated_at").notNull(),
// Same $defaultFn house rule as every sibling updatedAt (#8369): an insert that omits the column
// must get a real ISO-8601 timestamp, not a schema-level gap waiting for a future writer to trip over.
updatedAt: text("updated_at").notNull().$defaultFn(() => nowIso()),
},
(table) => ({
fingerprint: uniqueIndex("upstream_drift_reports_fingerprint_unique").on(table.fingerprint),
Expand Down
33 changes: 32 additions & 1 deletion test/unit/schema-timestamp-defaults.test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
import { eq } from "drizzle-orm";
import { describe, expect, it } from "vitest";
import { getDb } from "../../src/db/client";
import { aiReviewCache, aiSlopCache, linkedIssueSatisfactionCache, orbRelayPending, repositorySettings, webhookEvents } from "../../src/db/schema";
import {
aiReviewCache,
aiSlopCache,
linkedIssueSatisfactionCache,
orbRelayPending,
repositorySettings,
upstreamDriftReports,
webhookEvents,
} from "../../src/db/schema";
import { createTestEnv } from "../helpers/d1";

const ISO = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
Expand Down Expand Up @@ -102,4 +110,27 @@ describe("timestamp column defaults", () => {
expect(row?.createdAt).toMatch(ISO);
expect(row?.createdAt).not.toBe("CURRENT_TIMESTAMP");
});

it("applies upstreamDriftReports.updatedAt default on omit (#8369)", async () => {
const env = createTestEnv();
const db = getDb(env.DB);
// Omit updatedAt — the schema $defaultFn must inject a real ISO timestamp (same house rule as every
// sibling updatedAt). generatedAt stays explicit; this issue only covers the updatedAt gap.
await db.insert(upstreamDriftReports).values({
id: "drift-ts-default-1",
fingerprint: "fp-ts-default-1",
severity: "low",
summary: "schema defaultFn regression",
generatedAt: "2026-07-24T00:00:00.000Z",
});
const [row] = await db
.select()
.from(upstreamDriftReports)
.where(eq(upstreamDriftReports.id, "drift-ts-default-1"))
.limit(1);
expect(row?.updatedAt).toMatch(ISO);
expect(row?.updatedAt).not.toBe("CURRENT_TIMESTAMP");
expect(row?.updatedAt).not.toBe("");
expect(row?.generatedAt).toBe("2026-07-24T00:00:00.000Z");
});
});