// This Saltcorn instance's dev-deploy identity (env_id, label, policies). // Stored as a singleton row in _dd_env. const db = require("@saltcorn/data/db"); const { randomUuid } = require("./ids"); const { DESTRUCTIVE_POLICY } = require("./constants"); // The env identity is schema-scoped, so a single process serving multiple // tenants must NOT share one cached row across them. Key the cache by tenant // schema (db.getTenantSchema()), not a module-level singleton. const cachedEnvByTenant = new Map(); const tenantKey = () => (db.getTenantSchema ? db.getTenantSchema() : "public"); const getEnv = async () => { const key = tenantKey(); if (cachedEnvByTenant.has(key)) { return cachedEnvByTenant.get(key); } const rows = await db.select("_dd_env", {}); const env = rows.length > 0 ? rows[0] : null; cachedEnvByTenant.set(key, env); return env; }; const refreshEnvCache = async () => { cachedEnvByTenant.delete(tenantKey()); return await getEnv(); }; const initEnvIfMissing = async () => { const existing = await getEnv(); if (existing) { return existing; } const now = new Date().toISOString(); const row = { env_id: randomUuid(), env_label: null, on_destructive_op: DESTRUCTIVE_POLICY.CONFIRM, require_tls: 0, created_at: now, bootstrapped_at: null }; await db.insert("_dd_env", row, { noid: true }); cachedEnvByTenant.set(tenantKey(), row); return row; }; const markBootstrapped = async (envId) => { const now = new Date().toISOString(); await db.updateWhere("_dd_env", { bootstrapped_at: now }, { env_id: envId }); const cached = cachedEnvByTenant.get(tenantKey()); if (cached && cached.env_id === envId) { cached.bootstrapped_at = now; } }; module.exports = { getEnv, initEnvIfMissing, markBootstrapped, refreshEnvCache };