@miragon/mcp-toolkit-core 2.4.1 → 2.6.0
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/README.md +1 -1
- package/dist/auth/caller.d.ts +55 -0
- package/dist/auth/caller.d.ts.map +1 -0
- package/dist/auth/caller.js +81 -0
- package/dist/auth/caller.js.map +1 -0
- package/dist/engine/pipeline-executor.d.ts +32 -4
- package/dist/engine/pipeline-executor.d.ts.map +1 -1
- package/dist/engine/pipeline-executor.js +22 -2
- package/dist/engine/pipeline-executor.js.map +1 -1
- package/dist/framework/catalogue.d.ts +2 -2
- package/dist/framework/render-view.d.ts +6 -4
- package/dist/framework/render-view.d.ts.map +1 -1
- package/dist/framework/render-view.js.map +1 -1
- package/dist/index.d.ts +5 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -1
- package/dist/index.js.map +1 -1
- package/dist/middleware/org-gate.d.ts +31 -7
- package/dist/middleware/org-gate.d.ts.map +1 -1
- package/dist/middleware/org-gate.js +9 -6
- package/dist/middleware/org-gate.js.map +1 -1
- package/dist/middleware/role-filter.d.ts +39 -7
- package/dist/middleware/role-filter.d.ts.map +1 -1
- package/dist/middleware/role-filter.js +24 -28
- package/dist/middleware/role-filter.js.map +1 -1
- package/dist/tools/create-framework-app.d.ts +12 -1
- package/dist/tools/create-framework-app.d.ts.map +1 -1
- package/dist/tools/create-framework-app.js +10 -5
- package/dist/tools/create-framework-app.js.map +1 -1
- package/dist/tools/dashboard-store.d.ts +83 -13
- package/dist/tools/dashboard-store.d.ts.map +1 -1
- package/dist/tools/dashboard-store.js +174 -73
- package/dist/tools/dashboard-store.js.map +1 -1
- package/dist/tools/index.d.ts +5 -3
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +1 -1
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/install-toolkit.d.ts +22 -1
- package/dist/tools/install-toolkit.d.ts.map +1 -1
- package/dist/tools/install-toolkit.js +15 -3
- package/dist/tools/install-toolkit.js.map +1 -1
- package/dist/tools/register-catalogue-tool.d.ts.map +1 -1
- package/dist/tools/register-catalogue-tool.js +2 -5
- package/dist/tools/register-catalogue-tool.js.map +1 -1
- package/dist/tools/register-dashboard-tools.d.ts +15 -3
- package/dist/tools/register-dashboard-tools.d.ts.map +1 -1
- package/dist/tools/register-dashboard-tools.js +120 -20
- package/dist/tools/register-dashboard-tools.js.map +1 -1
- package/dist/tools/register-framework-tools.d.ts.map +1 -1
- package/dist/tools/register-framework-tools.js +4 -6
- package/dist/tools/register-framework-tools.js.map +1 -1
- package/dist/tools/register-tool.d.ts +67 -9
- package/dist/tools/register-tool.d.ts.map +1 -1
- package/dist/tools/register-tool.js +17 -8
- package/dist/tools/register-tool.js.map +1 -1
- package/dist/tools/register-widget-tool.d.ts +46 -5
- package/dist/tools/register-widget-tool.d.ts.map +1 -1
- package/dist/tools/register-widget-tool.js +25 -27
- package/dist/tools/register-widget-tool.js.map +1 -1
- package/dist/tools/registrar-shared.d.ts +74 -0
- package/dist/tools/registrar-shared.d.ts.map +1 -0
- package/dist/tools/registrar-shared.js +32 -0
- package/dist/tools/registrar-shared.js.map +1 -0
- package/dist/tools/tool-name-guard.d.ts +37 -0
- package/dist/tools/tool-name-guard.d.ts.map +1 -0
- package/dist/tools/tool-name-guard.js +81 -0
- package/dist/tools/tool-name-guard.js.map +1 -0
- package/package.json +7 -7
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
* `ctx.params.name`. When no name is present it fails *open* by default
|
|
12
12
|
* (allow) — pass `failClosed: true` to deny instead.
|
|
13
13
|
*
|
|
14
|
+
* The caller's roles come from {@link resolveCaller}, which reads both mcp-use 2
|
|
15
|
+
* shapes — middleware receives the SDK `AuthInfo` with the provider-mapped user
|
|
16
|
+
* under `ctx.auth.extra.user`, never `ctx.auth.user`.
|
|
17
|
+
*
|
|
14
18
|
* Batches need no special handling: mcp-use invokes `mcp:tools/call`
|
|
15
19
|
* middleware once per call, so each entry of a JSON-RPC batch is guarded
|
|
16
20
|
* individually (verified against 2.0.4 — a two-entry batch fires the guard
|
|
@@ -26,41 +30,31 @@
|
|
|
26
30
|
* *unrestricted* access — this is deliberately opt-in so that adding a new
|
|
27
31
|
* role doesn't silently revoke anyone's tools.
|
|
28
32
|
*/
|
|
33
|
+
import { resolveCaller } from "../auth/caller.js";
|
|
34
|
+
const modulePrefixOf = (toolName) => toolName.split("_")[0] ?? "";
|
|
29
35
|
export function createRoleFilterMiddleware(roleToModules, opts = {}) {
|
|
30
36
|
const failClosed = opts.failClosed ?? false;
|
|
31
37
|
const hasRules = Object.keys(roleToModules).length > 0;
|
|
32
38
|
// Returns `null` = unrestricted (full access), array = restricted.
|
|
33
|
-
const allowedModulesFor = (
|
|
34
|
-
|
|
35
|
-
return null;
|
|
36
|
-
const roles = Array.isArray(user?.roles) ? user.roles : [];
|
|
37
|
-
const restrictedRoles = roles.filter((r) => r in roleToModules);
|
|
39
|
+
const allowedModulesFor = (caller) => {
|
|
40
|
+
const restrictedRoles = (caller?.roles ?? []).filter((r) => r in roleToModules);
|
|
38
41
|
if (restrictedRoles.length === 0)
|
|
39
42
|
return null;
|
|
40
43
|
return [...new Set(restrictedRoles.flatMap((r) => roleToModules[r] ?? []))];
|
|
41
44
|
};
|
|
45
|
+
// Tools without an underscore are framework/app-level and always allowed.
|
|
46
|
+
const isAllowed = (toolName, allowed) => !toolName.includes("_") || allowed.includes(modulePrefixOf(toolName));
|
|
42
47
|
const toolsList = async (ctx, next) => {
|
|
43
|
-
const
|
|
44
|
-
if (!hasRules || !Array.isArray(
|
|
45
|
-
return
|
|
46
|
-
const allowed = allowedModulesFor(ctx
|
|
48
|
+
const result = await next();
|
|
49
|
+
if (!hasRules || !Array.isArray(result))
|
|
50
|
+
return result;
|
|
51
|
+
const allowed = allowedModulesFor(resolveCaller(ctx));
|
|
47
52
|
if (allowed === null)
|
|
48
|
-
return
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
});
|
|
54
|
-
};
|
|
55
|
-
// Tools without an underscore are framework/app-level and always allowed.
|
|
56
|
-
const assertModuleAllowed = (toolName, allowed, user) => {
|
|
57
|
-
if (!toolName.includes("_"))
|
|
58
|
-
return;
|
|
59
|
-
const modulePrefix = toolName.split("_")[0] ?? "";
|
|
60
|
-
if (!allowed.includes(modulePrefix)) {
|
|
61
|
-
const userRoles = user?.roles ?? [];
|
|
62
|
-
throw new Error(`Access denied: role(s) "${userRoles.join(", ")}" have no access to module "${modulePrefix}".`);
|
|
63
|
-
}
|
|
53
|
+
return result;
|
|
54
|
+
// Filtering keeps the element type, so the narrowed array is still the
|
|
55
|
+
// chain's `TResult` — TypeScript just cannot carry that through
|
|
56
|
+
// `Array.isArray`.
|
|
57
|
+
return result.filter((tool) => typeof tool.name === "string" && isAllowed(tool.name, allowed));
|
|
64
58
|
};
|
|
65
59
|
const toolsCall = async (ctx, next) => {
|
|
66
60
|
if (!hasRules)
|
|
@@ -72,9 +66,11 @@ export function createRoleFilterMiddleware(roleToModules, opts = {}) {
|
|
|
72
66
|
}
|
|
73
67
|
return next();
|
|
74
68
|
}
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
|
|
69
|
+
const caller = resolveCaller(ctx);
|
|
70
|
+
const allowed = allowedModulesFor(caller);
|
|
71
|
+
if (allowed !== null && !isAllowed(name, allowed)) {
|
|
72
|
+
throw new Error(`Access denied: role(s) "${(caller?.roles ?? []).join(", ")}" have no access to module "${modulePrefixOf(name)}".`);
|
|
73
|
+
}
|
|
78
74
|
return next();
|
|
79
75
|
};
|
|
80
76
|
return { toolsList, toolsCall };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"role-filter.js","sourceRoot":"","sources":["../../src/middleware/role-filter.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"role-filter.js","sourceRoot":"","sources":["../../src/middleware/role-filter.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,6 +3,7 @@ import type { OAuthProvider } from "mcp-use/oauth";
|
|
|
3
3
|
import type { DashboardStore } from "./dashboard-store.js";
|
|
4
4
|
import type { AppConfig, AppPlugin } from "../types/index.js";
|
|
5
5
|
import type { AppResourceCsp } from "../types/meta.js";
|
|
6
|
+
import type { DuplicateToolNamePolicy } from "./tool-name-guard.js";
|
|
6
7
|
export interface CreateFrameworkAppOptionsBase {
|
|
7
8
|
name: string;
|
|
8
9
|
version?: string;
|
|
@@ -26,7 +27,11 @@ export interface CreateFrameworkAppOptionsBase {
|
|
|
26
27
|
serverOptions?: Omit<ServerConfig, "name" | "version" | "description" | "host" | "oauth">;
|
|
27
28
|
plugins: AppPlugin[];
|
|
28
29
|
middleware?: {
|
|
29
|
-
/**
|
|
30
|
+
/**
|
|
31
|
+
* When set, every RPC must come from a caller whose provider-mapped user
|
|
32
|
+
* carries this organization (`organizationId`, or the 1.x-era
|
|
33
|
+
* `organization_id`).
|
|
34
|
+
*/
|
|
30
35
|
orgGate?: string;
|
|
31
36
|
/** role → allowed module prefixes. Empty / missing → no restriction. */
|
|
32
37
|
roleFilter?: Record<string, string[]>;
|
|
@@ -103,6 +108,12 @@ export interface CreateFrameworkAppOptionsBase {
|
|
|
103
108
|
* this option has no effect.
|
|
104
109
|
*/
|
|
105
110
|
dashboardStore?: DashboardStore;
|
|
111
|
+
/**
|
|
112
|
+
* Duplicate tool names across plugins, the framework tools, and later
|
|
113
|
+
* registrations: `"warn"` (default in 2.x) or `"throw"` (fail the boot).
|
|
114
|
+
* See `InstallToolkitOptions.duplicateToolNames`.
|
|
115
|
+
*/
|
|
116
|
+
duplicateToolNames?: DuplicateToolNamePolicy;
|
|
106
117
|
};
|
|
107
118
|
/** Supplies the non-empty set of apps each plugin represents. */
|
|
108
119
|
appConfig?: AppConfig;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-framework-app.d.ts","sourceRoot":"","sources":["../../src/tools/create-framework-app.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EAET,KAAK,YAAY,EAGlB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;
|
|
1
|
+
{"version":3,"file":"create-framework-app.d.ts","sourceRoot":"","sources":["../../src/tools/create-framework-app.ts"],"names":[],"mappings":"AACA,OAAO,EACL,SAAS,EAET,KAAK,YAAY,EAGlB,MAAM,SAAS,CAAA;AAChB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAGlD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAA;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,sBAAsB,CAAA;AAEnE,MAAM,WAAW,6BAA6B;IAC5C,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,aAAa,GAAG,MAAM,GAAG,OAAO,CAAC,CAAA;IACzF,OAAO,EAAE,SAAS,EAAE,CAAA;IACpB,UAAU,CAAC,EAAE;QACX;;;;WAIG;QACH,OAAO,CAAC,EAAE,MAAM,CAAA;QAChB,wEAAwE;QACxE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;QACrC;;;;;;;WAOG;QACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;KAC/B,CAAA;IACD,GAAG,EAAE;QACH;;;;;;WAMG;QACH,MAAM,EAAE;YACN,wEAAwE;YACxE,MAAM,EAAE,MAAM,CAAA;YACd,0EAA0E;YAC1E,OAAO,CAAC,EAAE,MAAM,CAAA;SACjB,CAAA;QACD,gEAAgE;QAChE,eAAe,CAAC,EAAE,MAAM,CAAA;QACxB;;;;;;WAMG;QACH,GAAG,CAAC,EAAE,cAAc,CAAA;QACpB;;;;;;;;;;;;;;;;;;;;;WAqBG;QACH,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB;;;;;WAKG;QACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;QAC1B;;;;;;;WAOG;QACH,cAAc,CAAC,EAAE,cAAc,CAAA;QAC/B;;;;WAIG;QACH,kBAAkB,CAAC,EAAE,uBAAuB,CAAA;KAC7C,CAAA;IACD,iEAAiE;IACjE,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB;AAED;;;;GAIG;AACH,MAAM,WAAW,kCAAkC,CACjD,KAAK,GAAG,OAAO,CACf,SAAQ,6BAA6B;IACrC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAA;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,qCAAsC,SAAQ,6BAA6B;IAC1F,KAAK,CAAC,EAAE,SAAS,CAAA;CAClB;AAED,MAAM,MAAM,yBAAyB,CAAC,KAAK,GAAG,OAAO,IACnD,kCAAkC,CAAC,KAAK,CAAC,GAAG,qCAAqC,CAAA;AAoBnF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EACtC,OAAO,EAAE,kCAAkC,CAAC,KAAK,CAAC,GACjD,OAAO,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5B,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,qCAAqC,GAC7C,OAAO,CAAC,SAAS,CAAC,CAAA"}
|
|
@@ -47,7 +47,8 @@ export async function createFrameworkApp(options) {
|
|
|
47
47
|
: new MCPServer({ ...options.serverOptions, ...baseConfig });
|
|
48
48
|
// The registrars are typed against the OAuth-less `MCPServer`; a
|
|
49
49
|
// `MCPServer<TUser>` differs only in the `ctx.auth` its callbacks receive,
|
|
50
|
-
// which
|
|
50
|
+
// which they read structurally through `resolveCaller` (never via the
|
|
51
|
+
// `TUser` type).
|
|
51
52
|
const serverForRegistrars = server;
|
|
52
53
|
// Collect every view name bound during boot so the registry can be primed
|
|
53
54
|
// once at the end (mcp-use accepts `view` bindings before priming — they
|
|
@@ -65,11 +66,12 @@ export async function createFrameworkApp(options) {
|
|
|
65
66
|
return originalTool(definition, callback);
|
|
66
67
|
};
|
|
67
68
|
serverForRegistrars.tool = wrappedTool;
|
|
69
|
+
// Both middlewares are typed structurally (host-agnostic, no mcp-use import
|
|
70
|
+
// in the root barrel) yet shaped so mcp-use 2's `MiddlewareContext` — SDK
|
|
71
|
+
// `AuthInfo` with the mapped user under `auth.extra.user` — is assignable to
|
|
72
|
+
// them; registering them needs no cast.
|
|
68
73
|
const orgGateId = options.middleware?.orgGate;
|
|
69
74
|
if (orgGateId) {
|
|
70
|
-
// The middleware is typed structurally on purpose so it stays host-
|
|
71
|
-
// agnostic; mcp-use 2.x types `ctx.auth` as its own `AuthInfo`, which is
|
|
72
|
-
// not mutually assignable with that shape. Only `auth.user` is read.
|
|
73
75
|
server.use("mcp:*", createOrgGateMiddleware(orgGateId));
|
|
74
76
|
}
|
|
75
77
|
const roleFilter = options.middleware?.roleFilter;
|
|
@@ -77,7 +79,6 @@ export async function createFrameworkApp(options) {
|
|
|
77
79
|
const { toolsList, toolsCall } = createRoleFilterMiddleware(roleFilter, {
|
|
78
80
|
failClosed: options.middleware?.roleFilterFailClosed ?? false,
|
|
79
81
|
});
|
|
80
|
-
// Cast for the same reason as the org gate above.
|
|
81
82
|
server.use("mcp:tools/list", toolsList);
|
|
82
83
|
server.use("mcp:tools/call", toolsCall);
|
|
83
84
|
}
|
|
@@ -92,7 +93,11 @@ export async function createFrameworkApp(options) {
|
|
|
92
93
|
builder: options.app.builder,
|
|
93
94
|
catalogueToolName: options.app.catalogueToolName,
|
|
94
95
|
dashboardStore: options.app.dashboardStore,
|
|
96
|
+
// Under OAuth a dashboard call without a resolvable caller id is refused,
|
|
97
|
+
// never widened to global (owner-less) scope.
|
|
98
|
+
requireCallerIdentity: Boolean(options.oauth),
|
|
95
99
|
appConfig: options.appConfig,
|
|
100
|
+
duplicateToolNames: options.app.duplicateToolNames,
|
|
96
101
|
});
|
|
97
102
|
// Prime the view registry LAST, once every registrar and plugin has bound
|
|
98
103
|
// its views. One inline entry per bound name, all sharing the same bundle
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-framework-app.js","sourceRoot":"","sources":["../../src/tools/create-framework-app.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAA;AACjC,OAAO,EACL,SAAS,EACT,aAAa,GAId,MAAM,SAAS,CAAA;AAEhB,OAAO,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AACnE,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AAIzE,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;
|
|
1
|
+
{"version":3,"file":"create-framework-app.js","sourceRoot":"","sources":["../../src/tools/create-framework-app.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,13 +10,17 @@ export declare const DASHBOARD_SCHEMA_VERSION = 1;
|
|
|
10
10
|
/**
|
|
11
11
|
* Persisted dashboard = full `render-view` input plus identity and
|
|
12
12
|
* ownership metadata. The server generates `id`, `createdAt`, `updatedAt`;
|
|
13
|
-
* `userId` is
|
|
13
|
+
* `userId` is the caller id `resolveCallerId(ctx)` resolves on save.
|
|
14
14
|
*/
|
|
15
15
|
export interface DashboardRecord {
|
|
16
16
|
id: string;
|
|
17
17
|
name: string;
|
|
18
18
|
description?: string;
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Owner; omitted only when the host boots without OAuth (global scope). An
|
|
21
|
+
* owner-less record is invisible to — and never writable by — an
|
|
22
|
+
* identified caller.
|
|
23
|
+
*/
|
|
20
24
|
userId?: string;
|
|
21
25
|
keys?: Record<string, unknown>;
|
|
22
26
|
steps?: PipelineStepRef[];
|
|
@@ -51,6 +55,22 @@ export interface DashboardSummary {
|
|
|
51
55
|
description?: string;
|
|
52
56
|
title?: string;
|
|
53
57
|
updatedAt: string;
|
|
58
|
+
/**
|
|
59
|
+
* The record's owner, as in {@link DashboardRecord.userId}. The built-in
|
|
60
|
+
* stores report it, and a custom store should: the dashboard tools hold an
|
|
61
|
+
* identified caller to its own summaries with it. A summary without one is
|
|
62
|
+
* verified through `get` instead (one read per entry).
|
|
63
|
+
*/
|
|
64
|
+
userId?: string;
|
|
65
|
+
/**
|
|
66
|
+
* Set (to the reason) when the record exists but this build cannot read it
|
|
67
|
+
* — a newer `schemaVersion`, corrupt JSON, a failed schema check, or (in a
|
|
68
|
+
* listing) an entry the filesystem refuses to read. `name` then repeats the
|
|
69
|
+
* id and `updatedAt` is best-effort (empty when unknown).
|
|
70
|
+
* Reported instead of skipped so it can't silently vanish, and refused by
|
|
71
|
+
* `get` / `save` / `delete` with {@link DashboardUnreadableError}.
|
|
72
|
+
*/
|
|
73
|
+
unreadable?: string;
|
|
54
74
|
}
|
|
55
75
|
/**
|
|
56
76
|
* Persistence backing for dashboards. The framework is indifferent to how
|
|
@@ -59,14 +79,34 @@ export interface DashboardSummary {
|
|
|
59
79
|
* backed one for production).
|
|
60
80
|
*
|
|
61
81
|
* All methods accept an optional `userId` filter so implementations can
|
|
62
|
-
* enforce ownership
|
|
63
|
-
*
|
|
82
|
+
* enforce ownership:
|
|
83
|
+
*
|
|
84
|
+
* - **No `userId`** — global scope, the no-OAuth boot: every record is
|
|
85
|
+
* visible and writable.
|
|
86
|
+
* - **A `userId`** — the caller sees and touches only records whose
|
|
87
|
+
* `userId` equals it. An owner-less record is NOT the caller's: it stays
|
|
88
|
+
* invisible to `list`/`get`/`delete`, and `save` refuses to update it.
|
|
89
|
+
* (The dashboard tools never reach a store without a `userId` once the
|
|
90
|
+
* request is authenticated — they refuse the call instead.)
|
|
91
|
+
*
|
|
92
|
+
* {@link isDashboardOwnedBy} is that rule; a custom store should apply it
|
|
93
|
+
* rather than re-derive it, and report each summary's owner
|
|
94
|
+
* ({@link DashboardSummary.userId}). The dashboard tools re-check every
|
|
95
|
+
* answer for an identified caller anyway — `get`, `list`, and the record a
|
|
96
|
+
* `save` or `delete` would touch — so a store on the laxer 2.5 rule (an
|
|
97
|
+
* owner-less record counted as everyone's) cannot leak or hand out such a
|
|
98
|
+
* record; it only costs extra reads.
|
|
64
99
|
*
|
|
65
100
|
* `save` carries the acting user as `input.userId`: updating an existing
|
|
66
|
-
* record
|
|
101
|
+
* record the caller doesn't own is rejected with
|
|
67
102
|
* {@link DashboardOwnershipError}, and `input.userId` can never reassign an
|
|
68
|
-
* existing record's owner.
|
|
69
|
-
*
|
|
103
|
+
* existing record's owner.
|
|
104
|
+
*
|
|
105
|
+
* A record that exists but cannot be read (newer `schemaVersion`, corrupt
|
|
106
|
+
* JSON, failed schema) is a conflict, never "absent": `get`, `save` and
|
|
107
|
+
* `delete` reject with {@link DashboardUnreadableError}, and `list` reports it
|
|
108
|
+
* with {@link DashboardSummary.unreadable} — so a save can never overwrite it
|
|
109
|
+
* and hand it a new owner.
|
|
70
110
|
*/
|
|
71
111
|
export interface DashboardStore {
|
|
72
112
|
save(input: DashboardSaveInput): Promise<DashboardRecord>;
|
|
@@ -88,6 +128,16 @@ export interface DashboardStore {
|
|
|
88
128
|
* Exported for unit testing.
|
|
89
129
|
*/
|
|
90
130
|
export declare function parseDashboardRecord(raw: unknown): DashboardRecord | undefined;
|
|
131
|
+
/**
|
|
132
|
+
* The ownership rule of the {@link DashboardStore} contract, shared by every
|
|
133
|
+
* built-in store and by the dashboard tools: no caller id = global scope
|
|
134
|
+
* (no-OAuth boot, everything visible); an identified caller owns exactly the
|
|
135
|
+
* records stamped with its id — an owner-less record is not one of them.
|
|
136
|
+
*
|
|
137
|
+
* Exported so a custom store applies the same rule instead of re-deriving it
|
|
138
|
+
* (the 2.5 rule also granted owner-less records to every identified caller).
|
|
139
|
+
*/
|
|
140
|
+
export declare function isDashboardOwnedBy(ownerId: string | undefined, userId: string | undefined): boolean;
|
|
91
141
|
/**
|
|
92
142
|
* Error thrown by `save()` when an update would touch a record the caller
|
|
93
143
|
* doesn't own, or would change a record's owner. Distinct from the
|
|
@@ -98,6 +148,24 @@ export declare function parseDashboardRecord(raw: unknown): DashboardRecord | un
|
|
|
98
148
|
export declare class DashboardOwnershipError extends Error {
|
|
99
149
|
constructor(message: string);
|
|
100
150
|
}
|
|
151
|
+
/**
|
|
152
|
+
* Error thrown by `get`, `save` and `delete` when the addressed record exists
|
|
153
|
+
* but this build cannot read it (newer `schemaVersion`, corrupt JSON, failed
|
|
154
|
+
* schema). Treating such a record as absent would let `save` overwrite it —
|
|
155
|
+
* stamping a fresh owner onto someone else's data — so it is a conflict the
|
|
156
|
+
* caller has to see.
|
|
157
|
+
*/
|
|
158
|
+
export declare class DashboardUnreadableError extends Error {
|
|
159
|
+
readonly dashboardId: string;
|
|
160
|
+
readonly reason: string;
|
|
161
|
+
constructor(dashboardId: string, reason: string);
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Throw {@link DashboardOwnershipError} unless `userId` may update `existing`
|
|
165
|
+
* ({@link isDashboardOwnedBy}). Shared by {@link resolveSavedRecord} and the
|
|
166
|
+
* dashboard tools, which re-check a custom store's answer before a save.
|
|
167
|
+
*/
|
|
168
|
+
export declare function assertDashboardWritable(existing: DashboardRecord, userId: string | undefined): void;
|
|
101
169
|
/**
|
|
102
170
|
* Resolve the record to persist for a `save`, enforcing ownership on updates.
|
|
103
171
|
*
|
|
@@ -108,9 +176,10 @@ export declare class DashboardOwnershipError extends Error {
|
|
|
108
176
|
* record with `id`, `createdAt`, and — critically — `existing.userId`
|
|
109
177
|
* preserved so `input.userId` can never reassign the owner.
|
|
110
178
|
*
|
|
111
|
-
*
|
|
112
|
-
*
|
|
113
|
-
*
|
|
179
|
+
* Without an `input.userId` (global scope: a host booted without OAuth) every
|
|
180
|
+
* record is writable, so single-user deployments keep working. An identified
|
|
181
|
+
* actor owns only records stamped with its id — an owner-less record is
|
|
182
|
+
* refused, never silently claimed.
|
|
114
183
|
*
|
|
115
184
|
* Exported for unit testing; the store factories below are the public API.
|
|
116
185
|
*/
|
|
@@ -127,9 +196,10 @@ export interface FileSystemDashboardStoreOptions {
|
|
|
127
196
|
}
|
|
128
197
|
/**
|
|
129
198
|
* Dashboards stored as one JSON file per record under `dir`. Suitable for
|
|
130
|
-
* single-node deployments that need survival across restarts.
|
|
131
|
-
*
|
|
132
|
-
*
|
|
199
|
+
* single-node deployments that need survival across restarts. Writes are
|
|
200
|
+
* atomic (temp file + rename), so a crash never leaves a torn record.
|
|
201
|
+
* Locking is advisory: concurrent writes of the same id can race — fine for
|
|
202
|
+
* the v1 "single user clicking Save" workflow, not fine for multi-writer
|
|
133
203
|
* production.
|
|
134
204
|
*/
|
|
135
205
|
export declare function createFileSystemDashboardStore(options: FileSystemDashboardStoreOptions): DashboardStore;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dashboard-store.d.ts","sourceRoot":"","sources":["../../src/tools/dashboard-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAC3D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAA;AAGhE;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAA;AAEzC;;;;GAIG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB
|
|
1
|
+
{"version":3,"file":"dashboard-store.d.ts","sourceRoot":"","sources":["../../src/tools/dashboard-store.ts"],"names":[],"mappings":"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"}
|