CodeIssuesPull RequestsActionsSecurityInsights
✨ AI
More
Settings

feat(spine): synthetic journeys — probe the product, not just the port #5474

Merged⚡ AI-generatedXSccantynz wants to mergefeat/synthetic-journeysmainopened 23d ago
2 changed files+29−12
Modifiedsrc/__tests__/email-normalize.test.ts+9−1View fileUnifiedSplit
232232 // of accepting one. It normalizes through `normalizeEmail(body.email)`
233233 // like every other site here — the first version lowercased inline and
234234 // this sweep is what caught it.
235 expect(sites.length).toBe(9);
235 //
236 // The tenth is the spine's probe user (src/lib/synthetic-journeys.ts,
237 // 2026-08-09) — a synthetic account minted so the authed journey can
238 // exercise logged-in rendering without a stored credential. First-party
239 // and fixed-address (spine-probe@gluecron.internal), so no provisioner;
240 // it normalizes at the insert. The CI gate's first enforced PR is what
241 // flagged it — this census, doing exactly what the paragraph above says
242 // it exists to do.
243 expect(sites.length).toBe(10);
236244 });
237245
238246 it("registration normalizes before the existence check, not after", async () => {
Modifiedsrc/lib/synthetic-journeys.ts+20−11View fileUnifiedSplit
3232import { db } from "../db";
3333import { sessions, users } from "../db/schema";
3434import { generateSessionToken } from "./auth";
35import { normalizeEmail } from "./email-normalize";
3536import { config } from "./config";
3637import type { SyntheticCheckResult } from "./synthetic-monitor";
3738
9495 }
9596}
9697
97/** Find-or-create the probe user; returns its id. */
98/**
99 * Find-or-create the probe user; returns its id.
100 *
101 * Insert-first with onConflictDoNothing, then select: two monitor ticks
102 * racing here must not both pass an existence check and both insert (the
103 * last-races.test.ts invariant — CI caught exactly that pattern in the
104 * first version of this function, on the gate's first enforced PR).
105 */
98106async function ensureProbeUser(): Promise<string> {
99 const [existing] = await db
100 .select({ id: users.id })
101 .from(users)
102 .where(eq(users.username, PROBE_USERNAME))
103 .limit(1);
104 if (existing) return existing.id;
105107 const unloginable = Buffer.from(
106108 crypto.getRandomValues(new Uint8Array(48))
107109 ).toString("base64");
108 const [row] = await db
110 const [inserted] = await db
109111 .insert(users)
110112 .values({
111113 username: PROBE_USERNAME,
112 email: PROBE_EMAIL,
114 email: normalizeEmail(PROBE_EMAIL),
113115 displayName: "Spine Probe (synthetic)",
114116 // Random bytes, never bcrypt — no password can ever hash to this.
115117 passwordHash: `!unloginable!${unloginable}`,
116118 emailVerifiedAt: new Date(),
117119 })
120 .onConflictDoNothing({ target: [users.username] })
118121 .returning({ id: users.id });
119 if (!row) throw new Error("probe user insert returned no row");
120 return row.id;
122 if (inserted) return inserted.id;
123 const [existing] = await db
124 .select({ id: users.id })
125 .from(users)
126 .where(eq(users.username, PROBE_USERNAME))
127 .limit(1);
128 if (!existing) throw new Error("probe user neither inserted nor found");
129 return existing.id;
121130}
122131
123132/** Real session row → authed pages must render logged-in chrome. */
124133
c comment · e edit title · m merge · a approve · r request changes · ? shortcuts