// Per-env run-ops-id mint cutover integration proof. // // NEVER mocks the DB: the mint decision runs through the pure core `computeRunIdMintKind` // wired to a REAL `makeFlag(prisma)` that reads the REAL `Organization.featureFlags` / // `FeatureFlag` rows in a testcontainers Postgres. Only the two boundary knobs // are injected — `masterEnabled` and the `splitEnabled` boot-boolean — never a // mocked DB. The run-ops-id/cuid format + residency are then proven through the SAME isomorphic // helpers the real trigger path uses (`generateRunOpsId` / `RunId.toFriendlyId` / // `RunId.fromFriendlyId` / `ownerEngine`). import type { PrismaClient } from "@trigger.dev/database"; import { generateRunOpsId, ownerEngine, RunId } from "@trigger.dev/core/v3/isomorphic"; import { postgresTest } from "@internal/testcontainers"; import { describe, expect, vi } from "vitest"; import { computeRunIdMintKind, type RunIdMintKind, } from "~/v3/runOpsMigration/runOpsMintKind.server"; import { FEATURE_FLAG } from "~/v3/featureFlags"; import { makeFlag } from "~/v3/featureFlags.server"; import { createTestOrgProjectWithMember, createRuntimeEnvironment, uniqueId, } from "./fixtures/environmentVariablesFixtures"; vi.setConfig({ testTimeout: 60_000 }); // The real trigger-path mint helper, copied verbatim from triggerTask.server.ts so the // test exercises the exact id format a cut-over env produces. function mintRunOpsFriendlyId(): string { return RunId.toFriendlyId(generateRunOpsId()); } // Mirrors the real trigger path: resolve the kind, then mint either a run-ops friendlyId or // the default cuid one (RunId.generate()). function mintRunFriendlyId(kind: RunIdMintKind): string { return kind === "runOpsId" ? mintRunOpsFriendlyId() : RunId.generate().friendlyId; } async function seedOrgEnv(prisma: PrismaClient, mintFlag?: RunIdMintKind) { const { organization, project } = await createTestOrgProjectWithMember(prisma); const environment = await createRuntimeEnvironment(prisma, { projectId: project.id, organizationId: organization.id, type: "PRODUCTION", slug: uniqueId("prod"), }); if (mintFlag) { await prisma.organization.update({ where: { id: organization.id }, data: { featureFlags: { [FEATURE_FLAG.runOpsMintKind]: mintFlag } }, }); } return { organization, environment }; } // Build the env-bound `flag` dependency around a REAL makeFlag(prisma) reading the real // Organization.featureFlags override store. Pure-core gets the real DB-backed flag; only // masterEnabled + splitEnabled are injected boundary config. function realFlag(prisma: PrismaClient) { const flagFn = makeFlag(prisma); return async (orgId: string, orgFeatureFlags: unknown | undefined): Promise => { const overrides = orgFeatureFlags !== undefined ? orgFeatureFlags : ( await prisma.organization.findFirst({ where: { id: orgId }, select: { featureFlags: true }, }) )?.featureFlags; return flagFn({ key: FEATURE_FLAG.runOpsMintKind, defaultValue: "cuid", overrides: (overrides as Record) ?? {}, }); }; } describe("per-env run-ops-id mint cutover", () => { postgresTest( "canary org mints run-ops/NEW; non-canary org mints cuid/LEGACY", async ({ prisma }) => { const a = await seedOrgEnv(prisma, "runOpsId"); // canary const b = await seedOrgEnv(prisma); // not cut over const flag = realFlag(prisma); const deps = { masterEnabled: true, splitEnabled: async () => true, flag }; const kindA = await computeRunIdMintKind( { organizationId: a.organization.id, id: a.environment.id }, deps ); const kindB = await computeRunIdMintKind( { organizationId: b.organization.id, id: b.environment.id }, deps ); expect(kindA).toBe("runOpsId"); expect(kindB).toBe("cuid"); const friendlyA = mintRunFriendlyId(kindA); const friendlyB = mintRunFriendlyId(kindB); expect(RunId.fromFriendlyId(friendlyA).length).toBe(26); expect(ownerEngine(RunId.fromFriendlyId(friendlyA))).toBe("NEW"); expect(RunId.fromFriendlyId(friendlyB).length).toBe(25); expect(ownerEngine(RunId.fromFriendlyId(friendlyB))).toBe("LEGACY"); } ); postgresTest( "split OFF mints cuid even for a 'runOpsId'-flagged org (split gate dominates)", async ({ prisma }) => { const a = await seedOrgEnv(prisma, "runOpsId"); const flag = vi.fn(realFlag(prisma)); const kind = await computeRunIdMintKind( { organizationId: a.organization.id, id: a.environment.id }, { masterEnabled: true, splitEnabled: async () => false, flag } ); expect(kind).toBe("cuid"); expect(flag).not.toHaveBeenCalled(); // gated off before any DB read } ); postgresTest( "drain-new-forward (D8): flipping back to cuid stops new run-ops mints without reverting existing", async ({ prisma }) => { const a = await seedOrgEnv(prisma, "runOpsId"); const flag = realFlag(prisma); const deps = { masterEnabled: true, splitEnabled: async () => true, flag }; // First run is born run-ops/NEW while cut over. const firstKind = await computeRunIdMintKind( { organizationId: a.organization.id, id: a.environment.id }, deps ); const firstFriendly = mintRunFriendlyId(firstKind); expect(firstKind).toBe("runOpsId"); expect(ownerEngine(RunId.fromFriendlyId(firstFriendly))).toBe("NEW"); // Roll the org back to cuid (drain-new-forward — set the flag to "cuid"). await prisma.organization.update({ where: { id: a.organization.id }, data: { featureFlags: { [FEATURE_FLAG.runOpsMintKind]: "cuid" } }, }); // The NEXT run mints cuid again (the env-bound resolver's TTL cache is not used here, // so the flip is observed immediately — production waits one cache TTL). const nextKind = await computeRunIdMintKind( { organizationId: a.organization.id, id: a.environment.id }, deps ); const nextFriendly = mintRunFriendlyId(nextKind); expect(nextKind).toBe("cuid"); expect(ownerEngine(RunId.fromFriendlyId(nextFriendly))).toBe("LEGACY"); // The already-minted run-ops run is untouched — drain-new-forward never reverts it. expect(RunId.fromFriendlyId(firstFriendly).length).toBe(26); expect(ownerEngine(RunId.fromFriendlyId(firstFriendly))).toBe("NEW"); } ); postgresTest( "parent and child re-resolve independently from their own org flag", async ({ prisma }) => { // Parent lives in a cut-over org; child is triggered into a NON-cut-over org. const parentOrg = await seedOrgEnv(prisma, "runOpsId"); const childOrg = await seedOrgEnv(prisma); // not cut over const flag = realFlag(prisma); const deps = { masterEnabled: true, splitEnabled: async () => true, flag }; const parentKind = await computeRunIdMintKind( { organizationId: parentOrg.organization.id, id: parentOrg.environment.id }, deps ); const childKind = await computeRunIdMintKind( { organizationId: childOrg.organization.id, id: childOrg.environment.id }, deps ); // Observed behavior: the mint decision is resolved per the run's OWN org/env flag — // it does NOT inherit the parent's residency. A child in a non-cut-over org mints cuid // even when its parent was born run-ops. If children must inherit, that inheritance // belongs to the child-trigger path, not this resolver. expect(parentKind).toBe("runOpsId"); expect(childKind).toBe("cuid"); } ); });