// Sync-policy constants: one source of truth for every enforcement point on both // sides of a sync. // The ONLY global _sc_config keys a deployer syncs. The capture side records / // ships only these and the apply side refuses any other key, so a compromised // peer cannot write security-relevant config it was never meant to touch // (disable_csrf_routes, custom HTML headers, SMTP creds). Per-environment // settings (base_url: links, OAuth callbacks, the idp issuer) are deliberately // absent. const SYNCABLE_CONFIG_KEYS = [ "menu_items", "site_name", "site_logo_id" ]; // User tables that must NEVER receive peer-synced rows and must never be // flipped into managed/starter mode, no matter what a peer sends. `users` is the // crown jewel: a synced row there is an injected account (role_id=1 => admin // takeover). Enforced on the apply (and revert) side, not just the UI, since a // hostile authenticated peer never goes through the UI. const ROW_SYNC_LOCKED_TABLES = ["users"]; // Per-table row-propagation modes. // user (default) -- rows belong to the target; sync never touches them. // starter -- rows ship once (initial seed), then the target owns them. // managed -- rows always converge from source; source is canonical. const DATA_MODES = { USER: "user", STARTER: "starter", MANAGED: "managed" }; // Plugin/system infrastructure: a table OR field whose name // begins with "_" is reserved by Saltcorn (_sc_*) and plugins (_dd_*, _ss_*, // _idp_*, the per-row identity columns _dd_row_uuid / _ss_row_uuid). Infra is // never journaled, synced, diffed, pruned, or offered a data mode. (Documented // limitation: an application table or field named with a leading underscore is // not synced.) const isInfraName = (name) => { return typeof name === "string" && name.startsWith("_"); }; const isLockedTable = (name) => { return ROW_SYNC_LOCKED_TABLES.includes(name); }; const isSyncedMode = (mode) => { return mode === DATA_MODES.MANAGED || mode === DATA_MODES.STARTER; }; module.exports = { SYNCABLE_CONFIG_KEYS, ROW_SYNC_LOCKED_TABLES, DATA_MODES, isInfraName, isLockedTable, isSyncedMode };