Governed substrate for autonomous agents: scoped identity (passports), audited actions, MCP workspace. Infra IPs and secrets redacted for public release.
71 lines
2.1 KiB
JavaScript
71 lines
2.1 KiB
JavaScript
// ADR-0001 / ADR-0003 — doc status as relation (_doc_statuses, table id cached by name).
|
|
// Registries have both a legacy `status` (text/select) and a canonical `status_id`
|
|
// (relation → _doc_statuses). This helper resolves slug ↔ row id so backend
|
|
// writers keep both in sync until the legacy column is retired.
|
|
|
|
import { dbAll, dbGet } from '../../database/connection.js';
|
|
|
|
const BDD_SPACE_ID = 11;
|
|
let statusTableIdCache = null;
|
|
const slugToId = new Map();
|
|
const idToSlug = new Map();
|
|
let loadedAt = 0;
|
|
const TTL_MS = 5 * 60_000;
|
|
|
|
async function ensureStatusTableId() {
|
|
if (statusTableIdCache) return statusTableIdCache;
|
|
const row = await dbGet(`
|
|
SELECT ut.id FROM universal_tables ut
|
|
JOIN projects p ON p.id = ut.project_id
|
|
WHERE p.space_id = ? AND ut.name = '_doc_statuses' LIMIT 1
|
|
`, [BDD_SPACE_ID]);
|
|
statusTableIdCache = row?.id || null;
|
|
return statusTableIdCache;
|
|
}
|
|
|
|
async function refresh(force = false) {
|
|
if (!force && Date.now() - loadedAt < TTL_MS && slugToId.size > 0) return;
|
|
const tid = await ensureStatusTableId();
|
|
if (!tid) return;
|
|
const rows = await dbAll(`SELECT id, data FROM table_rows WHERE table_id = ?`, [tid]);
|
|
slugToId.clear();
|
|
idToSlug.clear();
|
|
for (const r of rows) {
|
|
const data = typeof r.data === 'string' ? JSON.parse(r.data) : (r.data || {});
|
|
if (data.slug) {
|
|
slugToId.set(String(data.slug), r.id);
|
|
idToSlug.set(r.id, String(data.slug));
|
|
}
|
|
}
|
|
loadedAt = Date.now();
|
|
}
|
|
|
|
export async function getStatusesTableId() {
|
|
return ensureStatusTableId();
|
|
}
|
|
|
|
export async function resolveStatusId(slug) {
|
|
if (!slug) return null;
|
|
await refresh();
|
|
return slugToId.get(String(slug)) || null;
|
|
}
|
|
|
|
export async function resolveStatusSlug(id) {
|
|
if (!id) return null;
|
|
await refresh();
|
|
return idToSlug.get(Number(id)) || null;
|
|
}
|
|
|
|
export async function hasStatusIdColumn(registryTableId) {
|
|
const col = await dbGet(
|
|
`SELECT id FROM table_columns WHERE table_id = ? AND column_name = 'status_id' LIMIT 1`,
|
|
[registryTableId]
|
|
);
|
|
return !!col;
|
|
}
|
|
|
|
export function invalidateStatusCache() {
|
|
slugToId.clear();
|
|
idToSlug.clear();
|
|
loadedAt = 0;
|
|
}
|