This commit is contained in:
@@ -0,0 +1,215 @@
|
||||
import {
|
||||
applyRepositoryProfileServerMetadata,
|
||||
type RepositoryProfile,
|
||||
} from '@devrunbook/repository-intel'
|
||||
import { describe, expect, it, vi } from 'vitest'
|
||||
|
||||
import type { SafePlaybookVersionProjection } from '../playbooks/playbook-catalog'
|
||||
import type { repositoryProfileRevisions } from '../schema'
|
||||
import {
|
||||
DrizzleCompositionSourceReader,
|
||||
type CompositionPlaybookCatalog,
|
||||
type CompositionPlaybookVersionIdentityRowSource,
|
||||
type CompositionProfileRevisionRowSource,
|
||||
} from './composition-source-reader'
|
||||
|
||||
type RevisionRow = typeof repositoryProfileRevisions.$inferSelect
|
||||
|
||||
const workspaceId = '00000000-0000-4000-8000-000000000001'
|
||||
const revisionId = '00000000-0000-4000-8000-000000000002'
|
||||
|
||||
function profile(): RepositoryProfile {
|
||||
return applyRepositoryProfileServerMetadata(
|
||||
{
|
||||
apiVersion: 'devrunbook.io/v1alpha1',
|
||||
kind: 'RepositoryProfile',
|
||||
metadata: { name: 'Source fixture', 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,
|
||||
)
|
||||
}
|
||||
|
||||
function version(): SafePlaybookVersionProjection {
|
||||
return {
|
||||
id: '00000000-0000-4000-8000-000000000003',
|
||||
playbookId: '00000000-0000-4000-8000-000000000004',
|
||||
version: '1.2.3',
|
||||
digest: 'a'.repeat(64),
|
||||
lifecycle: 'validated',
|
||||
manifest: {
|
||||
metadata: {
|
||||
slug: 'bounded-change',
|
||||
version: '1.2.3',
|
||||
title: 'Bounded change',
|
||||
},
|
||||
spec: { intent: { outcome: 'Make a bounded change.' } },
|
||||
},
|
||||
template: '# Task\n',
|
||||
quality: {},
|
||||
publishedAt: new Date('2026-07-27T12:00:00.000Z'),
|
||||
}
|
||||
}
|
||||
|
||||
function revision(document = profile()): RevisionRow {
|
||||
return {
|
||||
id: revisionId,
|
||||
repositoryId: '00000000-0000-4000-8000-000000000005',
|
||||
revisionNumber: 1,
|
||||
profileJson: document,
|
||||
sourceSnapshotId: null,
|
||||
contentDigest: document.metadata.contentDigest!,
|
||||
createdBy: '00000000-0000-4000-8000-000000000006',
|
||||
createdAt: new Date('2026-07-27T12:00:00.000Z'),
|
||||
}
|
||||
}
|
||||
|
||||
function dependencies(
|
||||
selectedVersion: SafePlaybookVersionProjection | null = version(),
|
||||
selectedRevision: RevisionRow | null = revision(),
|
||||
) {
|
||||
const catalog: CompositionPlaybookCatalog = {
|
||||
findVersionBySlug: vi.fn(async () => selectedVersion),
|
||||
}
|
||||
const rows: CompositionProfileRevisionRowSource = {
|
||||
findRevisionForWorkspace: vi.fn(async () => selectedRevision),
|
||||
}
|
||||
const identities: CompositionPlaybookVersionIdentityRowSource = {
|
||||
findPublishedIdentityForWorkspace: vi.fn(async () => ({
|
||||
slug: 'bounded-change',
|
||||
version: '1.2.3',
|
||||
})),
|
||||
}
|
||||
return {
|
||||
catalog,
|
||||
rows,
|
||||
identities,
|
||||
reader: new DrizzleCompositionSourceReader(catalog, rows, identities),
|
||||
}
|
||||
}
|
||||
|
||||
describe('DrizzleCompositionSourceReader', () => {
|
||||
it('uses exact published catalog semantics with workspace scope', async () => {
|
||||
const target = dependencies()
|
||||
await expect(
|
||||
target.reader.findPublishedPlaybookVersion(
|
||||
workspaceId,
|
||||
'bounded-change',
|
||||
'1.2.3',
|
||||
),
|
||||
).resolves.toEqual({
|
||||
id: version().id,
|
||||
slug: 'bounded-change',
|
||||
version: '1.2.3',
|
||||
digest: 'a'.repeat(64),
|
||||
lifecycle: 'validated',
|
||||
manifest: version().manifest,
|
||||
template: '# Task\n',
|
||||
})
|
||||
expect(target.catalog.findVersionBySlug).toHaveBeenCalledWith(
|
||||
'bounded-change',
|
||||
'1.2.3',
|
||||
undefined,
|
||||
{ workspaceId },
|
||||
)
|
||||
})
|
||||
|
||||
it('returns generic null for missing or inaccessible playbooks', async () => {
|
||||
const target = dependencies(null)
|
||||
await expect(
|
||||
target.reader.findPublishedPlaybookVersion(
|
||||
workspaceId,
|
||||
'bounded-change',
|
||||
'1.2.3',
|
||||
),
|
||||
).resolves.toBeNull()
|
||||
})
|
||||
|
||||
it('resolves a persisted version ID through its governed visible identity', async () => {
|
||||
const target = dependencies()
|
||||
await expect(
|
||||
target.reader.findPublishedPlaybookVersionById(workspaceId, version().id),
|
||||
).resolves.toMatchObject({ id: version().id, slug: 'bounded-change' })
|
||||
expect(
|
||||
target.identities.findPublishedIdentityForWorkspace,
|
||||
).toHaveBeenCalledWith(workspaceId, version().id)
|
||||
expect(target.catalog.findVersionBySlug).toHaveBeenCalledWith(
|
||||
'bounded-change',
|
||||
'1.2.3',
|
||||
undefined,
|
||||
{ workspaceId },
|
||||
)
|
||||
})
|
||||
|
||||
it('returns generic null for an inaccessible persisted version ID', async () => {
|
||||
const target = dependencies()
|
||||
vi.mocked(
|
||||
target.identities.findPublishedIdentityForWorkspace,
|
||||
).mockResolvedValue(null)
|
||||
await expect(
|
||||
target.reader.findPublishedPlaybookVersionById(workspaceId, version().id),
|
||||
).resolves.toBeNull()
|
||||
expect(target.catalog.findVersionBySlug).not.toHaveBeenCalled()
|
||||
})
|
||||
|
||||
it('loads an exact immutable profile revision through workspace scoping', async () => {
|
||||
const target = dependencies()
|
||||
await expect(
|
||||
target.reader.findRepositoryProfileRevision(workspaceId, revisionId),
|
||||
).resolves.toMatchObject({
|
||||
id: revisionId,
|
||||
revisionNumber: 1,
|
||||
contentDigest: profile().metadata.contentDigest,
|
||||
profile: { metadata: { revision: 1 } },
|
||||
})
|
||||
expect(target.rows.findRevisionForWorkspace).toHaveBeenCalledWith(
|
||||
workspaceId,
|
||||
revisionId,
|
||||
)
|
||||
})
|
||||
|
||||
it('returns generic null for a missing or cross-workspace revision', async () => {
|
||||
const target = dependencies(version(), null)
|
||||
await expect(
|
||||
target.reader.findRepositoryProfileRevision(workspaceId, revisionId),
|
||||
).resolves.toBeNull()
|
||||
})
|
||||
|
||||
it('fails closed when stored profile bytes and digest disagree', async () => {
|
||||
const target = dependencies(version(), {
|
||||
...revision(),
|
||||
contentDigest: 'f'.repeat(64),
|
||||
})
|
||||
await expect(
|
||||
target.reader.findRepositoryProfileRevision(workspaceId, revisionId),
|
||||
).rejects.toThrow('failed integrity validation')
|
||||
})
|
||||
})
|
||||
Reference in New Issue
Block a user