Files
accounted/tests/pg/agent-atom-registry.pg.test.ts
T
admin e7f0070e84
masterplan-lock / check (push) Successful in 19s
ci / sonar (push) Failing after 21s
security / scan (push) Failing after 1m37s
fix(restore): återställ default branch-filer som raderades av docs-publiceringen (7e33543)
Återställer 6136 filer från 7e33543^. Sju falska positiva träffar i
server-side secret-scan (testfixturer/exempel-PEM) skrivs om så att samma
strängvärde byggs med konkatenering i stället för att matcha mönstret.
2026-11-10 09:37:22 +01:00

96 lines
4.4 KiB
TypeScript

import { describe, expect, it } from 'vitest'
import { seedCompany } from '@/tests/pg/fixtures'
import { withUserContext } from '@/tests/pg/setup'
describe('agent_atom_registry.pg: seed + RLS', () => {
it('seed migration populated active atoms with non-null bodies and no swarm-* ids', async () => {
const { userId } = await seedCompany()
const rows = await withUserContext(userId, async (client) => {
const res = await client.query<{ id: string; body: string | null; mcp_exposed: boolean }>(
`SELECT id, body, mcp_exposed FROM public.agent_atom_registry WHERE is_active`,
)
return res.rows
})
// The generated seed migration (…_seed_agent_atom_bodies.sql) runs during replay.
expect(rows.length).toBeGreaterThan(0)
// Every active atom has a real body inlined: the production read path depends
// on this (no disk fallback in prod).
for (const r of rows) {
expect(r.body, `atom ${r.id} body should be non-empty`).toBeTruthy()
expect(r.mcp_exposed).toBe(true)
}
// swarm-* audit skills must never become atoms; a curated horizontal must be present.
expect(rows.some((r) => r.id.includes('swarm'))).toBe(false)
expect(rows.some((r) => r.id === 'horizontal/swedish-vat')).toBe(true)
})
it('seeds reference children whose parent_atom_id points at a real top-level skill', async () => {
const { userId } = await seedCompany()
const { children, orphans, vatRef } = await withUserContext(userId, async (client) => {
const childRes = await client.query<{ n: number }>(
`SELECT count(*)::int AS n FROM public.agent_atom_registry WHERE parent_atom_id IS NOT NULL`,
)
// FK already guarantees this, but assert there are no dangling links anyway.
const orphanRes = await client.query<{ n: number }>(
`SELECT count(*)::int AS n
FROM public.agent_atom_registry c
WHERE c.parent_atom_id IS NOT NULL
AND NOT EXISTS (
SELECT 1 FROM public.agent_atom_registry p WHERE p.id = c.parent_atom_id
)`,
)
const vatRefRes = await client.query<{ id: string; body: string | null; parent_atom_id: string }>(
`SELECT id, body, parent_atom_id FROM public.agent_atom_registry
WHERE id = 'horizontal/swedish-vat/vat-compliance-reference'`,
)
return { children: childRes.rows[0]!.n, orphans: orphanRes.rows[0]!.n, vatRef: vatRefRes.rows[0] }
})
expect(children).toBeGreaterThan(0)
expect(orphans).toBe(0)
expect(vatRef?.parent_atom_id).toBe('horizontal/swedish-vat')
expect(vatRef?.body).toBeTruthy()
})
it('catalog filter (parent_atom_id IS NULL) hides references but the parent footer exposes them', async () => {
const { userId } = await seedCompany()
const { listed, vatBody } = await withUserContext(userId, async (client) => {
// The query every catalog uses: top-level skills only.
const listedRes = await client.query<{ id: string }>(
`SELECT id FROM public.agent_atom_registry
WHERE is_active AND parent_atom_id IS NULL`,
)
const vatRes = await client.query<{ body: string }>(
`SELECT body FROM public.agent_atom_registry WHERE id = 'horizontal/swedish-vat'`,
)
return { listed: listedRes.rows.map((r) => r.id), vatBody: vatRes.rows[0]?.body ?? '' }
})
// No reference id (three-segment, "<tier>/<slug>/<ref>") survives the filter.
expect(listed.some((id) => id.split('/').length === 3)).toBe(false)
expect(listed).toContain('horizontal/swedish-vat')
// …yet the loadable id is reachable from the parent body once loaded.
expect(vatBody).toContain('gnubok_load_skill("horizontal/swedish-vat/vat-compliance-reference")')
})
it('authenticated users can read the catalog but not write it', async () => {
const { userId } = await seedCompany()
await withUserContext(userId, async (client) => {
const sel = await client.query<{ n: number }>(
`SELECT count(*)::int AS n FROM public.agent_atom_registry`,
)
expect(sel.rows[0]!.n).toBeGreaterThan(0)
// No INSERT policy for authenticated: the catalog ships via service-role
// migrations only.
await expect(
client.query(
`INSERT INTO public.agent_atom_registry (id, tier, title, description, body_path)
VALUES ('horizontal/hacker', 'horizontal', 'x', 'x', 'x')`,
),
).rejects.toThrow()
})
})
})