UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

53 lines (52 loc) 3.08 kB
import { i as registerSecretValueForRedaction } from "./secret-redaction-registry-BOLC6DkF.js"; import { a as getNodeSqliteKysely, i as executeSqliteQueryTakeFirstSync, r as executeSqliteQuerySync } from "./kysely-sync-COmh4HWh.js"; import { C as ensureConfigRevisionKeySchema, s as runOpenClawStateWriteTransaction } from "./openclaw-state-db-BRTnL-D8.js"; import { createHmac, randomBytes } from "node:crypto"; //#region src/gateway/config-revision-token.ts const CONFIG_REVISION_SINGLETON_ID = 1; const CONFIG_REVISION_KEY_BYTES = 32; const CONFIG_REVISION_RAW_DOMAIN = "openclaw.gateway.config-revision.raw.v1"; const CONFIG_REVISION_RESOLVED_DOMAIN = "openclaw.gateway.config-revision.resolved.v1"; function registerConfigRevisionKeyForRedaction(key) { const bytes = Buffer.from(key); registerSecretValueForRedaction(bytes.toString("hex")); registerSecretValueForRedaction(bytes.toString("base64url")); } function parseConfigRevisionKey(row) { if (!(row.hmac_key instanceof Uint8Array) || row.hmac_key.byteLength !== CONFIG_REVISION_KEY_BYTES) throw new Error("config revision key is corrupt"); const key = Buffer.from(row.hmac_key); registerConfigRevisionKeyForRedaction(key); return key; } function loadOrCreateConfigRevisionKey(database, candidateKey) { const db = getNodeSqliteKysely(database); const existing = executeSqliteQueryTakeFirstSync(database, db.selectFrom("config_revision_keys").select("hmac_key").where("id", "=", CONFIG_REVISION_SINGLETON_ID)); if (existing) return parseConfigRevisionKey(existing); executeSqliteQuerySync(database, db.insertInto("config_revision_keys").values({ id: CONFIG_REVISION_SINGLETON_ID, hmac_key: candidateKey }).onConflict((conflict) => conflict.column("id").doNothing())); const stored = executeSqliteQueryTakeFirstSync(database, db.selectFrom("config_revision_keys").select("hmac_key").where("id", "=", CONFIG_REVISION_SINGLETON_ID)); if (!stored) throw new Error("config revision key could not be created"); return parseConfigRevisionKey(stored); } function projectRevision(key, domain, hash) { return `hmac-sha256:v1:${createHmac("sha256", key).update(JSON.stringify([domain, hash]), "utf8").digest("base64url")}`; } function createGatewayConfigRevisionProjector(key) { if (key.byteLength !== CONFIG_REVISION_KEY_BYTES) throw new Error("config revision key must be 32 bytes"); return { projectRawHash: (hash) => projectRevision(key, CONFIG_REVISION_RAW_DOMAIN, hash), projectResolvedHash: (hash) => projectRevision(key, CONFIG_REVISION_RESOLVED_DOMAIN, hash) }; } /** Loads the durable installation key once for the Gateway request lifecycle. */ function loadGatewayConfigRevisionProjector(options = {}) { const candidateKey = randomBytes(CONFIG_REVISION_KEY_BYTES); return runOpenClawStateWriteTransaction(({ db }) => { ensureConfigRevisionKeySchema(db); return createGatewayConfigRevisionProjector(loadOrCreateConfigRevisionKey(db, candidateKey)); }, options, { operationLabel: "gateway.config-revision-key.load" }); } //#endregion export { loadGatewayConfigRevisionProjector as t };