funifier-mcp 0.3.17 → 0.3.19
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 +3 -1
- package/.github/copilot-instructions.md +3 -1
- package/AGENTS.md +3 -1
- package/CHANGELOG.md +59 -0
- package/README.md +1 -1
- package/datasource-funifier-docs/.coverage.json +15 -5
- package/datasource-funifier-docs/.validation.json +77 -36
- package/datasource-funifier-docs/knowledge/guides/aggregates.md +13 -6
- package/datasource-funifier-docs/knowledge/guides/permission-audit.md +229 -0
- package/datasource-funifier-docs/knowledge/index.md +3 -2
- package/dist/cli/init.d.ts.map +1 -1
- package/dist/cli/init.js +3 -1
- package/dist/cli/init.js.map +1 -1
- package/dist/core/api-client.d.ts +2 -0
- package/dist/core/api-client.d.ts.map +1 -1
- package/dist/core/api-client.js +98 -47
- package/dist/core/api-client.js.map +1 -1
- package/dist/core/api-client.test.js +27 -0
- package/dist/core/api-client.test.js.map +1 -1
- package/dist/core/constants.d.ts +4 -0
- package/dist/core/constants.d.ts.map +1 -1
- package/dist/core/constants.js +8 -0
- package/dist/core/constants.js.map +1 -1
- package/dist/core/logger.d.ts +9 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +50 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/mcp/api-holder.test.d.ts +2 -0
- package/dist/mcp/api-holder.test.d.ts.map +1 -0
- package/dist/mcp/api-holder.test.js +45 -0
- package/dist/mcp/api-holder.test.js.map +1 -0
- package/dist/mcp/bundle.js +108 -105
- package/dist/mcp/check-update.d.ts +9 -0
- package/dist/mcp/check-update.d.ts.map +1 -1
- package/dist/mcp/check-update.js +35 -9
- package/dist/mcp/check-update.js.map +1 -1
- package/dist/mcp/check-update.test.js +36 -6
- package/dist/mcp/check-update.test.js.map +1 -1
- package/dist/mcp/doc-path.d.ts +11 -0
- package/dist/mcp/doc-path.d.ts.map +1 -0
- package/dist/mcp/doc-path.js +66 -0
- package/dist/mcp/doc-path.js.map +1 -0
- package/dist/mcp/doc-path.test.d.ts +2 -0
- package/dist/mcp/doc-path.test.d.ts.map +1 -0
- package/dist/mcp/doc-path.test.js +77 -0
- package/dist/mcp/doc-path.test.js.map +1 -0
- package/dist/mcp/index.js +19 -0
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/resources/documentation.d.ts.map +1 -1
- package/dist/mcp/resources/documentation.js +7 -3
- package/dist/mcp/resources/documentation.js.map +1 -1
- package/dist/mcp/tools/_audit.d.ts +103 -0
- package/dist/mcp/tools/_audit.d.ts.map +1 -0
- package/dist/mcp/tools/_audit.js +241 -0
- package/dist/mcp/tools/_audit.js.map +1 -0
- package/dist/mcp/tools/_audit.test.d.ts +2 -0
- package/dist/mcp/tools/_audit.test.d.ts.map +1 -0
- package/dist/mcp/tools/_audit.test.js +412 -0
- package/dist/mcp/tools/_audit.test.js.map +1 -0
- package/dist/mcp/tools/_backup.d.ts +37 -3
- package/dist/mcp/tools/_backup.d.ts.map +1 -1
- package/dist/mcp/tools/_backup.js +142 -11
- package/dist/mcp/tools/_backup.js.map +1 -1
- package/dist/mcp/tools/_backup.test.js +195 -0
- package/dist/mcp/tools/_backup.test.js.map +1 -1
- package/dist/mcp/tools/_char-guard.d.ts +2 -1
- package/dist/mcp/tools/_char-guard.d.ts.map +1 -1
- package/dist/mcp/tools/_char-guard.js +10 -3
- package/dist/mcp/tools/_char-guard.js.map +1 -1
- package/dist/mcp/tools/_fetch-current.d.ts +2 -1
- package/dist/mcp/tools/_fetch-current.d.ts.map +1 -1
- package/dist/mcp/tools/_fetch-current.js +2 -74
- package/dist/mcp/tools/_fetch-current.js.map +1 -1
- package/dist/mcp/tools/_registry.d.ts +183 -0
- package/dist/mcp/tools/_registry.d.ts.map +1 -0
- package/dist/mcp/tools/_registry.js +88 -0
- package/dist/mcp/tools/_registry.js.map +1 -0
- package/dist/mcp/tools/_registry.test.d.ts +2 -0
- package/dist/mcp/tools/_registry.test.d.ts.map +1 -0
- package/dist/mcp/tools/_registry.test.js +103 -0
- package/dist/mcp/tools/_registry.test.js.map +1 -0
- package/dist/mcp/tools/_scope-engine.d.ts +40 -0
- package/dist/mcp/tools/_scope-engine.d.ts.map +1 -0
- package/dist/mcp/tools/_scope-engine.js +197 -0
- package/dist/mcp/tools/_scope-engine.js.map +1 -0
- package/dist/mcp/tools/_scope-engine.test.d.ts +2 -0
- package/dist/mcp/tools/_scope-engine.test.d.ts.map +1 -0
- package/dist/mcp/tools/_scope-engine.test.js +241 -0
- package/dist/mcp/tools/_scope-engine.test.js.map +1 -0
- package/dist/mcp/tools/database.d.ts +4 -0
- package/dist/mcp/tools/database.d.ts.map +1 -1
- package/dist/mcp/tools/database.js +23 -4
- package/dist/mcp/tools/database.js.map +1 -1
- package/dist/mcp/tools/database.test.js +19 -0
- package/dist/mcp/tools/database.test.js.map +1 -1
- package/dist/mcp/tools/delete.d.ts.map +1 -1
- package/dist/mcp/tools/delete.js +3 -98
- package/dist/mcp/tools/delete.js.map +1 -1
- package/dist/mcp/tools/execute.d.ts.map +1 -1
- package/dist/mcp/tools/execute.js +36 -4
- package/dist/mcp/tools/execute.js.map +1 -1
- package/dist/mcp/tools/execute.test.d.ts +2 -0
- package/dist/mcp/tools/execute.test.d.ts.map +1 -0
- package/dist/mcp/tools/execute.test.js +87 -0
- package/dist/mcp/tools/execute.test.js.map +1 -0
- package/dist/mcp/tools/get.d.ts.map +1 -1
- package/dist/mcp/tools/get.js +4 -93
- package/dist/mcp/tools/get.js.map +1 -1
- package/dist/mcp/tools/index.d.ts.map +1 -1
- package/dist/mcp/tools/index.js +42 -1
- package/dist/mcp/tools/index.js.map +1 -1
- package/dist/mcp/tools/list.d.ts.map +1 -1
- package/dist/mcp/tools/list.js +3 -91
- package/dist/mcp/tools/list.js.map +1 -1
- package/dist/mcp/tools/logs.d.ts.map +1 -1
- package/dist/mcp/tools/logs.js +5 -3
- package/dist/mcp/tools/logs.js.map +1 -1
- package/dist/mcp/tools/permissions.d.ts.map +1 -1
- package/dist/mcp/tools/permissions.js +68 -11
- package/dist/mcp/tools/permissions.js.map +1 -1
- package/dist/mcp/tools/permissions.test.js +268 -4
- package/dist/mcp/tools/permissions.test.js.map +1 -1
- package/dist/mcp/tools/read-doc.d.ts.map +1 -1
- package/dist/mcp/tools/read-doc.js +10 -28
- package/dist/mcp/tools/read-doc.js.map +1 -1
- package/dist/mcp/tools/save.d.ts.map +1 -1
- package/dist/mcp/tools/save.js +4 -81
- package/dist/mcp/tools/save.js.map +1 -1
- package/package.json +3 -2
- package/skills/funifier/SKILL.md +3 -1
- package/skills/funifier/references/audit-permissions.md +97 -0
- package/skills/funifier/references/configure-security.md +6 -0
- package/skills/funifier/references/create-action.md +7 -0
- package/skills/funifier/references/create-aggregate.md +99 -79
- package/skills/funifier/references/create-audit.md +8 -0
- package/skills/funifier/references/create-challenge.md +7 -0
- package/skills/funifier/references/create-competition.md +7 -0
- package/skills/funifier/references/create-crossword.md +6 -0
- package/skills/funifier/references/create-custom-object.md +6 -0
- package/skills/funifier/references/create-custom-page.md +6 -0
- package/skills/funifier/references/create-folder.md +7 -0
- package/skills/funifier/references/create-lastmile.md +6 -0
- package/skills/funifier/references/create-leaderboard.md +6 -0
- package/skills/funifier/references/create-level.md +7 -0
- package/skills/funifier/references/create-lottery.md +7 -0
- package/skills/funifier/references/create-mystery.md +6 -0
- package/skills/funifier/references/create-notification.md +6 -0
- package/skills/funifier/references/create-point.md +7 -0
- package/skills/funifier/references/create-quiz.md +7 -0
- package/skills/funifier/references/create-scheduler.md +6 -0
- package/skills/funifier/references/create-story.md +6 -0
- package/skills/funifier/references/create-swap.md +6 -0
- package/skills/funifier/references/create-trigger.md +8 -0
- package/skills/funifier/references/create-virtual-good.md +6 -0
- package/skills/funifier/references/create-webhook.md +6 -0
- package/skills/funifier/references/create-websocket.md +6 -0
- package/skills/funifier/references/create-widget.md +6 -0
- package/skills/funifier/references/date-handling.md +6 -0
- package/skills/funifier/references/debug.md +6 -0
- package/skills/funifier/references/help.md +6 -0
- package/skills/funifier/references/implement-frontend.md +7 -0
- package/skills/funifier/references/import-csv.md +6 -0
- package/skills/funifier/references/manage-indexes.md +6 -0
- package/skills/funifier/references/manage-player.md +7 -0
- package/skills/funifier/references/manage-team.md +6 -0
- package/skills/funifier/references/query-aggregate.md +111 -0
- package/skills/funifier/references/upload-file.md +6 -0
- package/datasource-funifier-docs/.search-index.json +0 -58758
- package/datasource-funifier-docs/.skills-map.json +0 -141
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Pure authorization engine mirroring SecurityFilter.doFilter from funifier-service.
|
|
4
|
+
* No I/O, no imports beyond types — fully unit-testable against a transcribed table.
|
|
5
|
+
*
|
|
6
|
+
* Source: SecurityFilter.java (funifier-service)
|
|
7
|
+
* Each rule carries a line reference so source drift can be detected via validate:skills claims.
|
|
8
|
+
*/
|
|
9
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
|
+
exports.MANUAL_REVIEW_TOKENS = void 0;
|
|
11
|
+
exports.entityFull = entityFull;
|
|
12
|
+
exports.verbFor = verbFor;
|
|
13
|
+
exports.isPublicPath = isPublicPath;
|
|
14
|
+
exports.evaluateScope = evaluateScope;
|
|
15
|
+
exports.usedTokens = usedTokens;
|
|
16
|
+
/**
|
|
17
|
+
* Non-path-auditable tokens: their usage cannot be proven or disproven from a path manifest.
|
|
18
|
+
* These are always classified `manual-review`, never `excess`.
|
|
19
|
+
*/
|
|
20
|
+
exports.MANUAL_REVIEW_TOKENS = new Set([
|
|
21
|
+
"cross_domain",
|
|
22
|
+
"read_encrypted_field_values",
|
|
23
|
+
"read_encrypted_player_password",
|
|
24
|
+
"write_upload",
|
|
25
|
+
]);
|
|
26
|
+
// SecurityFilter.java:108-151: paths that bypass the scope check entirely.
|
|
27
|
+
// GET /v3/widget, /v3/global, /v3/system/global require no scope.
|
|
28
|
+
// NOTE: this list is hardcoded by mirroring SecurityFilter source; validate via sourceClaims.
|
|
29
|
+
const PUBLIC_GET_PREFIXES = ["/v3/widget", "/v3/global", "/v3/system/global"];
|
|
30
|
+
/** SecurityFilter.java:85-86: strip "/v3/", replace "/" → "_". */
|
|
31
|
+
function entityFull(path) {
|
|
32
|
+
const clean = path.split("?")[0];
|
|
33
|
+
const withoutV3 = clean.startsWith("/v3/") ? clean.slice(4) : clean.replace(/^\//, "");
|
|
34
|
+
return withoutV3.replace(/\//g, "_");
|
|
35
|
+
}
|
|
36
|
+
/** SecurityFilter.java:226-227: GET→read, POST/PUT→write, else lowercase. */
|
|
37
|
+
function verbFor(method) {
|
|
38
|
+
if (method === "GET")
|
|
39
|
+
return "read";
|
|
40
|
+
if (method === "POST" || method === "PUT")
|
|
41
|
+
return "write";
|
|
42
|
+
return method.toLowerCase();
|
|
43
|
+
}
|
|
44
|
+
/** SecurityFilter.java:108-151: true when the path requires no scope. */
|
|
45
|
+
function isPublicPath(method, path) {
|
|
46
|
+
const clean = path.split("?")[0];
|
|
47
|
+
if (method === "GET") {
|
|
48
|
+
for (const prefix of PUBLIC_GET_PREFIXES) {
|
|
49
|
+
if (clean === prefix || clean.startsWith(prefix + "/"))
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
/** SecurityFilter.java:223-224: remove spaces, split on comma, drop empty tokens. */
|
|
56
|
+
function normalizeScope(scope) {
|
|
57
|
+
return scope.replace(/ /g, "").split(",").filter(Boolean);
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Evaluate whether `scope` authorizes `method` on `path`, reproducing the exact decision
|
|
61
|
+
* tree of SecurityFilter.doFilter.
|
|
62
|
+
*/
|
|
63
|
+
function evaluateScope(scope, method, path) {
|
|
64
|
+
const cleanPath = path.split("?")[0];
|
|
65
|
+
// SecurityFilter.java:108-151: public-path bypass
|
|
66
|
+
if (isPublicPath(method, cleanPath)) {
|
|
67
|
+
return { allowed: true, rule: "public-path", requiredTokens: [] };
|
|
68
|
+
}
|
|
69
|
+
const verb = verbFor(method);
|
|
70
|
+
const entity = entityFull(cleanPath);
|
|
71
|
+
const tokens = normalizeScope(scope);
|
|
72
|
+
const isDatabase = cleanPath === "/v3/database" || cleanPath.startsWith("/v3/database/");
|
|
73
|
+
// SecurityFilter.java:259-263: special POST exceptions (checked before grammar)
|
|
74
|
+
if (method === "POST") {
|
|
75
|
+
if (cleanPath === "/v3/action/log") {
|
|
76
|
+
if (tokens.includes("write_actionlog")) {
|
|
77
|
+
return {
|
|
78
|
+
allowed: true,
|
|
79
|
+
rule: "special-actionlog",
|
|
80
|
+
matchedToken: "write_actionlog",
|
|
81
|
+
requiredTokens: ["write_actionlog"],
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// write_actionlog absent — falls through to grammar
|
|
85
|
+
}
|
|
86
|
+
if (cleanPath === "/v3/mobile/device") {
|
|
87
|
+
// Any non-empty scope passes (SecurityFilter.java:262-263)
|
|
88
|
+
if (tokens.length > 0) {
|
|
89
|
+
return { allowed: true, rule: "special-mobile-device", matchedToken: tokens[0], requiredTokens: [] };
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// SecurityFilter.java:230-253: grammar allow rules — {verb}_all, exact, fallback m1, m2
|
|
94
|
+
let grammarAllowed = false;
|
|
95
|
+
let grammarRule = "denied";
|
|
96
|
+
let grammarToken;
|
|
97
|
+
let grammarRequired = [];
|
|
98
|
+
// 1. {verb}_all (SecurityFilter.java:230)
|
|
99
|
+
const verbAll = `${verb}_all`;
|
|
100
|
+
if (tokens.includes(verbAll)) {
|
|
101
|
+
grammarAllowed = true;
|
|
102
|
+
grammarRule = "all";
|
|
103
|
+
grammarToken = verbAll;
|
|
104
|
+
grammarRequired = [verbAll];
|
|
105
|
+
}
|
|
106
|
+
// 2. Exact: {verb}_{entity_full} (SecurityFilter.java:234)
|
|
107
|
+
if (!grammarAllowed) {
|
|
108
|
+
const exactToken = `${verb}_${entity}`;
|
|
109
|
+
if (tokens.includes(exactToken)) {
|
|
110
|
+
grammarAllowed = true;
|
|
111
|
+
grammarRule = "exact";
|
|
112
|
+
grammarToken = exactToken;
|
|
113
|
+
grammarRequired = [exactToken];
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// 3. Fallback minus-1: {verb}_{prefix}_all (SecurityFilter.java:238-246, allow_full_m1)
|
|
117
|
+
if (!grammarAllowed) {
|
|
118
|
+
const segs = entity.split("_");
|
|
119
|
+
if (segs.length > 1) {
|
|
120
|
+
const m1Token = `${verb}_${segs.slice(0, -1).join("_")}_all`;
|
|
121
|
+
if (tokens.includes(m1Token)) {
|
|
122
|
+
grammarAllowed = true;
|
|
123
|
+
grammarRule = "fallback-m1";
|
|
124
|
+
grammarToken = m1Token;
|
|
125
|
+
grammarRequired = [m1Token];
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// 4. Fallback minus-2: {verb}_{prefix}_all (SecurityFilter.java:247-253, allow_full_m2)
|
|
130
|
+
// Code stops at m2 despite the "menos n" comment — confirmed at source.
|
|
131
|
+
if (!grammarAllowed) {
|
|
132
|
+
const segs = entity.split("_");
|
|
133
|
+
if (segs.length > 2) {
|
|
134
|
+
const m2Token = `${verb}_${segs.slice(0, -2).join("_")}_all`;
|
|
135
|
+
if (tokens.includes(m2Token)) {
|
|
136
|
+
grammarAllowed = true;
|
|
137
|
+
grammarRule = "fallback-m2";
|
|
138
|
+
grammarToken = m2Token;
|
|
139
|
+
grammarRequired = [m2Token];
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
// DatabaseRest.java: every /v3/database handler additionally requires the literal
|
|
144
|
+
// "database" scope token regardless of which grammar rule would otherwise allow it.
|
|
145
|
+
// Applies to ALL verbs including GET — verified at all 13 DatabaseRest check sites.
|
|
146
|
+
if (isDatabase) {
|
|
147
|
+
if (grammarAllowed && !tokens.includes("database")) {
|
|
148
|
+
return {
|
|
149
|
+
allowed: false,
|
|
150
|
+
rule: "database-keyword-missing",
|
|
151
|
+
matchedToken: grammarToken,
|
|
152
|
+
requiredTokens: [...grammarRequired, "database"],
|
|
153
|
+
};
|
|
154
|
+
}
|
|
155
|
+
if (grammarAllowed) {
|
|
156
|
+
return {
|
|
157
|
+
allowed: true,
|
|
158
|
+
rule: grammarRule,
|
|
159
|
+
matchedToken: grammarToken,
|
|
160
|
+
requiredTokens: [...grammarRequired, "database"],
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
// Grammar denied on a database path: suggest exact token + database keyword
|
|
164
|
+
return {
|
|
165
|
+
allowed: false,
|
|
166
|
+
rule: "denied",
|
|
167
|
+
requiredTokens: [`${verb}_${entity}`, "database"],
|
|
168
|
+
};
|
|
169
|
+
}
|
|
170
|
+
if (grammarAllowed) {
|
|
171
|
+
return { allowed: true, rule: grammarRule, matchedToken: grammarToken, requiredTokens: grammarRequired };
|
|
172
|
+
}
|
|
173
|
+
return { allowed: false, rule: "denied", requiredTokens: [`${verb}_${entity}`] };
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Returns the subset of tokens in `scope` that actually authorized at least one entry
|
|
177
|
+
* in `entries`. Used for excess-token calculation in the audit diff.
|
|
178
|
+
*/
|
|
179
|
+
function usedTokens(scope, entries) {
|
|
180
|
+
const tokens = normalizeScope(scope);
|
|
181
|
+
const used = new Set();
|
|
182
|
+
for (const entry of entries) {
|
|
183
|
+
const decision = evaluateScope(scope, entry.method, entry.path);
|
|
184
|
+
if (decision.allowed) {
|
|
185
|
+
if (decision.matchedToken)
|
|
186
|
+
used.add(decision.matchedToken);
|
|
187
|
+
// "database" is a co-required token for /v3/database paths — mark it used too
|
|
188
|
+
const cleanPath = entry.path.split("?")[0];
|
|
189
|
+
if ((cleanPath === "/v3/database" || cleanPath.startsWith("/v3/database/")) &&
|
|
190
|
+
tokens.includes("database")) {
|
|
191
|
+
used.add("database");
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
return used;
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=_scope-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_scope-engine.js","sourceRoot":"","sources":["../../../src/mcp/tools/_scope-engine.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_scope-engine.test.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/_scope-engine.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const vitest_1 = require("vitest");
|
|
4
|
+
const _scope_engine_1 = require("./_scope-engine");
|
|
5
|
+
// ─── entityFull ───────────────────────────────────────────────────────────────
|
|
6
|
+
(0, vitest_1.describe)("entityFull", () => {
|
|
7
|
+
(0, vitest_1.it)("strips /v3/ and replaces / with _", () => {
|
|
8
|
+
(0, vitest_1.expect)((0, _scope_engine_1.entityFull)("/v3/database/mycoll/aggregate")).toBe("database_mycoll_aggregate");
|
|
9
|
+
(0, vitest_1.expect)((0, _scope_engine_1.entityFull)("/v3/action/log")).toBe("action_log");
|
|
10
|
+
(0, vitest_1.expect)((0, _scope_engine_1.entityFull)("/v3/game")).toBe("game");
|
|
11
|
+
(0, vitest_1.expect)((0, _scope_engine_1.entityFull)("/v3/game/level/experience")).toBe("game_level_experience");
|
|
12
|
+
});
|
|
13
|
+
(0, vitest_1.it)("strips query string before processing", () => {
|
|
14
|
+
(0, vitest_1.expect)((0, _scope_engine_1.entityFull)("/v3/action/log?limit=10")).toBe("action_log");
|
|
15
|
+
});
|
|
16
|
+
});
|
|
17
|
+
// ─── verbFor ─────────────────────────────────────────────────────────────────
|
|
18
|
+
(0, vitest_1.describe)("verbFor (SecurityFilter.java:226-227)", () => {
|
|
19
|
+
(0, vitest_1.it)("maps GET → read", () => (0, vitest_1.expect)((0, _scope_engine_1.verbFor)("GET")).toBe("read"));
|
|
20
|
+
(0, vitest_1.it)("maps POST → write", () => (0, vitest_1.expect)((0, _scope_engine_1.verbFor)("POST")).toBe("write"));
|
|
21
|
+
(0, vitest_1.it)("maps PUT → write", () => (0, vitest_1.expect)((0, _scope_engine_1.verbFor)("PUT")).toBe("write"));
|
|
22
|
+
(0, vitest_1.it)("maps DELETE → delete", () => (0, vitest_1.expect)((0, _scope_engine_1.verbFor)("DELETE")).toBe("delete"));
|
|
23
|
+
(0, vitest_1.it)("lowercases other methods", () => (0, vitest_1.expect)((0, _scope_engine_1.verbFor)("PATCH")).toBe("patch"));
|
|
24
|
+
});
|
|
25
|
+
// ─── isPublicPath ─────────────────────────────────────────────────────────────
|
|
26
|
+
(0, vitest_1.describe)("isPublicPath (SecurityFilter.java:108-151)", () => {
|
|
27
|
+
(0, vitest_1.it)("GET /v3/widget is public", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("GET", "/v3/widget")).toBe(true));
|
|
28
|
+
(0, vitest_1.it)("GET /v3/widget/my-widget is public (prefix match)", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("GET", "/v3/widget/my-widget")).toBe(true));
|
|
29
|
+
(0, vitest_1.it)("GET /v3/global is public", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("GET", "/v3/global")).toBe(true));
|
|
30
|
+
(0, vitest_1.it)("GET /v3/system/global is public", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("GET", "/v3/system/global")).toBe(true));
|
|
31
|
+
(0, vitest_1.it)("POST /v3/widget is NOT public (method mismatch)", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("POST", "/v3/widget")).toBe(false));
|
|
32
|
+
(0, vitest_1.it)("GET /v3/game is not a public path", () => (0, vitest_1.expect)((0, _scope_engine_1.isPublicPath)("GET", "/v3/game")).toBe(false));
|
|
33
|
+
});
|
|
34
|
+
// ─── evaluateScope — grammar rules ───────────────────────────────────────────
|
|
35
|
+
(0, vitest_1.describe)("evaluateScope — public-path bypass", () => {
|
|
36
|
+
(0, vitest_1.it)("allows GET /v3/widget regardless of scope", () => {
|
|
37
|
+
const d = (0, _scope_engine_1.evaluateScope)("", "GET", "/v3/widget");
|
|
38
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
39
|
+
(0, vitest_1.expect)(d.rule).toBe("public-path");
|
|
40
|
+
});
|
|
41
|
+
(0, vitest_1.it)("allows GET /v3/global regardless of scope", () => {
|
|
42
|
+
const d = (0, _scope_engine_1.evaluateScope)("", "GET", "/v3/global");
|
|
43
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
44
|
+
(0, vitest_1.expect)(d.rule).toBe("public-path");
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
(0, vitest_1.describe)("evaluateScope — _all rule (SecurityFilter.java:230)", () => {
|
|
48
|
+
(0, vitest_1.it)("read_all allows GET on any non-database path", () => {
|
|
49
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all", "GET", "/v3/game/level");
|
|
50
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
51
|
+
(0, vitest_1.expect)(d.rule).toBe("all");
|
|
52
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("read_all");
|
|
53
|
+
});
|
|
54
|
+
(0, vitest_1.it)("write_all allows POST on any non-database path", () => {
|
|
55
|
+
const d = (0, _scope_engine_1.evaluateScope)("write_all", "POST", "/v3/action/log");
|
|
56
|
+
// /v3/action/log POST: write_actionlog fires first — but write_all doesn't include write_actionlog, so grammar fires
|
|
57
|
+
// Actually write_all should be checked in grammar, but /v3/action/log is a special POST:
|
|
58
|
+
// write_actionlog is checked first; if not present, grammar runs. write_all would match grammar.
|
|
59
|
+
// BUT wait: the special-actionlog check only fires when write_actionlog IS present.
|
|
60
|
+
// So with scope=write_all, grammar check runs: write_all → allowed via "all" rule.
|
|
61
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
62
|
+
(0, vitest_1.expect)(d.rule).toBe("all");
|
|
63
|
+
});
|
|
64
|
+
(0, vitest_1.it)("delete_all allows DELETE on any non-database path", () => {
|
|
65
|
+
const d = (0, _scope_engine_1.evaluateScope)("delete_all", "DELETE", "/v3/game/level");
|
|
66
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
67
|
+
(0, vitest_1.expect)(d.rule).toBe("all");
|
|
68
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("delete_all");
|
|
69
|
+
});
|
|
70
|
+
});
|
|
71
|
+
(0, vitest_1.describe)("evaluateScope — exact match (SecurityFilter.java:234)", () => {
|
|
72
|
+
(0, vitest_1.it)("read_action_log allows GET /v3/action/log", () => {
|
|
73
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_action_log", "GET", "/v3/action/log");
|
|
74
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
75
|
+
(0, vitest_1.expect)(d.rule).toBe("exact");
|
|
76
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("read_action_log");
|
|
77
|
+
});
|
|
78
|
+
(0, vitest_1.it)("write_game_level allows POST /v3/game/level", () => {
|
|
79
|
+
const d = (0, _scope_engine_1.evaluateScope)("write_game_level", "POST", "/v3/game/level");
|
|
80
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
81
|
+
(0, vitest_1.expect)(d.rule).toBe("exact");
|
|
82
|
+
});
|
|
83
|
+
(0, vitest_1.it)("denies when the exact token is absent", () => {
|
|
84
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_game", "GET", "/v3/game/level");
|
|
85
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
(0, vitest_1.describe)("evaluateScope — fallback minus-1 (allow_full_m1, SecurityFilter.java:238-246)", () => {
|
|
89
|
+
(0, vitest_1.it)("read_game_all allows GET /v3/game/level (entity=game_level, m1=game_all)", () => {
|
|
90
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_game_all", "GET", "/v3/game/level");
|
|
91
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
92
|
+
(0, vitest_1.expect)(d.rule).toBe("fallback-m1");
|
|
93
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("read_game_all");
|
|
94
|
+
});
|
|
95
|
+
(0, vitest_1.it)("read_game_level_all allows GET /v3/game/level/experience (m1=game_level_all)", () => {
|
|
96
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_game_level_all", "GET", "/v3/game/level/experience");
|
|
97
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
98
|
+
(0, vitest_1.expect)(d.rule).toBe("fallback-m1");
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
(0, vitest_1.describe)("evaluateScope — fallback minus-2 (allow_full_m2, SecurityFilter.java:247-253)", () => {
|
|
102
|
+
(0, vitest_1.it)("read_game_all allows GET /v3/game/level/experience (entity=game_level_experience, m2=game_all)", () => {
|
|
103
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_game_all", "GET", "/v3/game/level/experience");
|
|
104
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
105
|
+
(0, vitest_1.expect)(d.rule).toBe("fallback-m2");
|
|
106
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("read_game_all");
|
|
107
|
+
});
|
|
108
|
+
(0, vitest_1.it)("read_database_all does NOT authorize GET /v3/database/coll/find without database keyword (m2 denied first by db-keyword)", () => {
|
|
109
|
+
// read_database_all would be m1 for database_coll_find (entity has 3 segments)
|
|
110
|
+
// But /v3/database path requires "database" keyword regardless of grammar
|
|
111
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_database_all", "GET", "/v3/database/coll/find");
|
|
112
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
113
|
+
(0, vitest_1.expect)(d.rule).toBe("database-keyword-missing");
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
(0, vitest_1.describe)("evaluateScope — beyond minus-2 denied", () => {
|
|
117
|
+
(0, vitest_1.it)("read_a_all does NOT authorize GET /v3/a/b/c/d (entity=a_b_c_d, m2=a_b, no token)", () => {
|
|
118
|
+
// m1 would be read_a_b_c_all, m2 would be read_a_b_all — neither in scope
|
|
119
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_a_all", "GET", "/v3/a/b/c/d");
|
|
120
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
121
|
+
(0, vitest_1.expect)(d.rule).toBe("denied");
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
// ─── evaluateScope — special POST exceptions (SecurityFilter.java:259-263) ───
|
|
125
|
+
(0, vitest_1.describe)("evaluateScope — special POST exceptions", () => {
|
|
126
|
+
(0, vitest_1.it)("POST /v3/action/log with write_actionlog → special-actionlog (PSEC-06)", () => {
|
|
127
|
+
const d = (0, _scope_engine_1.evaluateScope)("write_actionlog", "POST", "/v3/action/log");
|
|
128
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
129
|
+
(0, vitest_1.expect)(d.rule).toBe("special-actionlog");
|
|
130
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("write_actionlog");
|
|
131
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("write_actionlog");
|
|
132
|
+
});
|
|
133
|
+
(0, vitest_1.it)("POST /v3/action/log without write_actionlog falls through to grammar (denied if no other token)", () => {
|
|
134
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all", "POST", "/v3/action/log");
|
|
135
|
+
// grammar: write_all not present, exact write_action_log not present... read_all is for GET.
|
|
136
|
+
// Actually: verb for POST is "write". write_all not in scope. exact write_action_log not in scope.
|
|
137
|
+
// Falls through → denied (read_all doesn't authorize write)
|
|
138
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
139
|
+
});
|
|
140
|
+
(0, vitest_1.it)("POST /v3/mobile/device with any non-empty scope → special-mobile-device", () => {
|
|
141
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all", "POST", "/v3/mobile/device");
|
|
142
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
143
|
+
(0, vitest_1.expect)(d.rule).toBe("special-mobile-device");
|
|
144
|
+
});
|
|
145
|
+
(0, vitest_1.it)("POST /v3/mobile/device with empty scope → denied (falls through to grammar)", () => {
|
|
146
|
+
const d = (0, _scope_engine_1.evaluateScope)("", "POST", "/v3/mobile/device");
|
|
147
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
// ─── evaluateScope — scope normalization (SecurityFilter.java:223-224) ────────
|
|
151
|
+
(0, vitest_1.describe)("evaluateScope — scope normalization", () => {
|
|
152
|
+
(0, vitest_1.it)("removes spaces before splitting (space-separated scope string)", () => {
|
|
153
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all, write_all", "GET", "/v3/game");
|
|
154
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
155
|
+
(0, vitest_1.expect)(d.matchedToken).toBe("read_all");
|
|
156
|
+
});
|
|
157
|
+
(0, vitest_1.it)("handles duplicate tokens without false denials", () => {
|
|
158
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_game,read_game,read_all", "GET", "/v3/game");
|
|
159
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
// ─── T6: database keyword rule (DatabaseRest.java, all 13 handler sites) ─────
|
|
163
|
+
(0, vitest_1.describe)("evaluateScope — database keyword (PSEC-07)", () => {
|
|
164
|
+
(0, vitest_1.it)("GET /v3/database/coll with read_all but without database keyword → database-keyword-missing", () => {
|
|
165
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all", "GET", "/v3/database/coll");
|
|
166
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
167
|
+
(0, vitest_1.expect)(d.rule).toBe("database-keyword-missing");
|
|
168
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("database");
|
|
169
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("read_all");
|
|
170
|
+
});
|
|
171
|
+
(0, vitest_1.it)("GET /v3/database/coll with read_all AND database keyword → allowed", () => {
|
|
172
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all,database", "GET", "/v3/database/coll");
|
|
173
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
174
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("database");
|
|
175
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("read_all");
|
|
176
|
+
});
|
|
177
|
+
(0, vitest_1.it)("POST /v3/database/coll with write_all but without database → database-keyword-missing", () => {
|
|
178
|
+
const d = (0, _scope_engine_1.evaluateScope)("write_all", "POST", "/v3/database/coll");
|
|
179
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
180
|
+
(0, vitest_1.expect)(d.rule).toBe("database-keyword-missing");
|
|
181
|
+
});
|
|
182
|
+
(0, vitest_1.it)("POST /v3/database/coll with write_all AND database → allowed", () => {
|
|
183
|
+
const d = (0, _scope_engine_1.evaluateScope)("write_all,database", "POST", "/v3/database/coll");
|
|
184
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
185
|
+
});
|
|
186
|
+
(0, vitest_1.it)("DELETE /v3/database/coll with delete_all AND database → allowed", () => {
|
|
187
|
+
const d = (0, _scope_engine_1.evaluateScope)("delete_all,database", "DELETE", "/v3/database/coll");
|
|
188
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
189
|
+
});
|
|
190
|
+
(0, vitest_1.it)("GET /v3/database/coll/aggregate denied when grammar itself denies (suggests entity token + database)", () => {
|
|
191
|
+
const d = (0, _scope_engine_1.evaluateScope)("database", "GET", "/v3/database/coll/aggregate");
|
|
192
|
+
(0, vitest_1.expect)(d.allowed).toBe(false);
|
|
193
|
+
(0, vitest_1.expect)(d.rule).toBe("denied");
|
|
194
|
+
(0, vitest_1.expect)(d.requiredTokens).toContain("database");
|
|
195
|
+
});
|
|
196
|
+
(0, vitest_1.it)("non-database path is unaffected by database keyword presence/absence", () => {
|
|
197
|
+
const d = (0, _scope_engine_1.evaluateScope)("read_all", "GET", "/v3/game");
|
|
198
|
+
(0, vitest_1.expect)(d.allowed).toBe(true);
|
|
199
|
+
(0, vitest_1.expect)(d.rule).not.toBe("database-keyword-missing");
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
// ─── T6: usedTokens ──────────────────────────────────────────────────────────
|
|
203
|
+
(0, vitest_1.describe)("usedTokens", () => {
|
|
204
|
+
(0, vitest_1.it)("returns empty set when no entries match", () => {
|
|
205
|
+
const used = (0, _scope_engine_1.usedTokens)("read_all", [{ method: "POST", path: "/v3/game" }]);
|
|
206
|
+
// POST needs write_* not read_*
|
|
207
|
+
(0, vitest_1.expect)(used.size).toBe(0);
|
|
208
|
+
});
|
|
209
|
+
(0, vitest_1.it)("attributes read_all when it authorizes a GET entry", () => {
|
|
210
|
+
const used = (0, _scope_engine_1.usedTokens)("read_all,write_all", [{ method: "GET", path: "/v3/game/level" }]);
|
|
211
|
+
(0, vitest_1.expect)(used.has("read_all")).toBe(true);
|
|
212
|
+
(0, vitest_1.expect)(used.has("write_all")).toBe(false);
|
|
213
|
+
});
|
|
214
|
+
(0, vitest_1.it)("attributes both grammar token and 'database' for /v3/database entries", () => {
|
|
215
|
+
const used = (0, _scope_engine_1.usedTokens)("read_all,database", [{ method: "GET", path: "/v3/database/coll" }]);
|
|
216
|
+
(0, vitest_1.expect)(used.has("read_all")).toBe(true);
|
|
217
|
+
(0, vitest_1.expect)(used.has("database")).toBe(true);
|
|
218
|
+
});
|
|
219
|
+
(0, vitest_1.it)("does not attribute database when path is not /v3/database", () => {
|
|
220
|
+
const used = (0, _scope_engine_1.usedTokens)("read_all,database", [{ method: "GET", path: "/v3/game" }]);
|
|
221
|
+
(0, vitest_1.expect)(used.has("database")).toBe(false);
|
|
222
|
+
});
|
|
223
|
+
(0, vitest_1.it)("handles multiple entries across different tokens", () => {
|
|
224
|
+
const used = (0, _scope_engine_1.usedTokens)("read_all,write_game,database", [
|
|
225
|
+
{ method: "GET", path: "/v3/game" },
|
|
226
|
+
{ method: "POST", path: "/v3/game" },
|
|
227
|
+
]);
|
|
228
|
+
(0, vitest_1.expect)(used.has("read_all")).toBe(true);
|
|
229
|
+
(0, vitest_1.expect)(used.has("write_game")).toBe(true);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
// ─── MANUAL_REVIEW_TOKENS ─────────────────────────────────────────────────────
|
|
233
|
+
(0, vitest_1.describe)("MANUAL_REVIEW_TOKENS", () => {
|
|
234
|
+
(0, vitest_1.it)("includes cross_domain, read_encrypted_field_values, read_encrypted_player_password, write_upload", () => {
|
|
235
|
+
(0, vitest_1.expect)(_scope_engine_1.MANUAL_REVIEW_TOKENS.has("cross_domain")).toBe(true);
|
|
236
|
+
(0, vitest_1.expect)(_scope_engine_1.MANUAL_REVIEW_TOKENS.has("read_encrypted_field_values")).toBe(true);
|
|
237
|
+
(0, vitest_1.expect)(_scope_engine_1.MANUAL_REVIEW_TOKENS.has("read_encrypted_player_password")).toBe(true);
|
|
238
|
+
(0, vitest_1.expect)(_scope_engine_1.MANUAL_REVIEW_TOKENS.has("write_upload")).toBe(true);
|
|
239
|
+
});
|
|
240
|
+
});
|
|
241
|
+
//# sourceMappingURL=_scope-engine.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_scope-engine.test.js","sourceRoot":"","sources":["../../../src/mcp/tools/_scope-engine.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
2
2
|
import { ApiHolder } from "../api-holder";
|
|
3
|
+
export declare function capAggregatePipeline(pipeline: unknown): {
|
|
4
|
+
pipeline: any[];
|
|
5
|
+
capped: boolean;
|
|
6
|
+
};
|
|
3
7
|
export declare function registerDatabaseTool(server: McpServer, apiHolder: ApiHolder): void;
|
|
4
8
|
//# sourceMappingURL=database.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/database.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/mcp/tools/database.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAQ1C,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,OAAO,GAAG;IAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IAAC,MAAM,EAAE,OAAO,CAAA;CAAE,CAS5F;AAsBD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,QAyP3E"}
|
|
@@ -1,8 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.capAggregatePipeline = capAggregatePipeline;
|
|
3
4
|
exports.registerDatabaseTool = registerDatabaseTool;
|
|
4
5
|
const zod_1 = require("zod");
|
|
5
6
|
const _char_guard_1 = require("./_char-guard");
|
|
7
|
+
const constants_1 = require("../../core/constants");
|
|
8
|
+
// Safety backstop: if an ad-hoc aggregate pipeline has no $limit stage anywhere,
|
|
9
|
+
// append one so a missing limit can't pull an unbounded result set. Returns the
|
|
10
|
+
// (possibly) augmented pipeline and whether the cap was injected, so the response
|
|
11
|
+
// can tell the agent to paginate explicitly with $skip/$limit.
|
|
12
|
+
function capAggregatePipeline(pipeline) {
|
|
13
|
+
if (!Array.isArray(pipeline)) {
|
|
14
|
+
return { pipeline: pipeline, capped: false };
|
|
15
|
+
}
|
|
16
|
+
const hasLimit = pipeline.some((stage) => stage && typeof stage === "object" && "$limit" in stage);
|
|
17
|
+
if (hasLimit)
|
|
18
|
+
return { pipeline, capped: false };
|
|
19
|
+
return { pipeline: [...pipeline, { $limit: constants_1.API.DEFAULT_AGGREGATE_LIMIT }], capped: true };
|
|
20
|
+
}
|
|
6
21
|
function pathLikeCollectionError(collection) {
|
|
7
22
|
if (!collection.includes("/"))
|
|
8
23
|
return null;
|
|
@@ -129,7 +144,7 @@ function registerDatabaseTool(server, apiHolder) {
|
|
|
129
144
|
skip: offset ?? 0,
|
|
130
145
|
});
|
|
131
146
|
const header = `Found ${results.length} document(s) in '${collection}':`;
|
|
132
|
-
return (0, _char_guard_1.applyCharGuard)(results, header);
|
|
147
|
+
return (0, _char_guard_1.applyCharGuard)(results, header, undefined, true);
|
|
133
148
|
}
|
|
134
149
|
if (action === "aggregate") {
|
|
135
150
|
if (!pipeline) {
|
|
@@ -139,10 +154,14 @@ function registerDatabaseTool(server, apiHolder) {
|
|
|
139
154
|
};
|
|
140
155
|
}
|
|
141
156
|
const pipelineArr = JSON.parse(pipeline);
|
|
142
|
-
const
|
|
157
|
+
const { pipeline: safePipeline, capped } = capAggregatePipeline(pipelineArr);
|
|
158
|
+
const results = await api.aggregateCollection(collection, safePipeline);
|
|
143
159
|
const docs = Array.isArray(results) ? results : [results];
|
|
144
|
-
const
|
|
145
|
-
|
|
160
|
+
const capNote = capped
|
|
161
|
+
? ` (no $limit in pipeline — auto-applied $limit:${constants_1.API.DEFAULT_AGGREGATE_LIMIT}; add an explicit $skip/$limit to paginate)`
|
|
162
|
+
: "";
|
|
163
|
+
const header = `Aggregate result (${docs.length} document(s)) from '${collection}'${capNote}:`;
|
|
164
|
+
return (0, _char_guard_1.applyCharGuard)(docs, header, undefined, true);
|
|
146
165
|
}
|
|
147
166
|
if (action === "insert") {
|
|
148
167
|
if (!data) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/mcp/tools/database.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/mcp/tools/database.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,7 +2,26 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const vitest_1 = require("vitest");
|
|
4
4
|
const database_1 = require("./database");
|
|
5
|
+
const constants_1 = require("../../core/constants");
|
|
5
6
|
const MAX_CHARS = 50000;
|
|
7
|
+
(0, vitest_1.describe)("capAggregatePipeline", () => {
|
|
8
|
+
(0, vitest_1.it)("appends a $limit backstop when the pipeline has none", () => {
|
|
9
|
+
const { pipeline, capped } = (0, database_1.capAggregatePipeline)([{ $match: { active: true } }]);
|
|
10
|
+
(0, vitest_1.expect)(capped).toBe(true);
|
|
11
|
+
(0, vitest_1.expect)(pipeline[pipeline.length - 1]).toEqual({ $limit: constants_1.API.DEFAULT_AGGREGATE_LIMIT });
|
|
12
|
+
});
|
|
13
|
+
(0, vitest_1.it)("leaves a pipeline with an explicit $limit untouched", () => {
|
|
14
|
+
const input = [{ $match: { active: true } }, { $limit: 5 }];
|
|
15
|
+
const { pipeline, capped } = (0, database_1.capAggregatePipeline)(input);
|
|
16
|
+
(0, vitest_1.expect)(capped).toBe(false);
|
|
17
|
+
(0, vitest_1.expect)(pipeline).toEqual(input);
|
|
18
|
+
});
|
|
19
|
+
(0, vitest_1.it)("does not mutate the original pipeline array", () => {
|
|
20
|
+
const input = [{ $match: {} }];
|
|
21
|
+
(0, database_1.capAggregatePipeline)(input);
|
|
22
|
+
(0, vitest_1.expect)(input).toHaveLength(1);
|
|
23
|
+
});
|
|
24
|
+
});
|
|
6
25
|
function makeHarness(fakeApi) {
|
|
7
26
|
const handlers = {};
|
|
8
27
|
const server = {
|