feat(api): Postgres persistence for registries + scans (owner-scoped, fail-closed)
CI (SIAX Cloud) / security (push) Successful in 13s
CI (SIAX Cloud) / contracts (pull_request) Successful in 17s
CI (SIAX Cloud) / security (pull_request) Successful in 13s
CI (SIAX Cloud) / contracts (push) Successful in 16s
CI (SIAX Cloud) / quality (push) Successful in 52s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m13s
CI (SIAX Cloud) / security (push) Successful in 13s
CI (SIAX Cloud) / contracts (pull_request) Successful in 17s
CI (SIAX Cloud) / security (pull_request) Successful in 13s
CI (SIAX Cloud) / contracts (push) Successful in 16s
CI (SIAX Cloud) / quality (push) Successful in 52s
CI (SIAX Cloud) / quality (pull_request) Successful in 1m13s
- schema migration 001 (registries, scans; owner_sub = introspected subject) - pg pool + services; scan ownership enforced in SQL (INSERT ... SELECT WHERE owner_sub) - real handlers: 201/400/404/500, owner-scoped GET/POST, listScans registryId filter - graceful shutdown closes pool; 7 new persistence tests (21/21)
This commit is contained in:
@@ -0,0 +1,56 @@
|
||||
export interface RegistryRow {
|
||||
id: string;
|
||||
owner_sub: string;
|
||||
name: string;
|
||||
url: string;
|
||||
config: unknown;
|
||||
created_at: Date;
|
||||
}
|
||||
|
||||
export interface PoolLike {
|
||||
query(text: string, values?: unknown[]): Promise<{ rows: Record<string, unknown>[] }>;
|
||||
}
|
||||
|
||||
function toRegistry(row: Record<string, unknown>): {
|
||||
id: string;
|
||||
name: string;
|
||||
url: string;
|
||||
config: unknown;
|
||||
createdAt: string;
|
||||
} {
|
||||
return {
|
||||
id: String(row.id),
|
||||
name: String(row.name),
|
||||
url: String(row.url),
|
||||
config: row.config,
|
||||
createdAt: new Date(row.created_at as string).toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export async function listRegistries(db: PoolLike, ownerSub: string) {
|
||||
const res = await db.query(
|
||||
"SELECT id, owner_sub, name, url, config, created_at FROM registries WHERE owner_sub = $1 ORDER BY created_at DESC",
|
||||
[ownerSub],
|
||||
);
|
||||
return res.rows.map(toRegistry);
|
||||
}
|
||||
|
||||
export async function createRegistry(
|
||||
db: PoolLike,
|
||||
ownerSub: string,
|
||||
input: { name: string; url: string; config?: unknown },
|
||||
) {
|
||||
const res = await db.query(
|
||||
"INSERT INTO registries (owner_sub, name, url, config) VALUES ($1, $2, $3, $4::jsonb) RETURNING id, owner_sub, name, url, config, created_at",
|
||||
[ownerSub, input.name, input.url, JSON.stringify(input.config ?? {})],
|
||||
);
|
||||
return toRegistry(res.rows[0]);
|
||||
}
|
||||
|
||||
export async function getRegistry(db: PoolLike, ownerSub: string, id: string) {
|
||||
const res = await db.query(
|
||||
"SELECT id, owner_sub, name, url, config, created_at FROM registries WHERE owner_sub = $1 AND id = $2",
|
||||
[ownerSub, id],
|
||||
);
|
||||
return res.rows[0] ? toRegistry(res.rows[0]) : null;
|
||||
}
|
||||
Reference in New Issue
Block a user