Publish DevRunbook source
Managed validation / full (push) Successful in 3m18s

This commit is contained in:
DevRunbook release export
2026-09-03 04:09:17 +02:00
commit cfd2804e27
928 changed files with 161642 additions and 0 deletions
@@ -0,0 +1,100 @@
import { readFileSync, readdirSync } from 'node:fs'
import path from 'node:path'
import { describe, expect, it } from 'vitest'
const repositoryRoot = process.cwd()
function sourceFiles(relativeRoot: string): string[] {
const absoluteRoot = path.join(repositoryRoot, relativeRoot)
return readdirSync(absoluteRoot, { recursive: true, withFileTypes: true })
.filter(
(entry) =>
entry.isFile() &&
/\.(?:ts|tsx)$/u.test(entry.name) &&
!entry.name.endsWith('.test.ts'),
)
.map((entry) => path.join(entry.parentPath, entry.name))
}
function violations(files: readonly string[], forbidden: RegExp) {
return files
.filter((file) => forbidden.test(readFileSync(file, 'utf8')))
.map((file) => path.relative(repositoryRoot, file).replaceAll('\\', '/'))
}
describe('architectural dependency boundaries', () => {
it('keeps persistence adapters out of Next.js route handlers and UI', () => {
const routes = sourceFiles('apps/web/src/app').filter((file) =>
file.endsWith(`${path.sep}route.ts`),
)
const ui = sourceFiles('packages/ui/src')
const forbidden = /(?:@devrunbook\/db|drizzle-orm)/u
expect(violations(routes, forbidden)).toEqual([])
expect(violations(ui, forbidden)).toEqual([])
})
it('keeps domain and application packages independent of framework and persistence code', () => {
expect(
violations(
sourceFiles('packages/domain/src'),
/(?:@devrunbook\/(?:application|db)|drizzle-orm|from ['"]next(?:\/|['"]))/u,
),
).toEqual([])
expect(
violations(
sourceFiles('packages/application/src'),
/(?:@devrunbook\/db|drizzle-orm|from ['"]next(?:\/|['"]))/u,
),
).toEqual([])
})
it('prevents content and composer code from executing imported instructions', () => {
const files = [
...sourceFiles('packages/content/src'),
...sourceFiles('packages/composer/src'),
]
expect(
violations(
files,
/(?:node:child_process|child_process|Bun\.spawn|Deno\.Command)/u,
),
).toEqual([])
})
it('keeps operator commands attached to application use cases', () => {
const commands = sourceFiles('apps/worker/src/operator')
for (const command of commands) {
const source = readFileSync(command, 'utf8')
expect(source, path.relative(repositoryRoot, command)).toContain(
'@devrunbook/application',
)
expect(source, path.relative(repositoryRoot, command)).not.toMatch(
/(?:getSqlClient|\.execute\(|sql`)/u,
)
}
})
it('keeps worker orchestration downstream and job handlers adapter-free', () => {
const upstream = [
...sourceFiles('packages/domain/src'),
...sourceFiles('packages/application/src'),
...sourceFiles('packages/db/src'),
...sourceFiles('apps/web/src'),
]
expect(
violations(upstream, /(?:@devrunbook\/worker|apps\/worker)/u),
).toEqual([])
const handlers = sourceFiles('apps/worker/src/jobs').filter((file) =>
file.endsWith(`${path.sep}handlers.ts`),
)
expect(
violations(
handlers,
/(?:@devrunbook\/db|drizzle-orm|getSqlClient|node:child_process|sql`)/u,
),
).toEqual([])
})
})
@@ -0,0 +1,253 @@
import { cp, mkdtemp, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import path from 'node:path'
import type {
AuthPersistence,
AuthSessionRecord,
AuthUserRecord,
CreateAuthSessionRecord,
} from '../../packages/application/src/auth/auth-service'
import { AuthService } from '../../packages/application/src/auth/auth-service'
import { TokenDigester } from '../../packages/application/src/auth/token-digest'
import { loadPlaybookPackage } from '../../packages/content/src/loader'
import { createLogger } from '../../packages/observability/src/index'
import { handleAuthRequest } from '../../apps/web/src/auth/csrf'
import {
assertNonSecretConfiguration,
authorizeBootstrap,
} from '../../apps/web/src/setup/setup-policy'
import { afterEach, describe, expect, it, vi } from 'vitest'
const temporaryDirectories: string[] = []
afterEach(async () => {
await Promise.all(
temporaryDirectories.splice(0).map((directory) =>
rm(directory, {
recursive: true,
force: true,
}),
),
)
vi.restoreAllMocks()
})
async function maliciousPackage(): Promise<string> {
const directory = await mkdtemp(
path.join(tmpdir(), 'devrunbook-security-content-'),
)
temporaryDirectories.push(directory)
await cp(path.resolve('content/playbooks/root-cause-bugfix'), directory, {
recursive: true,
})
const manifestPath = path.join(directory, 'playbook.yaml')
const manifest = (await readFile(manifestPath, 'utf8')).replace(
' sensitive: false\n includeInOutput: true',
' sensitive: true\n includeInOutput: true',
)
await writeFile(manifestPath, manifest)
return directory
}
class CapturingAuthPersistence implements AuthPersistence {
readonly user: AuthUserRecord = {
id: 'user-1',
email: 'owner@example.test',
displayName: 'Owner',
passwordHash: '[password-hash]',
emailVerified: true,
image: null,
status: 'active',
createdAt: new Date('2026-07-27T00:00:00.000Z'),
updatedAt: new Date('2026-07-27T00:00:00.000Z'),
}
sessionInput: CreateAuthSessionRecord | undefined
async findUserById(id: string) {
return id === this.user.id ? this.user : null
}
async findUserByEmail(email: string) {
return email === this.user.email ? this.user : null
}
async updateUser() {
return this.user
}
async createSession(input: CreateAuthSessionRecord) {
this.sessionInput = input
return {
id: 'session-1',
revokedAt: null,
...input,
}
}
async findSessionByTokenHash(): Promise<AuthSessionRecord | null> {
return null
}
async touchSession(): Promise<AuthSessionRecord | null> {
return null
}
async revokeSessionByTokenHash() {
return false
}
async revokeSessionsForUser() {
return 0
}
}
describe('production security boundaries', () => {
it('uses the database workspace migration runner copied into the image', async () => {
const dockerfile = await readFile(path.resolve('Dockerfile'), 'utf8')
expect(dockerfile).toContain(
'CMD ["./packages/db/node_modules/.bin/tsx", "packages/db/src/migrate.ts"]',
)
expect(dockerfile).not.toContain(
'CMD ["./node_modules/.bin/tsx", "packages/db/src/migrate.ts"]',
)
})
it('ships the worker as a standalone bundle without production node_modules', async () => {
const dockerfile = await readFile(path.resolve('Dockerfile'), 'utf8')
const workerPackage = JSON.parse(
await readFile(path.resolve('apps/worker/package.json'), 'utf8'),
) as { scripts: { build: string } }
expect(workerPackage.scripts.build).toContain(
'esbuild src/index.ts src/operator/password-reset.ts',
)
expect(workerPackage.scripts.build).toContain('--bundle --platform=node')
expect(workerPackage.scripts.build).toContain(
'const require = createRequire(import.meta.url)',
)
expect(dockerfile).toContain(
'cp -a /app/apps/worker/dist/. /out/worker/dist/',
)
expect(dockerfile).not.toContain(
'pnpm --filter @devrunbook/worker --prod deploy',
)
})
it('rejects secret-bearing package output and nested setup configuration', async () => {
await expect(loadPlaybookPackage(await maliciousPackage())).rejects.toThrow(
'sensitive input problemStatement cannot be included in output',
)
expect(() =>
assertNonSecretConfiguration({
integration: { apiToken: 'must-never-be-persisted' },
}),
).toThrow(
'configuration.integration.apiToken must not contain secret material',
)
expect(() =>
assertNonSecretConfiguration({
integrationEncryptionKeyVersion: 'v2',
}),
).not.toThrow()
})
it('persists only a peppered HMAC session digest', async () => {
const rawToken = 'raw-session-token-with-high-entropy-0123456789'
const persistence = new CapturingAuthPersistence()
const digester = new TokenDigester(Buffer.alloc(32, 7))
const service = new AuthService(
persistence,
digester,
() => new Date('2026-07-27T12:00:00.000Z'),
)
const active = await service.createSession({
userId: persistence.user.id,
rawToken,
})
expect(active?.rawToken).toBe(rawToken)
expect(JSON.stringify(persistence.sessionInput)).not.toContain(rawToken)
expect(persistence.sessionInput?.tokenHash).toMatch(
/^hmac-sha256:v1:[a-f0-9]{64}$/u,
)
expect(
digester.matches(rawToken, persistence.sessionInput!.tokenHash),
).toBe(true)
expect(new TokenDigester(Buffer.alloc(32, 8)).digest(rawToken)).not.toBe(
persistence.sessionInput?.tokenHash,
)
})
it('denies proxy bootstrap bypass and cross-origin credential requests without reflection', async () => {
const proxied = new Request('http://127.0.0.1/api/v1/instance/setup', {
method: 'POST',
headers: { 'x-forwarded-for': '127.0.0.1' },
})
expect(authorizeBootstrap(proxied, '', undefined)).toBe(false)
expect(
authorizeBootstrap(proxied, 'attacker-token', 'operator-token'),
).toBe(false)
const handler = vi.fn(async () => new Response('should not run'))
const rawCookie = 'devrunbook.session=raw-session-secret'
const request = new Request(
'https://runbook.example.test/api/auth/session',
{
method: 'POST',
headers: {
origin: 'https://attacker.example.test',
'sec-fetch-site': 'cross-site',
cookie: rawCookie,
},
},
)
const response = await handleAuthRequest(
request,
handler,
'https://runbook.example.test',
)
const body = await response.text()
expect(response.status).toBe(403)
expect(handler).not.toHaveBeenCalled()
expect(body).not.toContain('attacker.example.test')
expect(body).not.toContain(rawCookie)
expect(body).toContain('INVALID_ORIGIN')
})
it('redacts root and nested secret fields from structured logs', async () => {
let output = ''
vi.spyOn(process.stdout, 'write').mockImplementation((chunk) => {
output += String(chunk)
return true
})
const logger = createLogger('info')
logger.info(
{
password: 'root-password-secret',
token: 'root-token-secret',
req: {
headers: {
authorization: 'Bearer raw-authorization-secret',
cookie: 'session=raw-cookie-secret',
},
},
account: { secret: 'nested-account-secret' },
},
'security redaction probe',
)
await new Promise((resolve) => setTimeout(resolve, 20))
expect(output).not.toContain('root-password-secret')
expect(output).not.toContain('root-token-secret')
expect(output).not.toContain('raw-authorization-secret')
expect(output).not.toContain('raw-cookie-secret')
expect(output).not.toContain('nested-account-secret')
expect(output).toContain('[REDACTED]')
})
})