funifier-mcp 0.3.10 → 0.3.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.cursor/rules/funifier.mdc +1 -0
- package/.github/copilot-instructions.md +1 -0
- package/AGENTS.md +46 -1
- package/README.md +13 -2
- package/datasource-funifier-docs/.coverage.json +1 -1
- package/dist/cli/config-writers.d.ts +3 -3
- package/dist/cli/config-writers.d.ts.map +1 -1
- package/dist/cli/config-writers.js +22 -24
- package/dist/cli/config-writers.js.map +1 -1
- package/dist/cli/config-writers.test.js +7 -2
- package/dist/cli/config-writers.test.js.map +1 -1
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +19 -11
- package/dist/cli/init.js.map +1 -1
- package/dist/cli/init.test.js +46 -0
- package/dist/cli/init.test.js.map +1 -1
- package/dist/core/api-client.d.ts +4 -0
- package/dist/core/api-client.d.ts.map +1 -1
- package/dist/core/api-client.js +23 -0
- package/dist/core/api-client.js.map +1 -1
- package/dist/mcp/bundle.js +110 -107
- package/dist/mcp/tools/_backup.d.ts +89 -0
- package/dist/mcp/tools/_backup.d.ts.map +1 -0
- package/dist/mcp/tools/_backup.js +325 -0
- package/dist/mcp/tools/_backup.js.map +1 -0
- package/dist/mcp/tools/_backup.test.d.ts +2 -0
- package/dist/mcp/tools/_backup.test.d.ts.map +1 -0
- package/dist/mcp/tools/_backup.test.js +342 -0
- package/dist/mcp/tools/_backup.test.js.map +1 -0
- package/dist/mcp/tools/database.d.ts.map +1 -1
- package/dist/mcp/tools/database.js +14 -0
- package/dist/mcp/tools/database.js.map +1 -1
- package/dist/mcp/tools/database.test.js +40 -0
- package/dist/mcp/tools/database.test.js.map +1 -1
- package/dist/mcp/tools/list-tools.d.ts.map +1 -1
- package/dist/mcp/tools/list-tools.js +3 -2
- package/dist/mcp/tools/list-tools.js.map +1 -1
- package/dist/mcp/tools/permissions.d.ts.map +1 -1
- package/dist/mcp/tools/permissions.js +231 -4
- package/dist/mcp/tools/permissions.js.map +1 -1
- package/dist/mcp/tools/permissions.test.js +562 -12
- package/dist/mcp/tools/permissions.test.js.map +1 -1
- package/package.json +1 -1
- package/skills/funifier/references/configure-security.md +18 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Internal backup chokepoint for `funifier_permissions`.
|
|
3
|
+
*
|
|
4
|
+
* Every mutating permission branch hands a complete pre-image {@link BackupSnapshot}
|
|
5
|
+
* to {@link captureBackup} BEFORE issuing its remote write. If the write to disk
|
|
6
|
+
* throws, the caller's try/catch aborts the mutation — that is the deterministic,
|
|
7
|
+
* LLM-independent "back up first" guarantee. Restore is the inverse: read a snapshot,
|
|
8
|
+
* then {@link applySnapshot} reapplies the captured state (or removes a resource that
|
|
9
|
+
* did not exist before).
|
|
10
|
+
*/
|
|
11
|
+
export type BackupCategory = "security" | "studio-role" | "studio-assignment";
|
|
12
|
+
export interface RoleNaturalKey {
|
|
13
|
+
name: string;
|
|
14
|
+
type: string;
|
|
15
|
+
item: string;
|
|
16
|
+
}
|
|
17
|
+
export interface AssignmentKey {
|
|
18
|
+
type: string;
|
|
19
|
+
item: string;
|
|
20
|
+
role: string;
|
|
21
|
+
}
|
|
22
|
+
export interface BackupSnapshot {
|
|
23
|
+
version: 1;
|
|
24
|
+
/** Originating action, e.g. "delete_studio_role". */
|
|
25
|
+
action: string;
|
|
26
|
+
category: BackupCategory;
|
|
27
|
+
/** security._id | role _id/name | "type:item:role". */
|
|
28
|
+
resourceId: string;
|
|
29
|
+
/** Recorded so restore-to-absent can resolve the server `_id` (studio-role) or rebuild the unassign payload. */
|
|
30
|
+
naturalKey?: RoleNaturalKey | AssignmentKey;
|
|
31
|
+
/** false => the original op created the resource (restore = remove it). */
|
|
32
|
+
existedBefore: boolean;
|
|
33
|
+
capturedAt: string;
|
|
34
|
+
/** Best-effort, from ApiHolder. */
|
|
35
|
+
serverUrl: string | null;
|
|
36
|
+
/** Full prior state; null when existedBefore=false. */
|
|
37
|
+
preImage: unknown | null;
|
|
38
|
+
}
|
|
39
|
+
export interface BackupListItem {
|
|
40
|
+
path: string;
|
|
41
|
+
category: BackupCategory;
|
|
42
|
+
resourceId: string;
|
|
43
|
+
action: string;
|
|
44
|
+
capturedAt: string;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Root directory for snapshots. Honors `FUNIFIER_BACKUP_ROOT` so tests (and operators
|
|
48
|
+
* with a preferred location) can redirect writes without touching the working tree.
|
|
49
|
+
* Falls back to `<FUNIFIER_PROJECT_ROOT or cwd>/.funifier/backups`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function backupRoot(): string;
|
|
52
|
+
/** Resolve and validate that `raw` points inside `root` (blocks path traversal). */
|
|
53
|
+
export declare function resolveBackupPath(raw: string, root?: string): string;
|
|
54
|
+
/**
|
|
55
|
+
* Coerce any `_id` representation the API may return into a canonical string.
|
|
56
|
+
* Use ONLY for backup filenames / `resourceId` — never as the write payload's `_id`.
|
|
57
|
+
*/
|
|
58
|
+
export declare function normalizeSecurityId(id: unknown): string;
|
|
59
|
+
/**
|
|
60
|
+
* Writes `<dir>/.gitignore` with `*` when missing so snapshots (which may contain
|
|
61
|
+
* app_secret) stay out of git even when the project root .gitignore was never updated.
|
|
62
|
+
*/
|
|
63
|
+
export declare function ensureSelfIgnore(dir: string): void;
|
|
64
|
+
/**
|
|
65
|
+
* Serialize a snapshot to `<root>/<category>/<safeId>-<timestamp>.json` and return the
|
|
66
|
+
* absolute path. Synchronous so call sites need not await. **Throws** on any mkdir/write/
|
|
67
|
+
* serialization failure — this throw is the abort signal that prevents the remote mutation.
|
|
68
|
+
*/
|
|
69
|
+
export declare function captureBackup(snapshot: BackupSnapshot, root?: string): string;
|
|
70
|
+
/**
|
|
71
|
+
* Writes the snapshot, re-reads it from disk, and asserts the persisted bytes match.
|
|
72
|
+
* For security snapshots, also asserts `apps` and `roles` arrays are present unless
|
|
73
|
+
* `skipContentCheck` is true — used by restore's own pre-backup where the live
|
|
74
|
+
* document may already be truncated and a content check would block recovery.
|
|
75
|
+
* Throws on any write/read-back/validation failure — callers must abort the mutation.
|
|
76
|
+
*/
|
|
77
|
+
export declare function captureBackupVerified(snapshot: BackupSnapshot, root?: string, { skipContentCheck }?: {
|
|
78
|
+
skipContentCheck?: boolean;
|
|
79
|
+
}): string;
|
|
80
|
+
/** Recursively read every `*.json` snapshot under `root`, newest-first. Skips unreadable files. */
|
|
81
|
+
export declare function listSnapshots(root?: string): BackupListItem[];
|
|
82
|
+
/** Read and zod-validate a snapshot. Throws on missing, corrupt, or schema-invalid files. */
|
|
83
|
+
export declare function readSnapshot(filePath: string): BackupSnapshot;
|
|
84
|
+
/**
|
|
85
|
+
* Reapply a snapshot's prior state ("make reality match preImage"): when `existedBefore`
|
|
86
|
+
* reapply the captured payload; otherwise remove the resource the original op created.
|
|
87
|
+
*/
|
|
88
|
+
export declare function applySnapshot(api: any, snapshot: BackupSnapshot): Promise<unknown>;
|
|
89
|
+
//# sourceMappingURL=_backup.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_backup.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/_backup.ts"],"names":[],"mappings":"AAIA;;;;;;;;;GASG;AAEH,MAAM,MAAM,cAAc,GAAG,UAAU,GAAG,aAAa,GAAG,mBAAmB,CAAC;AAE9E,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,CAAC,CAAC;IACX,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,cAAc,CAAC;IACzB,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,gHAAgH;IAChH,UAAU,CAAC,EAAE,cAAc,GAAG,aAAa,CAAC;IAC5C,2EAA2E;IAC3E,aAAa,EAAE,OAAO,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,mCAAmC;IACnC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,uDAAuD;IACvD,QAAQ,EAAE,OAAO,GAAG,IAAI,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,cAAc,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAGnC;AAED,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,GAAE,MAAqB,GAAG,MAAM,CAOlF;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,EAAE,EAAE,OAAO,GAAG,MAAM,CAYvD;AAcD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAKlD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,cAAc,EAAE,IAAI,GAAE,MAAqB,GAAG,MAAM,CAgB3F;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,cAAc,EACxB,IAAI,GAAE,MAAqB,EAC3B,EAAE,gBAAwB,EAAE,GAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAO,GAChE,MAAM,CAwBR;AA4CD,mGAAmG;AACnG,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAAqB,GAAG,cAAc,EAAE,CAqB3E;AAED,6FAA6F;AAC7F,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,cAAc,CAI7D;AA4ID;;;GAGG;AACH,wBAAsB,aAAa,CAAC,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC,CAWxF"}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.backupRoot = backupRoot;
|
|
7
|
+
exports.resolveBackupPath = resolveBackupPath;
|
|
8
|
+
exports.normalizeSecurityId = normalizeSecurityId;
|
|
9
|
+
exports.ensureSelfIgnore = ensureSelfIgnore;
|
|
10
|
+
exports.captureBackup = captureBackup;
|
|
11
|
+
exports.captureBackupVerified = captureBackupVerified;
|
|
12
|
+
exports.listSnapshots = listSnapshots;
|
|
13
|
+
exports.readSnapshot = readSnapshot;
|
|
14
|
+
exports.applySnapshot = applySnapshot;
|
|
15
|
+
const fs_1 = __importDefault(require("fs"));
|
|
16
|
+
const path_1 = __importDefault(require("path"));
|
|
17
|
+
const zod_1 = require("zod");
|
|
18
|
+
/**
|
|
19
|
+
* Root directory for snapshots. Honors `FUNIFIER_BACKUP_ROOT` so tests (and operators
|
|
20
|
+
* with a preferred location) can redirect writes without touching the working tree.
|
|
21
|
+
* Falls back to `<FUNIFIER_PROJECT_ROOT or cwd>/.funifier/backups`.
|
|
22
|
+
*/
|
|
23
|
+
function backupRoot() {
|
|
24
|
+
const projectRoot = process.env.FUNIFIER_PROJECT_ROOT ?? process.cwd();
|
|
25
|
+
return process.env.FUNIFIER_BACKUP_ROOT ?? path_1.default.join(projectRoot, ".funifier", "backups");
|
|
26
|
+
}
|
|
27
|
+
/** Resolve and validate that `raw` points inside `root` (blocks path traversal). */
|
|
28
|
+
function resolveBackupPath(raw, root = backupRoot()) {
|
|
29
|
+
const resolved = path_1.default.resolve(raw);
|
|
30
|
+
const resolvedRoot = path_1.default.resolve(root);
|
|
31
|
+
if (!resolved.startsWith(resolvedRoot + path_1.default.sep) && resolved !== resolvedRoot) {
|
|
32
|
+
throw new Error(`backup_path must be within ${resolvedRoot}; got ${raw}`);
|
|
33
|
+
}
|
|
34
|
+
return resolved;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Coerce any `_id` representation the API may return into a canonical string.
|
|
38
|
+
* Use ONLY for backup filenames / `resourceId` — never as the write payload's `_id`.
|
|
39
|
+
*/
|
|
40
|
+
function normalizeSecurityId(id) {
|
|
41
|
+
if (id === null || id === undefined) {
|
|
42
|
+
throw new Error("Security _id is null or undefined.");
|
|
43
|
+
}
|
|
44
|
+
if (typeof id === "string")
|
|
45
|
+
return id;
|
|
46
|
+
if (typeof id === "object") {
|
|
47
|
+
const obj = id;
|
|
48
|
+
if (typeof obj.$oid === "string")
|
|
49
|
+
return obj.$oid;
|
|
50
|
+
// Expanded BSON ObjectId or other object — derive a stable filesystem-safe token.
|
|
51
|
+
return JSON.stringify(id).replace(/[^A-Za-z0-9]/g, "_").slice(0, 40);
|
|
52
|
+
}
|
|
53
|
+
return String(id);
|
|
54
|
+
}
|
|
55
|
+
/** `resourceId` with filesystem-unsafe characters collapsed to `_`. */
|
|
56
|
+
function sanitizeId(resourceId) {
|
|
57
|
+
return resourceId.replace(/[^A-Za-z0-9._-]/g, "_");
|
|
58
|
+
}
|
|
59
|
+
/** ISO-8601 → compact `YYYYMMDDTHHmmssSSS` (sub-second precision avoids same-second collisions). */
|
|
60
|
+
function compactTimestamp(capturedAt) {
|
|
61
|
+
return capturedAt.replace(/[-:]/g, "").replace(/\.(\d{3})Z$/, "$1");
|
|
62
|
+
}
|
|
63
|
+
const SELF_IGNORE_CONTENT = "*\n";
|
|
64
|
+
/**
|
|
65
|
+
* Writes `<dir>/.gitignore` with `*` when missing so snapshots (which may contain
|
|
66
|
+
* app_secret) stay out of git even when the project root .gitignore was never updated.
|
|
67
|
+
*/
|
|
68
|
+
function ensureSelfIgnore(dir) {
|
|
69
|
+
const ignorePath = path_1.default.join(dir, ".gitignore");
|
|
70
|
+
if (!fs_1.default.existsSync(ignorePath)) {
|
|
71
|
+
fs_1.default.writeFileSync(ignorePath, SELF_IGNORE_CONTENT, "utf8");
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Serialize a snapshot to `<root>/<category>/<safeId>-<timestamp>.json` and return the
|
|
76
|
+
* absolute path. Synchronous so call sites need not await. **Throws** on any mkdir/write/
|
|
77
|
+
* serialization failure — this throw is the abort signal that prevents the remote mutation.
|
|
78
|
+
*/
|
|
79
|
+
function captureBackup(snapshot, root = backupRoot()) {
|
|
80
|
+
fs_1.default.mkdirSync(root, { recursive: true });
|
|
81
|
+
ensureSelfIgnore(root);
|
|
82
|
+
const dir = path_1.default.join(root, snapshot.category);
|
|
83
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
84
|
+
const safeId = sanitizeId(normalizeSecurityId(snapshot.resourceId));
|
|
85
|
+
const timestamp = compactTimestamp(snapshot.capturedAt);
|
|
86
|
+
let filePath = path_1.default.join(dir, `${safeId}-${timestamp}.json`);
|
|
87
|
+
if (fs_1.default.existsSync(filePath)) {
|
|
88
|
+
filePath = path_1.default.join(dir, `${safeId}-${timestamp}-${Date.now()}.json`);
|
|
89
|
+
}
|
|
90
|
+
fs_1.default.writeFileSync(filePath, JSON.stringify(snapshot, null, 2), "utf8");
|
|
91
|
+
return filePath;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Writes the snapshot, re-reads it from disk, and asserts the persisted bytes match.
|
|
95
|
+
* For security snapshots, also asserts `apps` and `roles` arrays are present unless
|
|
96
|
+
* `skipContentCheck` is true — used by restore's own pre-backup where the live
|
|
97
|
+
* document may already be truncated and a content check would block recovery.
|
|
98
|
+
* Throws on any write/read-back/validation failure — callers must abort the mutation.
|
|
99
|
+
*/
|
|
100
|
+
function captureBackupVerified(snapshot, root = backupRoot(), { skipContentCheck = false } = {}) {
|
|
101
|
+
const filePath = captureBackup(snapshot, root);
|
|
102
|
+
let readBack;
|
|
103
|
+
try {
|
|
104
|
+
readBack = readSnapshot(filePath);
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
throw new Error(`Backup integrity check failed: could not re-read snapshot at ${filePath}: ${error.message}`);
|
|
108
|
+
}
|
|
109
|
+
if (JSON.stringify(readBack.preImage) !== JSON.stringify(snapshot.preImage)) {
|
|
110
|
+
throw new Error(`Backup integrity check failed: read-back preImage differs from captured data at ${filePath}`);
|
|
111
|
+
}
|
|
112
|
+
if (!skipContentCheck && snapshot.category === "security") {
|
|
113
|
+
const pre = readBack.preImage;
|
|
114
|
+
if (!pre || !Array.isArray(pre.apps) || !Array.isArray(pre.roles)) {
|
|
115
|
+
throw new Error(`Backup integrity check failed: security snapshot at ${filePath} is missing 'apps' or 'roles' in preImage`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return filePath;
|
|
119
|
+
}
|
|
120
|
+
const roleNaturalKeySchema = zod_1.z.object({
|
|
121
|
+
name: zod_1.z.string(),
|
|
122
|
+
type: zod_1.z.string(),
|
|
123
|
+
item: zod_1.z.string(),
|
|
124
|
+
});
|
|
125
|
+
const assignmentKeySchema = zod_1.z.object({
|
|
126
|
+
type: zod_1.z.string(),
|
|
127
|
+
item: zod_1.z.string(),
|
|
128
|
+
role: zod_1.z.string(),
|
|
129
|
+
});
|
|
130
|
+
const snapshotSchema = zod_1.z.object({
|
|
131
|
+
version: zod_1.z.literal(1),
|
|
132
|
+
action: zod_1.z.string(),
|
|
133
|
+
category: zod_1.z.enum(["security", "studio-role", "studio-assignment"]),
|
|
134
|
+
resourceId: zod_1.z.string(),
|
|
135
|
+
naturalKey: zod_1.z.union([roleNaturalKeySchema, assignmentKeySchema]).optional(),
|
|
136
|
+
existedBefore: zod_1.z.boolean(),
|
|
137
|
+
capturedAt: zod_1.z.string(),
|
|
138
|
+
serverUrl: zod_1.z.string().nullable(),
|
|
139
|
+
preImage: zod_1.z.unknown().nullable(),
|
|
140
|
+
});
|
|
141
|
+
/** Lenient header used for listing — tolerates files missing the full body. */
|
|
142
|
+
const snapshotHeaderSchema = zod_1.z.object({
|
|
143
|
+
category: zod_1.z.enum(["security", "studio-role", "studio-assignment"]),
|
|
144
|
+
resourceId: zod_1.z.string(),
|
|
145
|
+
action: zod_1.z.string(),
|
|
146
|
+
capturedAt: zod_1.z.string(),
|
|
147
|
+
});
|
|
148
|
+
function walkJsonFiles(dir) {
|
|
149
|
+
const out = [];
|
|
150
|
+
for (const entry of fs_1.default.readdirSync(dir, { withFileTypes: true })) {
|
|
151
|
+
const full = path_1.default.join(dir, entry.name);
|
|
152
|
+
if (entry.isDirectory())
|
|
153
|
+
out.push(...walkJsonFiles(full));
|
|
154
|
+
else if (entry.isFile() && entry.name.endsWith(".json"))
|
|
155
|
+
out.push(full);
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
/** Recursively read every `*.json` snapshot under `root`, newest-first. Skips unreadable files. */
|
|
160
|
+
function listSnapshots(root = backupRoot()) {
|
|
161
|
+
if (!fs_1.default.existsSync(root))
|
|
162
|
+
return [];
|
|
163
|
+
const items = [];
|
|
164
|
+
for (const filePath of walkJsonFiles(root)) {
|
|
165
|
+
try {
|
|
166
|
+
const parsed = JSON.parse(fs_1.default.readFileSync(filePath, "utf8"));
|
|
167
|
+
const header = snapshotHeaderSchema.parse(parsed);
|
|
168
|
+
items.push({
|
|
169
|
+
path: filePath,
|
|
170
|
+
category: header.category,
|
|
171
|
+
resourceId: header.resourceId,
|
|
172
|
+
action: header.action,
|
|
173
|
+
capturedAt: header.capturedAt,
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
catch {
|
|
177
|
+
console.warn(`Skipping corrupt/invalid snapshot: ${filePath}`);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return items.sort((a, b) => b.capturedAt.localeCompare(a.capturedAt));
|
|
181
|
+
}
|
|
182
|
+
/** Read and zod-validate a snapshot. Throws on missing, corrupt, or schema-invalid files. */
|
|
183
|
+
function readSnapshot(filePath) {
|
|
184
|
+
const raw = fs_1.default.readFileSync(filePath, "utf8");
|
|
185
|
+
const parsed = JSON.parse(raw);
|
|
186
|
+
return snapshotSchema.parse(parsed);
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Compare two `_id` values semantically:
|
|
190
|
+
* - Both strings → direct equality.
|
|
191
|
+
* - Both objects → structural equality via JSON.stringify.
|
|
192
|
+
* - String vs BSON $oid object → compare string against the $oid hex value.
|
|
193
|
+
* - Other mixed types (unresolvable) → return false (abort restore).
|
|
194
|
+
*/
|
|
195
|
+
function securityIdsMatch(liveId, preImageId) {
|
|
196
|
+
if (typeof liveId === "string" && typeof preImageId === "string")
|
|
197
|
+
return liveId === preImageId;
|
|
198
|
+
if (typeof liveId === "object" && liveId !== null && typeof preImageId === "object" && preImageId !== null) {
|
|
199
|
+
return JSON.stringify(liveId) === JSON.stringify(preImageId);
|
|
200
|
+
}
|
|
201
|
+
// One side is a string, the other an object — normalize $oid for comparison.
|
|
202
|
+
const objSide = typeof liveId === "object" ? liveId : preImageId;
|
|
203
|
+
const strSide = typeof liveId === "string" ? liveId : preImageId;
|
|
204
|
+
if (typeof strSide === "string" && objSide !== null && typeof objSide === "object") {
|
|
205
|
+
const oid = objSide.$oid;
|
|
206
|
+
if (typeof oid === "string")
|
|
207
|
+
return strSide === oid;
|
|
208
|
+
}
|
|
209
|
+
// Other mixed types — cannot determine canonical equivalence; abort.
|
|
210
|
+
return false;
|
|
211
|
+
}
|
|
212
|
+
async function applySecuritySnapshot(api, snapshot) {
|
|
213
|
+
const preImage = snapshot.preImage;
|
|
214
|
+
if (!preImage || preImage._id === undefined || preImage._id === null) {
|
|
215
|
+
throw new Error("Security snapshot has no restorable pre-image.");
|
|
216
|
+
}
|
|
217
|
+
// Critical #2: require apps[] and roles[] — a snapshot without them could truncate the document.
|
|
218
|
+
if (!Array.isArray(preImage.apps) || !Array.isArray(preImage.roles)) {
|
|
219
|
+
throw new Error("Security snapshot pre-image is missing 'apps' or 'roles' arrays. " +
|
|
220
|
+
"Refusing to apply a malformed snapshot that could truncate the security document.");
|
|
221
|
+
}
|
|
222
|
+
// Read live doc — try $toString aggregate first (guarantees a string _id), fall back to plain read.
|
|
223
|
+
let live;
|
|
224
|
+
if (typeof api.aggregateCollection === "function") {
|
|
225
|
+
try {
|
|
226
|
+
const docs = await api.aggregateCollection("security", [
|
|
227
|
+
{ $addFields: { _id: { $toString: "$_id" } } },
|
|
228
|
+
{ $limit: 1 },
|
|
229
|
+
]);
|
|
230
|
+
if (Array.isArray(docs) && docs.length > 0 && docs[0]?._id)
|
|
231
|
+
live = docs[0];
|
|
232
|
+
}
|
|
233
|
+
catch {
|
|
234
|
+
// fall through to queryCollection
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
if (!live) {
|
|
238
|
+
const docs = await api.queryCollection("security", {}, { limit: 1, skip: 0 });
|
|
239
|
+
live = Array.isArray(docs) ? docs[0] : undefined;
|
|
240
|
+
}
|
|
241
|
+
if (!live || live._id === undefined || live._id === null) {
|
|
242
|
+
throw new Error("Security document not found in collection 'security'.");
|
|
243
|
+
}
|
|
244
|
+
// Resolve live _id to a real string — never accept a synthetic token derived from JSON.stringify.
|
|
245
|
+
// Mirrors the contract of funifier-studio SecurityFormCtrl: _id is the gamification API key string.
|
|
246
|
+
let liveIdStr;
|
|
247
|
+
if (typeof live._id === "string") {
|
|
248
|
+
liveIdStr = live._id;
|
|
249
|
+
}
|
|
250
|
+
else if (typeof live._id === "object" && typeof live._id.$oid === "string") {
|
|
251
|
+
// BSON extended-JSON shape { "$oid": "<hex>" } — extract the hex string.
|
|
252
|
+
liveIdStr = live._id.$oid;
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
// $toString aggregate did not run or failed and plain read returned an unresolvable _id.
|
|
256
|
+
// Writing a synthetic token as _id would corrupt the security document — abort.
|
|
257
|
+
throw new Error(`Cannot restore security snapshot: live _id is not a string (got type '${typeof live._id}') ` +
|
|
258
|
+
`and $toString aggregate did not resolve it. Refusing to write a synthetic _id.`);
|
|
259
|
+
}
|
|
260
|
+
// High #1: explicit type guard — preImage._id must be a string or a BSON {$oid} object.
|
|
261
|
+
// securityIdsMatch handles these cases, but a guard here gives a deterministic, readable error
|
|
262
|
+
// rather than silently returning false for unresolvable shapes.
|
|
263
|
+
const pid = preImage._id;
|
|
264
|
+
if (typeof pid !== "string" && !(typeof pid === "object" && pid !== null && typeof pid.$oid === "string")) {
|
|
265
|
+
throw new Error(`Security snapshot _id has unresolvable type ('${typeof pid}'). Cannot safely compare with live document; refusing to restore.`);
|
|
266
|
+
}
|
|
267
|
+
if (!securityIdsMatch(liveIdStr, preImage._id)) {
|
|
268
|
+
const preStr = normalizeSecurityId(preImage._id);
|
|
269
|
+
throw new Error(`Security document _id mismatch (snapshot '${preStr}' vs live '${liveIdStr}'). Refusing to restore a divergent document.`);
|
|
270
|
+
}
|
|
271
|
+
// Write the pre-image back with the verified real string _id.
|
|
272
|
+
// normalizeSecurityId MUST NOT be used here — it can produce synthetic tokens from BSON objects.
|
|
273
|
+
return api.updateDocument("security", { ...preImage, _id: liveIdStr });
|
|
274
|
+
}
|
|
275
|
+
async function applyStudioRoleSnapshot(api, snapshot) {
|
|
276
|
+
if (snapshot.existedBefore) {
|
|
277
|
+
if (!snapshot.preImage)
|
|
278
|
+
throw new Error("Studio-role snapshot marked existedBefore but has no pre-image.");
|
|
279
|
+
return api.saveRole(snapshot.preImage);
|
|
280
|
+
}
|
|
281
|
+
// The original op created the role, so there is no captured `_id`. Resolve it now,
|
|
282
|
+
// while the role still exists, by matching the natural key — then delete.
|
|
283
|
+
const naturalKey = snapshot.naturalKey;
|
|
284
|
+
if (!naturalKey || !naturalKey.name) {
|
|
285
|
+
throw new Error("Cannot restore studio role to absent without a natural key.");
|
|
286
|
+
}
|
|
287
|
+
const roles = await api.listRoles();
|
|
288
|
+
const matches = roles.filter((role) => role.name === naturalKey.name && role.type === naturalKey.type && role.item === naturalKey.item);
|
|
289
|
+
if (matches.length > 1) {
|
|
290
|
+
throw new Error(`Ambiguous studio role natural key (${naturalKey.name}/${naturalKey.type}/${naturalKey.item}): ${matches.length} matches. Refusing to delete.`);
|
|
291
|
+
}
|
|
292
|
+
const match = matches[0];
|
|
293
|
+
if (!match || !match._id) {
|
|
294
|
+
return { ok: 1, note: "Role already absent; nothing to delete." };
|
|
295
|
+
}
|
|
296
|
+
return api.deleteRole(match._id);
|
|
297
|
+
}
|
|
298
|
+
async function applyStudioAssignmentSnapshot(api, snapshot) {
|
|
299
|
+
if (snapshot.existedBefore) {
|
|
300
|
+
if (!snapshot.preImage)
|
|
301
|
+
throw new Error("Assignment snapshot marked existedBefore but has no pre-image.");
|
|
302
|
+
return api.assignRole(snapshot.preImage);
|
|
303
|
+
}
|
|
304
|
+
const naturalKey = snapshot.naturalKey;
|
|
305
|
+
if (!naturalKey)
|
|
306
|
+
throw new Error("Cannot restore assignment to absent without a natural key.");
|
|
307
|
+
return api.unassignRole(naturalKey);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Reapply a snapshot's prior state ("make reality match preImage"): when `existedBefore`
|
|
311
|
+
* reapply the captured payload; otherwise remove the resource the original op created.
|
|
312
|
+
*/
|
|
313
|
+
async function applySnapshot(api, snapshot) {
|
|
314
|
+
switch (snapshot.category) {
|
|
315
|
+
case "security":
|
|
316
|
+
return applySecuritySnapshot(api, snapshot);
|
|
317
|
+
case "studio-role":
|
|
318
|
+
return applyStudioRoleSnapshot(api, snapshot);
|
|
319
|
+
case "studio-assignment":
|
|
320
|
+
return applyStudioAssignmentSnapshot(api, snapshot);
|
|
321
|
+
default:
|
|
322
|
+
throw new Error(`Unknown backup category: ${snapshot.category}`);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
//# sourceMappingURL=_backup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_backup.js","sourceRoot":"","sources":["../../../src/mcp/tools/_backup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_backup.test.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/_backup.test.ts"],"names":[],"mappings":""}
|