import { createHash, randomUUID } from 'node:crypto' import { applyRepositoryProfileServerMetadata, type RepositoryProfile, } from '@devrunbook/repository-intel' import { afterAll, beforeAll, describe, expect, it } from 'vitest' import { closeDatabase, getSqlClient } from '../index' import { DrizzleGeneratedRunStore } from './generated-run-store' const databaseIntegration = process.env.DEVRUNBOOK_DATABASE_INTEGRATION === 'true' && Boolean(process.env.DATABASE_URL) function profile(name: string): RepositoryProfile { return applyRepositoryProfileServerMetadata( { apiVersion: 'devrunbook.io/v1alpha1', kind: 'RepositoryProfile', metadata: { name, revision: 1, source: 'manual' }, spec: { repositoryType: 'single-app', stack: { languages: ['TypeScript'], frameworks: [], packageManagers: ['pnpm'], databases: ['PostgreSQL'], deploymentTypes: ['Docker'], testFrameworks: ['Vitest'], }, commands: [], paths: { applicationRoots: ['apps/web'], testRoots: ['tests'], documentationRoots: ['docs'], generated: ['dist'], protected: ['runtime'], excluded: ['node_modules'], }, policies: { preserveBackwardCompatibility: true, newDependencies: 'justify', gitWrite: 'none', migrations: 'reversible-only', documentationRequired: true, networkAccess: 'forbidden', productionDataAccess: 'forbidden', }, }, }, 1, ) } describe.skipIf(!databaseIntegration)( 'generated-run history integration', () => { const workspaceA = randomUUID() const workspaceB = randomUUID() const userId = randomUUID() const repositoryA = randomUUID() const repositoryB = randomUUID() const alphaSlug = `history-alpha-${randomUUID()}` const betaSlug = `history-beta-${randomUUID()}` let alphaVersionId: string let betaVersionId: string let profileRevisionA: string let profileRevisionB: string let store: DrizzleGeneratedRunStore const runIds = [randomUUID(), randomUUID(), randomUUID()] async function insertVersion(slug: string) { const sql = getSqlClient() const [playbook] = await sql<{ id: string }[]>` insert into playbooks ( workspace_id, logical_id, slug, namespace, source_type ) values ( ${workspaceA}, ${slug}, ${slug}, ${`private-${workspaceA}`}, 'private' ) returning id ` const manifest = { metadata: { slug, version: '1.0.0', title: 'History fixture' }, spec: { intent: { outcome: 'Verify history.' } }, } const [version] = await sql<{ id: string }[]>` insert into playbook_versions ( playbook_id, semantic_version, lifecycle, package_api_version, title, summary, category, risk_tier, package_json, template_text, content_digest, published_at, created_by ) values ( ${playbook!.id}, '1.0.0', 'validated', 'devrunbook.io/v1alpha1', 'History fixture', 'History fixture', 'testing', 'low', ${JSON.stringify(manifest)}::jsonb, '# Task', ${'a'.repeat(64)}, '2026-07-27T12:00:00.000Z', ${userId} ) returning id ` return version!.id } async function insertRun(input: { id: string workspaceId: string playbookVersionId: string slug: string generatedAt: string repository?: { id: string revisionId: string document: RepositoryProfile } corruptRepository?: boolean }) { const sql = getSqlClient() const prompt = `# ${input.id}\n` const digest = createHash('sha256').update(prompt, 'utf8').digest('hex') const repositorySnapshot = input.corruptRepository ? { revisionId: input.repository!.revisionId, repositoryId: input.repository!.id, revisionNumber: 1, contentDigest: input.repository!.document.metadata.contentDigest, profile: {}, } : input.repository ? { revisionId: input.repository.revisionId, repositoryId: input.repository.id, revisionNumber: 1, contentDigest: input.repository.document.metadata.contentDigest, profile: input.repository.document, } : null await sql` insert into generated_runs ( id, workspace_id, playbook_version_id, playbook_snapshot_json, repository_profile_snapshot_json, normalized_input_json, policy_snapshot_json, provenance_json, lint_result_json, rendered_prompt, render_digest, idempotency_key, generated_by, generated_at ) values ( ${input.id}, ${input.workspaceId}, ${input.playbookVersionId}, ${JSON.stringify({ slug: input.slug })}::jsonb, ${repositorySnapshot === null ? null : JSON.stringify(repositorySnapshot)}::jsonb, '{}'::jsonb, '{}'::jsonb, '[]'::jsonb, ${JSON.stringify({ exportReadiness: 'ready', findings: [] })}::jsonb, ${prompt}, ${digest}, ${randomUUID()}, ${userId}, ${input.generatedAt} ) ` } beforeAll(async () => { const sql = getSqlClient() await sql` insert into users ( id, email, display_name, password_hash, instance_role, status ) values ( ${userId}, ${`run-history-${userId}@example.invalid`}, 'Run history', 'not-a-real-password-hash', 'user', 'active' ) ` await sql` insert into workspaces (id, name, type) values (${workspaceA}, 'Run history A', 'team'), (${workspaceB}, 'Run history B', 'team') ` await sql` insert into repositories (id, workspace_id, display_name, source_type) values (${repositoryA}, ${workspaceA}, 'Repository A', 'manual'), (${repositoryB}, ${workspaceA}, 'Repository B', 'manual') ` alphaVersionId = await insertVersion(alphaSlug) betaVersionId = await insertVersion(betaSlug) const profileA = profile('Repository A') const profileB = profile('Repository B') const [revisionA] = await sql<{ id: string }[]>` insert into repository_profile_revisions ( repository_id, revision_number, profile_json, content_digest, created_by ) values ( ${repositoryA}, 1, ${JSON.stringify(profileA)}::jsonb, ${profileA.metadata.contentDigest!}, ${userId} ) returning id ` const [revisionB] = await sql<{ id: string }[]>` insert into repository_profile_revisions ( repository_id, revision_number, profile_json, content_digest, created_by ) values ( ${repositoryB}, 1, ${JSON.stringify(profileB)}::jsonb, ${profileB.metadata.contentDigest!}, ${userId} ) returning id ` profileRevisionA = revisionA!.id profileRevisionB = revisionB!.id await insertRun({ id: runIds[0]!, workspaceId: workspaceA, playbookVersionId: alphaVersionId, slug: alphaSlug, generatedAt: '2026-07-27T12:00:00.000Z', repository: { id: repositoryA, revisionId: profileRevisionA, document: profileA, }, }) await insertRun({ id: runIds[1]!, workspaceId: workspaceA, playbookVersionId: alphaVersionId, slug: alphaSlug, generatedAt: '2026-07-27T12:00:00.000Z', }) await insertRun({ id: runIds[2]!, workspaceId: workspaceA, playbookVersionId: betaVersionId, slug: betaSlug, generatedAt: '2026-07-26T12:00:00.000Z', repository: { id: repositoryB, revisionId: profileRevisionB, document: profileB, }, }) store = new DrizzleGeneratedRunStore() }) afterAll(async () => { const sql = getSqlClient() await sql`delete from workspaces where id in (${workspaceA}, ${workspaceB})` await sql`delete from users where id = ${userId}` await closeDatabase() }) it('paginates generatedAt plus ID without duplicates or omissions', async () => { const seen: string[] = [] let cursor: string | null = null do { const page = await store.listForWorkspace(workspaceA, { limit: 1, cursor, }) seen.push(...page.items.map((item) => item.id)) cursor = page.nextCursor } while (cursor) const tied = runIds .slice(0, 2) .sort((left, right) => left.localeCompare(right, 'en')) expect(seen).toEqual([...tied, runIds[2]]) expect(new Set(seen).size).toBe(3) await expect(store.listForWorkspace(workspaceB, {})).resolves.toEqual({ items: [], nextCursor: null, }) }) it('filters playbooks relationally and repositories through validated snapshots', async () => { const byPlaybook = await store.listForWorkspace(workspaceA, { playbookSlug: alphaSlug, }) expect(byPlaybook.items.map((item) => item.id).sort()).toEqual( runIds.slice(0, 2).sort(), ) const byRepository = await store.listForWorkspace(workspaceA, { repositoryId: repositoryA, }) expect(byRepository.items.map((item) => item.id)).toEqual([runIds[0]]) }) it('fails closed when a repository filter encounters a corrupt frozen snapshot', async () => { const corruptId = randomUUID() await insertRun({ id: corruptId, workspaceId: workspaceA, playbookVersionId: alphaVersionId, slug: alphaSlug, generatedAt: '2026-07-28T12:00:00.000Z', repository: { id: repositoryA, revisionId: profileRevisionA, document: profile('Repository A'), }, corruptRepository: true, }) await expect( store.listForWorkspace(workspaceA, { repositoryId: repositoryA }), ).rejects.toMatchObject({ code: 'generated_run_persistence_corrupt' }) }) }, )