Files
policy-enforced/test/policy-enforced.test.ts
T
2026-09-28 14:49:02 -04:00

212 lines
8.0 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { overall, validateReport } from '@extant2000/evidence-record'
import {
claimRule,
evaluatePolicy,
evaluateRule,
formatReport,
toReport,
inOverflowRule,
orgScopingRule,
type SourceFile,
} from '../src/index.js'
const f = (path: string, content: string): SourceFile => ({ path, content })
// An app that scopes rows by tenant columns.
const tenantOrg = orgScopingRule({
guards: /requireOrg|resolveOrg|assertContactInOrg/,
inlineTenantFilter: /\.eq\((['"])(organization_id|org_id|owner_id|user_id)\1/,
})
// An app with no tenant columns at all, using RBAC capability checks instead.
const rbacOrg = orgScopingRule({
serviceClients: /createServiceClient|createClient\(/,
guards: /requireAuth|requireProjectCap|requireAdminCap|getRequestClient/,
})
describe('orgScopingRule — the divergence that made this a library', () => {
it('tenant-column app: a service-role handler with no guard is a violation', () => {
const r = evaluateRule(tenantOrg, [
f('server/api/x.ts', 'const s = createServiceClient()\ns.from("t").select()'),
])
expect(r.violations).toHaveLength(1)
})
it('tenant-column app: an inline tenant filter satisfies it', () => {
const r = evaluateRule(tenantOrg, [
f('server/api/x.ts', `const s = createServiceClient()\ns.from("t").select().eq('org_id', id)`),
])
expect(r.violations).toHaveLength(0)
})
it('RBAC app: a capability check satisfies it, with NO tenant column', () => {
// This is why one shared script could not work. The RBAC app has no org_id
// anywhere; under the tenant-column rule this same file would be a false
// violation.
const rbacFile = f('server/api/y.ts',
'await requireProjectCap(event, id, "view")\nconst s = createServiceClient()')
expect(evaluateRule(rbacOrg, [rbacFile]).violations).toHaveLength(0)
expect(evaluateRule(tenantOrg, [rbacFile]).violations).toHaveLength(1)
})
it('a documented exemption excuses the file and is counted', () => {
const r = evaluateRule(tenantOrg, [
f('server/api/cron.ts', 'createServiceClient()\n// org-scoping-exempt: nightly cron, cross-tenant by design'),
])
expect(r.violations).toHaveLength(0)
expect(r.exempted).toBe(1)
})
it('ignores files outside the path scope', () => {
const r = evaluateRule(tenantOrg, [f('app/pages/x.vue', 'createServiceClient()')])
expect(r.considered).toBe(0)
expect(r.violations).toHaveLength(0)
})
it('ignores a file that never touches a service-role client', () => {
const r = evaluateRule(tenantOrg, [f('server/api/x.ts', 'const s = getRequestClient(event)')])
expect(r.considered).toBe(1)
expect(r.subject).toBe(0)
})
})
describe('inOverflowRule', () => {
const rule = inOverflowRule({ chunkHelpers: /selectInChunks/ })
it('flags a dynamic .in() with no chunking', () => {
const r = evaluateRule(rule, [f('server/x.ts', `supabase.from('t').select().in('id', ids)`)])
expect(r.violations).toHaveLength(1)
})
it('accepts a chunked call', () => {
const r = evaluateRule(rule, [
f('server/x.ts', `selectInChunks(ids, p => supabase.from('t').select().in('id', p))`),
])
expect(r.violations).toHaveLength(0)
})
it('does NOT flag a literal array — that list is bounded', () => {
const r = evaluateRule(rule, [f('server/x.ts', `.in('status', ['a','b'])`)])
expect(r.subject).toBe(0)
})
})
describe('claimRule — advertised == implemented', () => {
// The classic gap: uptime or SLA language in marketing copy with nothing
// in the code that enforces it.
const rule = claimRule({
id: 'uptime-claim',
claimPaths: ['src/views/', 'app/pages/'],
claim: /99\.\d+%\s*uptime|uptime\s*SLA/i,
enforcedBy: /uptimeCredit|slaEnforcer/,
})
it('flags an uptime claim with no enforcement', () => {
const r = evaluateRule(rule, [f('src/views/Pricing.vue', '<p>99.9% uptime SLA</p>')])
expect(r.violations).toHaveLength(1)
})
it('passes when enforcement is present', () => {
const r = evaluateRule(rule, [
f('src/views/Pricing.vue', '<p>99.9% uptime SLA</p>\nimport { uptimeCredit } from "~/lib"'),
])
expect(r.violations).toHaveLength(0)
})
})
describe('regex state safety', () => {
it('a global-flag rule does not skip files via lastIndex', () => {
// A `g` regex carries lastIndex between .test() calls. Reusing one across
// files makes later files silently pass — a green gate covering nothing.
const sticky = orgScopingRule({
serviceClients: /createServiceClient/g,
guards: /requireOrg/g,
})
const r = evaluateRule(sticky, [
f('server/api/a.ts', 'createServiceClient()'),
f('server/api/b.ts', 'createServiceClient()'),
f('server/api/c.ts', 'createServiceClient()'),
])
expect(r.violations).toHaveLength(3)
})
})
describe('evaluatePolicy + formatReport', () => {
it('distinguishes "nothing was checked" from a real pass', () => {
// "nothing changed that this covers" is not "the policy holds".
const nothing = evaluatePolicy([tenantOrg], [f('server/api/x.ts', 'export default 1')])
expect(nothing.passed).toBe(true)
expect(nothing.vacuous).toBe(true)
expect(overall(toReport(nothing))).toBe('not-assessed')
const nothingText = formatReport(nothing)
expect(nothingText).toContain('NOT ASSESSED')
expect(nothingText).toContain('not evidence the policy holds')
// The word it replaced needed a glossary.
expect(nothingText).not.toContain('VACUOUS')
const real = evaluatePolicy([tenantOrg], [
f('server/api/x.ts', `createServiceClient()\n.eq('org_id', o)`),
])
expect(real.passed).toBe(true)
expect(real.vacuous).toBe(false)
expect(overall(toReport(real))).toBe('pass')
})
it('a pass cites the files it actually checked', () => {
// A gate that reports "3 files checked" without naming them is an
// asserted result, which is the defect this library exists to find.
const real = evaluatePolicy([tenantOrg], [
f('server/api/x.ts', `createServiceClient()\n.eq('org_id', o)`),
])
expect(toReport(real).findings[0]!.evidence.length).toBeGreaterThan(0)
expect(formatReport(real, { evidence: 'full' })).toContain('server/api/x.ts')
})
it('aggregates violations across rules and prints remedies', () => {
const rep = evaluatePolicy([tenantOrg, inOverflowRule({ chunkHelpers: /selectInChunks/ })], [
f('server/api/a.ts', 'createServiceClient()'),
f('server/b.ts', `.in('id', ids)`),
])
expect(rep.passed).toBe(false)
expect(rep.violations).toHaveLength(2)
const text = formatReport(rep, { evidence: 'full' })
expect(text).toContain('org-scoping')
expect(text).toContain('in-overflow')
expect(text).toContain('org-scoping-exempt:')
expect(overall(toReport(rep))).toBe('fail')
})
it('cites the line that triggered the rule, not just the file', () => {
const rep = evaluatePolicy([tenantOrg], [
f('server/api/a.ts', 'const x = 1\nconst y = 2\ncreateServiceClient()'),
])
expect(rep.violations[0]!.line).toBe(3)
expect(rep.violations[0]!.excerpt).toBe('createServiceClient()')
expect(formatReport(rep)).toContain('server/api/a.ts:3')
})
it('counts exemptions as evidence rather than hiding them', () => {
const rep = evaluatePolicy([tenantOrg], [
f('server/api/a.ts', 'createServiceClient() // org-scoping-exempt: cross-tenant cron'),
])
expect(rep.passed).toBe(true)
const text = formatReport(rep, { evidence: 'full' })
expect(text).toContain('exempted via')
expect(text).toContain('server/api/a.ts')
})
it('every conclusion carries a citation', () => {
const rep = evaluatePolicy([tenantOrg, inOverflowRule({ chunkHelpers: /selectInChunks/ })], [
f('server/api/a.ts', 'createServiceClient()'),
f('server/b.ts', `.in('id', ids)`),
])
expect(validateReport(toReport(rep))).toEqual([])
})
it('an empty file set is vacuous, never a pass claim', () => {
const rep = evaluatePolicy([tenantOrg], [])
expect(rep.vacuous).toBe(true)
})
})