sc-dev-deploy/lib/constants.js

87 lines
2.9 KiB
JavaScript

// Compile-time constants for the dev-deploy plugin.
const PLUGIN_NAME = "dev-deploy";
const PLUGIN_VERSION = "0.0.7";
// Namespace UUID for deterministic IDs derived from (kind, name).
// Generated once via crypto.randomUUID() and frozen here forever.
// Two environments that bootstrap from the same metadata population
// will assign identical UUIDs to entities with the same (kind, name).
const ID_NAMESPACE = "8b3a1e0d-4f6c-4d2a-9c5b-7e8f9a0b1c2d";
const OP_SCHEMA_VERSION = 1;
// The ONLY global _sc_config keys dev-deploy syncs. One source of truth for both
// the journalling side (wrap.js only records set_config ops for these keys) and
// the apply side (applySetConfig refuses any other key), so a compromised peer
// cannot write security-relevant config it was never meant to touch (e.g.
// disable_csrf_routes, custom HTML headers, SMTP creds).
const SYNCABLE_CONFIG_KEYS = [
"menu_items",
"site_name",
"site_logo_id",
"base_url"
];
const DATA_MODES = {
MANAGED: "managed",
STARTER: "starter",
USER: "user"
};
// 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).
// The admin UI already refuses to manage `users` (routes.js); the apply AND revert
// sides must refuse it too, since a malicious authenticated peer never goes through
// the UI. One source of truth for every enforcement point.
const ROW_SYNC_LOCKED_TABLES = ["users"];
const DESTRUCTIVE_POLICY = {
AUTO: "auto",
CONFIRM: "confirm",
REFUSE: "refuse"
};
// Entity kinds the plugin tracks. Children point at parents via parent_uuid.
const ENTITY_KINDS = {
TABLE: "table",
FIELD: "field",
VIEW: "view",
PAGE: "page",
TRIGGER: "trigger",
ROLE: "role",
LIBRARY: "library",
TAG: "tag",
CONSTRAINT: "constraint",
FILE: "file",
PAGE_GROUP: "page_group",
PAGE_GROUP_MEMBER: "page_group_member",
WORKFLOW_STEP: "workflow_step"
};
// Files don't have a meaningful integer id in current Saltcorn (File.create
// doesn't insert into _sc_files anymore — files are identified by their disk
// location and metadata via xattrs). We derive a stable 31-bit int from the
// location string so files fit the existing UNIQUE(kind, current_id) shape of
// _dd_entity_ids without a schema change.
const fileLocationToId = (location) => {
const crypto = require("crypto");
const hash = crypto.createHash("sha256").update(String(location)).digest();
return hash.readUInt32BE(0) & 0x7FFFFFFF;
};
module.exports = {
PLUGIN_NAME,
PLUGIN_VERSION,
ID_NAMESPACE,
OP_SCHEMA_VERSION,
SYNCABLE_CONFIG_KEYS,
DATA_MODES,
ROW_SYNC_LOCKED_TABLES,
DESTRUCTIVE_POLICY,
ENTITY_KINDS,
fileLocationToId
};