@rubytech/create-maxy-code 0.1.351 → 0.1.353

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.
Files changed (92) hide show
  1. package/package.json +2 -2
  2. package/payload/platform/config/brand.json +1 -1
  3. package/payload/platform/package-lock.json +76 -1
  4. package/payload/platform/plugins/.claude-plugin/marketplace.json +5 -0
  5. package/payload/platform/plugins/admin/hooks/lib/maxy-mcp-plugins.txt +1 -0
  6. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js +27 -10
  7. package/payload/platform/plugins/admin/mcp/dist/__tests__/capabilities-here.test.js.map +1 -1
  8. package/payload/platform/plugins/admin/skills/agent-builder/references/agent-pattern.md +1 -1
  9. package/payload/platform/plugins/admin/skills/platform-architecture/SKILL.md +40 -2
  10. package/payload/platform/plugins/cloudflare/skills/calendar-site/SKILL.md +2 -2
  11. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/booking.css +41 -0
  12. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/booking.js +236 -47
  13. package/payload/platform/plugins/cloudflare/skills/calendar-site/template/public/index.html +6 -0
  14. package/payload/platform/plugins/connector/.claude-plugin/plugin.json +21 -0
  15. package/payload/platform/plugins/connector/PLUGIN.md +55 -0
  16. package/payload/platform/plugins/connector/lib/mcp-spawn-tee/index.js +193 -0
  17. package/payload/platform/plugins/connector/lib/mcp-spawn-tee/package.json +3 -0
  18. package/payload/platform/plugins/connector/mcp/dist/index.d.ts +2 -0
  19. package/payload/platform/plugins/connector/mcp/dist/index.d.ts.map +1 -0
  20. package/payload/platform/plugins/connector/mcp/dist/index.js +119 -0
  21. package/payload/platform/plugins/connector/mcp/dist/index.js.map +1 -0
  22. package/payload/platform/plugins/connector/mcp/dist/lib/call.d.ts +54 -0
  23. package/payload/platform/plugins/connector/mcp/dist/lib/call.d.ts.map +1 -0
  24. package/payload/platform/plugins/connector/mcp/dist/lib/call.js +157 -0
  25. package/payload/platform/plugins/connector/mcp/dist/lib/call.js.map +1 -0
  26. package/payload/platform/plugins/connector/mcp/dist/lib/redact.d.ts +10 -0
  27. package/payload/platform/plugins/connector/mcp/dist/lib/redact.d.ts.map +1 -0
  28. package/payload/platform/plugins/connector/mcp/dist/lib/redact.js +29 -0
  29. package/payload/platform/plugins/connector/mcp/dist/lib/redact.js.map +1 -0
  30. package/payload/platform/plugins/connector/mcp/dist/lib/ssrf.d.ts +29 -0
  31. package/payload/platform/plugins/connector/mcp/dist/lib/ssrf.d.ts.map +1 -0
  32. package/payload/platform/plugins/connector/mcp/dist/lib/ssrf.js +112 -0
  33. package/payload/platform/plugins/connector/mcp/dist/lib/ssrf.js.map +1 -0
  34. package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts +25 -0
  35. package/payload/platform/plugins/connector/mcp/dist/lib/store.d.ts.map +1 -0
  36. package/payload/platform/plugins/connector/mcp/dist/lib/store.js +63 -0
  37. package/payload/platform/plugins/connector/mcp/dist/lib/store.js.map +1 -0
  38. package/payload/platform/plugins/connector/mcp/dist/scripts/audit-connectors.d.ts +9 -0
  39. package/payload/platform/plugins/connector/mcp/dist/scripts/audit-connectors.d.ts.map +1 -0
  40. package/payload/platform/plugins/connector/mcp/dist/scripts/audit-connectors.js +63 -0
  41. package/payload/platform/plugins/connector/mcp/dist/scripts/audit-connectors.js.map +1 -0
  42. package/payload/platform/plugins/connector/mcp/package.json +20 -0
  43. package/payload/platform/plugins/docs/references/connector.md +33 -0
  44. package/payload/platform/plugins/docs/references/getting-started.md +1 -1
  45. package/payload/platform/scripts/check-agent-contract.mjs +97 -0
  46. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.d.ts.map +1 -1
  47. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js +5 -0
  48. package/payload/platform/services/claude-session-manager/dist/canonical-tool-names.generated.js.map +1 -1
  49. package/payload/platform/templates/agents/admin/IDENTITY.md +4 -0
  50. package/payload/platform/templates/specialists/agents/citation-auditor.md +5 -1
  51. package/payload/platform/templates/specialists/agents/coding-assistant.md +8 -0
  52. package/payload/platform/templates/specialists/agents/compiled-truth-rewriter.md +4 -0
  53. package/payload/platform/templates/specialists/agents/content-producer.md +8 -0
  54. package/payload/platform/templates/specialists/agents/data-manager.md +9 -1
  55. package/payload/platform/templates/specialists/agents/database-operator.md +12 -0
  56. package/payload/platform/templates/specialists/agents/librarian.md +9 -1
  57. package/payload/platform/templates/specialists/agents/personal-assistant.md +8 -0
  58. package/payload/platform/templates/specialists/agents/project-manager.md +8 -0
  59. package/payload/platform/templates/specialists/agents/public-session-reviewer.md +9 -1
  60. package/payload/platform/templates/specialists/agents/research-assistant.md +8 -0
  61. package/payload/platform/templates/specialists/agents/typed-edge-classifier.md +4 -2
  62. package/payload/premium-plugins/writer-craft/agents/writer-craft--manuscript-reviewer.md +12 -0
  63. package/payload/server/public/assets/{AdminLoginScreens-B1cvICYI.js → AdminLoginScreens-CzdOQKyO.js} +1 -1
  64. package/payload/server/public/assets/{AdminShell-B-GeoG3j.js → AdminShell-CC-CuN6Y.js} +1 -1
  65. package/payload/server/public/assets/{Checkbox-DoGMXVpF.js → Checkbox-sQBc9xSy.js} +1 -1
  66. package/payload/server/public/assets/{OperatorConversations-CfG1EYyP.js → OperatorConversations-CA_2c3sp.js} +1 -1
  67. package/payload/server/public/assets/OperatorConversations-DPVKGsRS.css +1 -0
  68. package/payload/server/public/assets/{admin-DF9JDP6a.js → admin-qW6jM6l0.js} +1 -1
  69. package/payload/server/public/assets/admin-types-DJoj6VJv.js +1 -0
  70. package/payload/server/public/assets/{browser-Cyi6v8BS.js → browser-BsW6KaxZ.js} +1 -1
  71. package/payload/server/public/assets/calendar-BPAiN1cL.js +1 -0
  72. package/payload/server/public/assets/chat-DVD9yoVL.js +1 -0
  73. package/payload/server/public/assets/{data-CrJZjlQ1.js → data-D_cR_NCZ.js} +1 -1
  74. package/payload/server/public/assets/{graph-CutaO0w1.js → graph-CmpAy2WP.js} +1 -1
  75. package/payload/server/public/assets/{graph-labels-CH0sWvcA.js → graph-labels-C0SLq_VP.js} +1 -1
  76. package/payload/server/public/assets/{operator-CqKk6Twn.js → operator-CrjtJcEY.js} +1 -1
  77. package/payload/server/public/assets/page-Cf3fVDSo.js +32 -0
  78. package/payload/server/public/assets/{public-D5lkOp3H.js → public-BkNtvSYp.js} +1 -1
  79. package/payload/server/public/browser.html +4 -4
  80. package/payload/server/public/calendar.html +4 -4
  81. package/payload/server/public/chat.html +6 -6
  82. package/payload/server/public/data.html +4 -4
  83. package/payload/server/public/graph.html +6 -6
  84. package/payload/server/public/index.html +7 -7
  85. package/payload/server/public/operator.html +8 -8
  86. package/payload/server/public/public.html +6 -6
  87. package/payload/server/server.js +153 -83
  88. package/payload/server/public/assets/OperatorConversations-C8G6Gfgu.css +0 -1
  89. package/payload/server/public/assets/admin-types-Dg11L4MQ.js +0 -1
  90. package/payload/server/public/assets/calendar-CA3_Dm8j.js +0 -1
  91. package/payload/server/public/assets/chat-C4hHkcTu.js +0 -1
  92. package/payload/server/public/assets/page-Bfm1FN4n.js +0 -30
@@ -0,0 +1,119 @@
1
+ import { initStderrTee } from "../../../../lib/mcp-stderr-tee/dist/index.js";
2
+ initStderrTee("connector");
3
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
4
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
5
+ import { z } from "zod";
6
+ import { lifelineTool } from "../../../../lib/mcp-lifeline/dist/index.js";
7
+ import { readRegistry, listConnectors, registerConnector, deregisterConnector, resolveConnector, } from "./lib/store.js";
8
+ import { performCall } from "./lib/call.js";
9
+ import { hostResolvesPrivate } from "./lib/ssrf.js";
10
+ // Plugin-system boot tolerance: module init must never throw. tools/list is enumerated
11
+ // with empty env, so account context is resolved per call; all tools are registered
12
+ // unconditionally and each handler refuses per-call when context is absent.
13
+ const ACCOUNT_ID = process.env.ACCOUNT_ID ?? null;
14
+ const PLATFORM_ROOT = process.env.PLATFORM_ROOT ?? null;
15
+ function countRegistered() {
16
+ if (!ACCOUNT_ID || !PLATFORM_ROOT)
17
+ return "n/a";
18
+ try {
19
+ return Object.keys(readRegistry(PLATFORM_ROOT, ACCOUNT_ID)).length;
20
+ }
21
+ catch {
22
+ return "n/a";
23
+ }
24
+ }
25
+ process.stderr.write(`[connector] op=init account=${ACCOUNT_ID ?? "null"} connectors=${countRegistered()}\n`);
26
+ let callSeq = 0;
27
+ const nextReqId = () => (++callSeq).toString(16).padStart(6, "0");
28
+ function ok(data) {
29
+ return {
30
+ content: [{ type: "text", text: typeof data === "string" ? data : JSON.stringify(data, null, 2) }],
31
+ };
32
+ }
33
+ function fail(msg) {
34
+ return { content: [{ type: "text", text: msg }], isError: true };
35
+ }
36
+ function refuseNoAccount(tool) {
37
+ process.stderr.write(`[connector] tool=${tool} refuse reason=no-account-context\n`);
38
+ return fail(`${tool} cannot execute: launched without ACCOUNT_ID/PLATFORM_ROOT (metadata-only mode).`);
39
+ }
40
+ function ctx(tool) {
41
+ if (!ACCOUNT_ID || !PLATFORM_ROOT)
42
+ return { refusal: refuseNoAccount(tool) };
43
+ return { platformRoot: PLATFORM_ROOT, accountId: ACCOUNT_ID };
44
+ }
45
+ const server = new McpServer({ name: "connector", version: "0.1.0" });
46
+ lifelineTool(server, "connector-register", "Register a named third-party REST API: store its base URL and a static credential so the agent can call it. auth.scheme is bearer | api-key-header | basic; headerName is required for api-key-header. The credential is stored in the account secrets file and is never returned or logged. Returns the non-secret record only.", {
47
+ name: z.string().min(1),
48
+ baseUrl: z.string().min(1),
49
+ auth: z.object({
50
+ scheme: z.enum(["bearer", "api-key-header", "basic"]),
51
+ value: z.string().min(1),
52
+ headerName: z.string().min(1).optional(),
53
+ }),
54
+ }, async ({ name, baseUrl, auth }) => {
55
+ const c = ctx("connector-register");
56
+ if ("refusal" in c)
57
+ return c.refusal;
58
+ let url;
59
+ try {
60
+ url = new URL(baseUrl);
61
+ }
62
+ catch {
63
+ return fail("connector-register: baseUrl is not a valid URL.");
64
+ }
65
+ if (url.protocol !== "http:" && url.protocol !== "https:")
66
+ return fail("connector-register: baseUrl must be http(s).");
67
+ if (auth.scheme === "api-key-header" && !auth.headerName)
68
+ return fail("connector-register: headerName is required for the api-key-header scheme.");
69
+ if (await hostResolvesPrivate(url.hostname)) {
70
+ process.stderr.write(`[connector] op=register-refused name=${name} reason=private-ip target=${url.hostname}\n`);
71
+ return fail("connector-register: refused — baseUrl host resolves to a private or loopback address.");
72
+ }
73
+ const rec = {
74
+ baseUrl,
75
+ host: url.hostname,
76
+ authScheme: auth.scheme,
77
+ ...(auth.scheme === "api-key-header" ? { headerName: auth.headerName } : {}),
78
+ };
79
+ registerConnector(c.platformRoot, c.accountId, name, rec, auth.value);
80
+ process.stderr.write(`[connector] op=register name=${name} host=${url.hostname} scheme=${auth.scheme}\n`);
81
+ return ok({ name, baseUrl, host: url.hostname, authScheme: auth.scheme });
82
+ });
83
+ lifelineTool(server, "connector-call", "Make an authenticated request to a registered connector. The credential is injected from the secret store; the request is confined to the registered host (a different host, a private address, or a cross-host redirect is refused). Returns { status, headers (redacted), body (capped) }.", {
84
+ name: z.string().min(1),
85
+ method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
86
+ path: z.string(),
87
+ query: z.record(z.string()).optional(),
88
+ body: z.unknown().optional(),
89
+ headers: z.record(z.string()).optional(),
90
+ }, async ({ name, method, path, query, body, headers }) => {
91
+ const c = ctx("connector-call");
92
+ if ("refusal" in c)
93
+ return c.refusal;
94
+ const resolved = resolveConnector(c.platformRoot, c.accountId, name);
95
+ if (!resolved)
96
+ return fail(`connector-call: no connector named '${name}' is registered.`);
97
+ const reqId = nextReqId();
98
+ const result = await performCall(resolved.rec, resolved.secret, { method, path, query, body, headers }, { log: (line) => process.stderr.write(`[connector] ${line}\n`), reqId });
99
+ if (!result.ok)
100
+ return fail(`connector-call refused: ${result.refused}.`);
101
+ return ok({ status: result.status, headers: result.headers, body: result.body, truncated: result.truncated });
102
+ });
103
+ lifelineTool(server, "connector-list", "List the registered connectors for this account (names and base URLs only — never credentials).", {}, async () => {
104
+ const c = ctx("connector-list");
105
+ if ("refusal" in c)
106
+ return c.refusal;
107
+ return ok(listConnectors(c.platformRoot, c.accountId));
108
+ });
109
+ lifelineTool(server, "connector-deregister", "Remove a registered connector and its stored credential. Idempotent: removing an unknown name is reported, not an error.", { name: z.string().min(1) }, async ({ name }) => {
110
+ const c = ctx("connector-deregister");
111
+ if ("refusal" in c)
112
+ return c.refusal;
113
+ const had = deregisterConnector(c.platformRoot, c.accountId, name);
114
+ process.stderr.write(`[connector] op=deregister name=${name} existed=${had}\n`);
115
+ return ok(had ? `Deregistered connector '${name}'.` : `No connector named '${name}' was registered.`);
116
+ });
117
+ const transport = new StdioServerTransport();
118
+ await server.connect(transport);
119
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ import type { LookupFunction } from "node:net";
2
+ import { fetch as undiciFetch, type Dispatcher } from "undici";
3
+ import { type Refusal, type Resolution } from "./ssrf.js";
4
+ import type { ConnectorRecord } from "./store.js";
5
+ export interface CallParams {
6
+ method: string;
7
+ path: string;
8
+ query?: Record<string, string>;
9
+ body?: unknown;
10
+ headers?: Record<string, string>;
11
+ }
12
+ export interface CallDeps {
13
+ /** Override for tests; defaults to undici's fetch (same instance as the pinned dispatcher). */
14
+ fetchImpl?: typeof undiciFetch;
15
+ /** Override for tests so a loopback stub resolves; defaults to the real address-validating resolve. */
16
+ resolve?: (targetHost: string, registeredHost: string, kind: "request" | "redirect") => Promise<Resolution>;
17
+ /**
18
+ * Build the dispatcher that pins the connection to the validated addresses. Defaults to
19
+ * the real pinned dispatcher. Tests return `undefined` to skip pinning (a pinned loopback
20
+ * address would otherwise fail the public re-validation).
21
+ */
22
+ makeDispatcher?: (addresses: string[]) => Dispatcher | undefined;
23
+ /** Sink for `[connector]` lifecycle lines; the secret is never passed to it. */
24
+ log?: (line: string) => void;
25
+ reqId?: string;
26
+ }
27
+ export type CallResult = {
28
+ ok: true;
29
+ status: number;
30
+ headers: Record<string, string>;
31
+ body: string;
32
+ truncated: boolean;
33
+ } | {
34
+ ok: false;
35
+ refused: Refusal;
36
+ };
37
+ /**
38
+ * Build the DNS lookup an undici dispatcher uses to dial a connector. It returns the
39
+ * pre-validated addresses without consulting DNS — so no second, independent lookup
40
+ * happens at connect time — and re-validates each is public, failing closed. undici
41
+ * always calls it with `{ all: true }`; the single-result branch is kept for completeness.
42
+ */
43
+ export declare function pinnedLookup(addresses: string[]): LookupFunction;
44
+ /** Dispatcher that dials only the validated addresses; TLS/SNI still use the hostname, so cert validation is unchanged. */
45
+ export declare function pinnedDispatcher(addresses: string[]): Dispatcher;
46
+ /**
47
+ * Make one authenticated, host-bound request to a registered connector. The host is resolved
48
+ * and validated before the request and before every redirect hop, and the socket is pinned to
49
+ * the validated addresses so no second connect-time lookup can land on a rebind. The credential
50
+ * is injected from the caller-supplied secret and never logged. Returns status + redacted headers
51
+ * + capped body, or a refusal when resolution rejects the target.
52
+ */
53
+ export declare function performCall(rec: ConnectorRecord, secret: string, params: CallParams, deps?: CallDeps): Promise<CallResult>;
54
+ //# sourceMappingURL=call.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../src/lib/call.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC/C,OAAO,EAAS,KAAK,IAAI,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEtE,OAAO,EAA8B,KAAK,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,WAAW,CAAC;AACtF,OAAO,KAAK,EAAc,eAAe,EAAE,MAAM,YAAY,CAAC;AAE9D,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED,MAAM,WAAW,QAAQ;IACvB,+FAA+F;IAC/F,SAAS,CAAC,EAAE,OAAO,WAAW,CAAC;IAC/B,uGAAuG;IACvG,OAAO,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,UAAU,KAAK,OAAO,CAAC,UAAU,CAAC,CAAC;IAC5G;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,UAAU,GAAG,SAAS,CAAC;IACjE,gFAAgF;IAChF,GAAG,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,GAC/F;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAQpC;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,cAAc,CAUhE;AAED,2HAA2H;AAC3H,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,EAAE,GAAG,UAAU,CAEhE;AAkBD;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,UAAU,EAClB,IAAI,GAAE,QAAa,GAClB,OAAO,CAAC,UAAU,CAAC,CA8FrB"}
@@ -0,0 +1,157 @@
1
+ import { isIP } from "node:net";
2
+ import { Agent, fetch as undiciFetch } from "undici";
3
+ import { redactHeaders, scrubSecret } from "./redact.js";
4
+ import { isPrivateIp, resolveTarget } from "./ssrf.js";
5
+ const BODY_CAP = 262144; // 256 KiB
6
+ const MAX_REDIRECTS = 5;
7
+ /** Tag carried by the fail-closed error a pinned lookup raises, so the connect-time refusal is distinguishable from a genuine network fault. */
8
+ const PIN_REFUSAL = "__connectorPinRefusal";
9
+ /**
10
+ * Build the DNS lookup an undici dispatcher uses to dial a connector. It returns the
11
+ * pre-validated addresses without consulting DNS — so no second, independent lookup
12
+ * happens at connect time — and re-validates each is public, failing closed. undici
13
+ * always calls it with `{ all: true }`; the single-result branch is kept for completeness.
14
+ */
15
+ export function pinnedLookup(addresses) {
16
+ return ((_hostname, options, cb) => {
17
+ const safe = addresses.filter((a) => !isPrivateIp(a));
18
+ if (safe.length === 0) {
19
+ cb(Object.assign(new Error("connector: pinned address failed public re-validation"), { [PIN_REFUSAL]: true }), "", 0);
20
+ return;
21
+ }
22
+ if (options?.all)
23
+ cb(null, safe.map((a) => ({ address: a, family: isIP(a) || 4 })));
24
+ else
25
+ cb(null, safe[0], isIP(safe[0]) || 4);
26
+ });
27
+ }
28
+ /** Dispatcher that dials only the validated addresses; TLS/SNI still use the hostname, so cert validation is unchanged. */
29
+ export function pinnedDispatcher(addresses) {
30
+ return new Agent({ connect: { lookup: pinnedLookup(addresses) } });
31
+ }
32
+ /** True when an error's cause chain carries the pinned-lookup fail-closed tag. */
33
+ function isPinRefusal(err) {
34
+ for (let cur = err; cur != null; cur = cur.cause) {
35
+ if (cur[PIN_REFUSAL] === true)
36
+ return true;
37
+ }
38
+ return false;
39
+ }
40
+ /** Inject the credential per scheme. Returns the scheme label for the auth-applied log line. */
41
+ function applyAuth(headers, rec, secret) {
42
+ if (rec.authScheme === "bearer")
43
+ headers["Authorization"] = `Bearer ${secret}`;
44
+ else if (rec.authScheme === "basic")
45
+ headers["Authorization"] = `Basic ${Buffer.from(secret).toString("base64")}`;
46
+ else
47
+ headers[rec.headerName] = secret; // api-key-header (headerName validated at register)
48
+ return rec.authScheme;
49
+ }
50
+ /**
51
+ * Make one authenticated, host-bound request to a registered connector. The host is resolved
52
+ * and validated before the request and before every redirect hop, and the socket is pinned to
53
+ * the validated addresses so no second connect-time lookup can land on a rebind. The credential
54
+ * is injected from the caller-supplied secret and never logged. Returns status + redacted headers
55
+ * + capped body, or a refusal when resolution rejects the target.
56
+ */
57
+ export async function performCall(rec, secret, params, deps = {}) {
58
+ const fetchImpl = deps.fetchImpl ?? undiciFetch;
59
+ const resolve = deps.resolve ?? resolveTarget;
60
+ const makeDispatcher = deps.makeDispatcher ?? pinnedDispatcher;
61
+ const log = deps.log ?? (() => { });
62
+ const reqId = deps.reqId ?? "—";
63
+ const url = new URL(params.path, rec.baseUrl);
64
+ // A caller-supplied path may carry userinfo (user:pass@host); strip it so the only credential
65
+ // sent is the one the connector injects, and so userinfo cannot smuggle alternate auth.
66
+ url.username = "";
67
+ url.password = "";
68
+ if (params.query)
69
+ for (const [k, v] of Object.entries(params.query))
70
+ url.searchParams.set(k, v);
71
+ log(`op=call reqId=${reqId} method=${params.method} host=${url.hostname} path=${url.pathname}`);
72
+ const reqResolution = await resolve(url.hostname, rec.host, "request");
73
+ if (!reqResolution.ok) {
74
+ log(`op=call-refused reqId=${reqId} reason=${reqResolution.refused} target=${url.hostname}`);
75
+ return { ok: false, refused: reqResolution.refused };
76
+ }
77
+ // Track every pinned dispatcher this call creates (initial + each redirect hop) so the
78
+ // finally can close them — an undici Agent holds a connection pool and timers and would
79
+ // otherwise leak in this long-lived process. A test seam returning undefined is untracked:
80
+ // that is the shared global dispatcher, which is never ours to close.
81
+ const createdDispatchers = [];
82
+ const pin = (addresses) => {
83
+ const d = makeDispatcher(addresses);
84
+ if (d)
85
+ createdDispatchers.push(d);
86
+ return d;
87
+ };
88
+ let dispatcher = pin(reqResolution.addresses);
89
+ // Caller headers may not set the auth header or Host — those are ours to control.
90
+ const headers = {};
91
+ if (params.headers) {
92
+ for (const [k, v] of Object.entries(params.headers)) {
93
+ const lk = k.toLowerCase();
94
+ if (lk === "authorization" || lk === "host")
95
+ continue;
96
+ if (rec.headerName && lk === rec.headerName.toLowerCase())
97
+ continue;
98
+ headers[k] = v;
99
+ }
100
+ }
101
+ let bodyStr;
102
+ if (params.body !== undefined) {
103
+ if (!Object.keys(headers).some((k) => k.toLowerCase() === "content-type"))
104
+ headers["Content-Type"] = "application/json";
105
+ bodyStr = typeof params.body === "string" ? params.body : JSON.stringify(params.body);
106
+ }
107
+ const scheme = applyAuth(headers, rec, secret);
108
+ log(`op=auth-applied reqId=${reqId} scheme=${scheme === "api-key-header" ? "api-key" : scheme}`);
109
+ const start = Date.now();
110
+ let current = url;
111
+ let hops = 0;
112
+ try {
113
+ let res;
114
+ for (;;) {
115
+ res = await fetchImpl(current.toString(), {
116
+ method: params.method, headers, body: bodyStr, redirect: "manual",
117
+ // Omit when undefined so undici falls back to the global dispatcher (the test seam for
118
+ // a loopback stub); in production pin always returns the pinned dispatcher.
119
+ ...(dispatcher ? { dispatcher } : {}),
120
+ });
121
+ const location = res.status >= 300 && res.status < 400 ? res.headers.get("location") : null;
122
+ if (!location || hops++ >= MAX_REDIRECTS)
123
+ break;
124
+ const next = new URL(location, current);
125
+ const redirectResolution = await resolve(next.hostname, rec.host, "redirect");
126
+ if (!redirectResolution.ok) {
127
+ log(`op=call-refused reqId=${reqId} reason=${redirectResolution.refused} target=${next.hostname}`);
128
+ return { ok: false, refused: redirectResolution.refused };
129
+ }
130
+ dispatcher = pin(redirectResolution.addresses);
131
+ current = next;
132
+ }
133
+ const raw = await res.text();
134
+ const truncated = raw.length > BODY_CAP;
135
+ // Scrub the credential from the body in case the upstream reflects it (debug/echo endpoints).
136
+ const body = scrubSecret(truncated ? raw.slice(0, BODY_CAP) : raw, secret);
137
+ log(`op=response reqId=${reqId} status=${res.status} bytes=${raw.length} ms=${Date.now() - start}`);
138
+ return { ok: true, status: res.status, headers: redactHeaders(res.headers, rec.headerName, secret), body, truncated };
139
+ }
140
+ catch (err) {
141
+ // A pinned lookup that fails its public re-validation at connect time surfaces here. The
142
+ // reason is the same as a resolve-time private address; the trigger is the pinned-lookup
143
+ // re-validation. Any other fetch error is a genuine fault, not a refusal — rethrow it.
144
+ if (isPinRefusal(err)) {
145
+ log(`op=call-refused reqId=${reqId} reason=private-ip target=${current.hostname}`);
146
+ return { ok: false, refused: "private-ip" };
147
+ }
148
+ throw err;
149
+ }
150
+ finally {
151
+ // The body is already buffered by now; close every dispatcher this call created. Fire-and-forget
152
+ // so socket teardown never delays the tool response.
153
+ for (const d of createdDispatchers)
154
+ void d.close().catch(() => { });
155
+ }
156
+ }
157
+ //# sourceMappingURL=call.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"call.js","sourceRoot":"","sources":["../../src/lib/call.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /** Replace every occurrence of a credential (raw and base64 forms) with a marker. */
2
+ export declare function scrubSecret(text: string, secret: string): string;
3
+ /**
4
+ * Copy response headers into a plain object, masking the auth-bearing ones so a returned
5
+ * response never re-exposes a credential or session token. The connector's own api-key header
6
+ * (if any) is masked alongside Authorization and Set-Cookie, and the known secret value is
7
+ * scrubbed from every remaining header value in case the upstream reflects it.
8
+ */
9
+ export declare function redactHeaders(headers: Headers, apiKeyHeader?: string, secret?: string): Record<string, string>;
10
+ //# sourceMappingURL=redact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.d.ts","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAGA,qFAAqF;AACrF,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMhE;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,OAAO,EAAE,YAAY,CAAC,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAQ9G"}
@@ -0,0 +1,29 @@
1
+ /** Header names always redacted from a returned response (case-insensitive). */
2
+ const ALWAYS_DROP = ["authorization", "set-cookie"];
3
+ /** Replace every occurrence of a credential (raw and base64 forms) with a marker. */
4
+ export function scrubSecret(text, secret) {
5
+ if (!secret)
6
+ return text;
7
+ let out = text.split(secret).join("<redacted>");
8
+ const b64 = Buffer.from(secret).toString("base64");
9
+ if (b64)
10
+ out = out.split(b64).join("<redacted>");
11
+ return out;
12
+ }
13
+ /**
14
+ * Copy response headers into a plain object, masking the auth-bearing ones so a returned
15
+ * response never re-exposes a credential or session token. The connector's own api-key header
16
+ * (if any) is masked alongside Authorization and Set-Cookie, and the known secret value is
17
+ * scrubbed from every remaining header value in case the upstream reflects it.
18
+ */
19
+ export function redactHeaders(headers, apiKeyHeader, secret) {
20
+ const drop = new Set(ALWAYS_DROP);
21
+ if (apiKeyHeader)
22
+ drop.add(apiKeyHeader.toLowerCase());
23
+ const out = {};
24
+ headers.forEach((value, key) => {
25
+ out[key] = drop.has(key.toLowerCase()) ? "<redacted>" : secret ? scrubSecret(value, secret) : value;
26
+ });
27
+ return out;
28
+ }
29
+ //# sourceMappingURL=redact.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redact.js","sourceRoot":"","sources":["../../src/lib/redact.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,WAAW,GAAG,CAAC,eAAe,EAAE,YAAY,CAAC,CAAC;AAEpD,qFAAqF;AACrF,MAAM,UAAU,WAAW,CAAC,IAAY,EAAE,MAAc;IACtD,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IACzB,IAAI,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAChD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACnD,IAAI,GAAG;QAAE,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACjD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,aAAa,CAAC,OAAgB,EAAE,YAAqB,EAAE,MAAe;IACpF,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,WAAW,CAAC,CAAC;IAClC,IAAI,YAAY;QAAE,IAAI,CAAC,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC;IACvD,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,OAAO,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;QAC7B,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACtG,CAAC,CAAC,CAAC;IACH,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,29 @@
1
+ /** True for any loopback, private, link-local, or unique-local address (v4 or v6). */
2
+ export declare function isPrivateIp(ip: string): boolean;
3
+ /**
4
+ * Resolve a host and judge whether any of its addresses is private. IP literals (incl.
5
+ * bracketed IPv6) skip DNS. Fails closed: an unresolvable or lookup-erroring host is treated
6
+ * as unsafe (returns true), so the caller refuses rather than throwing.
7
+ */
8
+ export declare function hostResolvesPrivate(host: string): Promise<boolean>;
9
+ export type Refusal = "host-mismatch" | "private-ip" | "redirect-escape";
10
+ export type Resolution = {
11
+ ok: true;
12
+ addresses: string[];
13
+ } | {
14
+ ok: false;
15
+ refused: Refusal;
16
+ };
17
+ /**
18
+ * Resolve a request/redirect target to the validated public addresses the connection
19
+ * must pin to, or a refusal. The target must be the registered host (an off-host initial
20
+ * request is "host-mismatch", an off-host redirect is "redirect-escape"); the resolved set
21
+ * must be non-empty and every address public, else "private-ip". IP literals (incl.
22
+ * bracketed IPv6) skip DNS. Fails closed: a lookup error or empty result is a refusal.
23
+ *
24
+ * This is the single DNS lookup for a call. The caller pins the socket to the returned
25
+ * addresses so `fetch` performs no second, independent lookup — closing the window where
26
+ * a host could answer public here and private to the connect-time lookup.
27
+ */
28
+ export declare function resolveTarget(targetHost: string, registeredHost: string, kind: "request" | "redirect"): Promise<Resolution>;
29
+ //# sourceMappingURL=ssrf.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.d.ts","sourceRoot":"","sources":["../../src/lib/ssrf.ts"],"names":[],"mappings":"AAwBA,sFAAsF;AACtF,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAqB/C;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWxE;AAED,MAAM,MAAM,OAAO,GAAG,eAAe,GAAG,YAAY,GAAG,iBAAiB,CAAC;AAEzE,MAAM,MAAM,UAAU,GAClB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,MAAM,EAAE,CAAA;CAAE,GACjC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAC;AAEpC;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CACjC,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,EACtB,IAAI,EAAE,SAAS,GAAG,UAAU,GAC3B,OAAO,CAAC,UAAU,CAAC,CAmBrB"}
@@ -0,0 +1,112 @@
1
+ import { lookup } from "node:dns/promises";
2
+ import { isIP } from "node:net";
3
+ /** Strip the `[ ]` that URL.hostname keeps around an IPv6 literal, and a trailing FQDN dot. */
4
+ function normalizeHost(host) {
5
+ let s = host.toLowerCase();
6
+ if (s.startsWith("[") && s.endsWith("]"))
7
+ s = s.slice(1, -1);
8
+ if (s.endsWith("."))
9
+ s = s.slice(0, -1);
10
+ return s;
11
+ }
12
+ /** True for an IPv4 address in any loopback/private/link-local/CGNAT/"this-host" range. */
13
+ function v4Private(ip) {
14
+ const o = ip.split(".").map((s) => Number(s));
15
+ if (o.length !== 4 || o.some((n) => Number.isNaN(n) || n < 0 || n > 255))
16
+ return false;
17
+ const [a, b] = o;
18
+ if (a === 10 || a === 127 || a === 0)
19
+ return true; // private, loopback, "this host"
20
+ if (a === 172 && b >= 16 && b <= 31)
21
+ return true; // private
22
+ if (a === 192 && b === 168)
23
+ return true; // private
24
+ if (a === 169 && b === 254)
25
+ return true; // link-local
26
+ if (a === 100 && b >= 64 && b <= 127)
27
+ return true; // CGNAT (100.64/10)
28
+ return false;
29
+ }
30
+ /** True for any loopback, private, link-local, or unique-local address (v4 or v6). */
31
+ export function isPrivateIp(ip) {
32
+ const bare = normalizeHost(ip);
33
+ const fam = isIP(bare);
34
+ if (fam === 4)
35
+ return v4Private(bare);
36
+ if (fam === 6) {
37
+ const lower = bare;
38
+ if (lower === "::1" || lower === "::")
39
+ return true; // loopback, unspecified
40
+ const dotted = lower.match(/::ffff:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})$/); // IPv4-mapped, dotted
41
+ if (dotted)
42
+ return v4Private(dotted[1]);
43
+ const hex = lower.match(/::ffff:([0-9a-f]{1,4}):([0-9a-f]{1,4})$/); // IPv4-mapped, hex
44
+ if (hex) {
45
+ const hi = parseInt(hex[1], 16);
46
+ const lo = parseInt(hex[2], 16);
47
+ return v4Private(`${(hi >> 8) & 255}.${hi & 255}.${(lo >> 8) & 255}.${lo & 255}`);
48
+ }
49
+ if (lower.startsWith("fc") || lower.startsWith("fd"))
50
+ return true; // fc00::/7 ULA
51
+ // fe80::/10 link-local spans fe80–febf, i.e. fe8/fe9/fea/feb prefixes.
52
+ if (/^fe[89ab]/.test(lower))
53
+ return true;
54
+ return false;
55
+ }
56
+ return false;
57
+ }
58
+ /**
59
+ * Resolve a host and judge whether any of its addresses is private. IP literals (incl.
60
+ * bracketed IPv6) skip DNS. Fails closed: an unresolvable or lookup-erroring host is treated
61
+ * as unsafe (returns true), so the caller refuses rather than throwing.
62
+ */
63
+ export async function hostResolvesPrivate(host) {
64
+ const bare = normalizeHost(host);
65
+ if (!bare)
66
+ return true; // empty/malformed host can never be a safe public target
67
+ if (isIP(bare))
68
+ return isPrivateIp(bare);
69
+ try {
70
+ const addrs = await lookup(bare, { all: true });
71
+ if (addrs.length === 0)
72
+ return true;
73
+ return addrs.some((a) => isPrivateIp(a.address));
74
+ }
75
+ catch {
76
+ return true; // DNS failure → fail closed
77
+ }
78
+ }
79
+ /**
80
+ * Resolve a request/redirect target to the validated public addresses the connection
81
+ * must pin to, or a refusal. The target must be the registered host (an off-host initial
82
+ * request is "host-mismatch", an off-host redirect is "redirect-escape"); the resolved set
83
+ * must be non-empty and every address public, else "private-ip". IP literals (incl.
84
+ * bracketed IPv6) skip DNS. Fails closed: a lookup error or empty result is a refusal.
85
+ *
86
+ * This is the single DNS lookup for a call. The caller pins the socket to the returned
87
+ * addresses so `fetch` performs no second, independent lookup — closing the window where
88
+ * a host could answer public here and private to the connect-time lookup.
89
+ */
90
+ export async function resolveTarget(targetHost, registeredHost, kind) {
91
+ if (normalizeHost(targetHost) !== normalizeHost(registeredHost)) {
92
+ return { ok: false, refused: kind === "redirect" ? "redirect-escape" : "host-mismatch" };
93
+ }
94
+ const bare = normalizeHost(targetHost);
95
+ if (!bare)
96
+ return { ok: false, refused: "private-ip" }; // empty/malformed host is never a safe target
97
+ if (isIP(bare)) {
98
+ return isPrivateIp(bare) ? { ok: false, refused: "private-ip" } : { ok: true, addresses: [bare] };
99
+ }
100
+ let addrs;
101
+ try {
102
+ addrs = await lookup(bare, { all: true });
103
+ }
104
+ catch {
105
+ return { ok: false, refused: "private-ip" }; // DNS failure → fail closed
106
+ }
107
+ if (addrs.length === 0 || addrs.some((a) => isPrivateIp(a.address))) {
108
+ return { ok: false, refused: "private-ip" };
109
+ }
110
+ return { ok: true, addresses: addrs.map((a) => a.address) };
111
+ }
112
+ //# sourceMappingURL=ssrf.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ssrf.js","sourceRoot":"","sources":["../../src/lib/ssrf.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ export type AuthScheme = "bearer" | "api-key-header" | "basic";
2
+ export interface ConnectorRecord {
3
+ baseUrl: string;
4
+ host: string;
5
+ authScheme: AuthScheme;
6
+ /** Required when authScheme is "api-key-header"; the header the credential is sent in. */
7
+ headerName?: string;
8
+ }
9
+ type Registry = Record<string, ConnectorRecord>;
10
+ type Secrets = Record<string, string>;
11
+ export declare function readRegistry(platformRoot: string, accountId: string): Registry;
12
+ export declare function readSecrets(platformRoot: string, accountId: string): Secrets;
13
+ export declare function registerConnector(platformRoot: string, accountId: string, name: string, rec: ConnectorRecord, secret: string): void;
14
+ /** Remove a connector from both files. Returns whether it existed in either. */
15
+ export declare function deregisterConnector(platformRoot: string, accountId: string, name: string): boolean;
16
+ export declare function resolveConnector(platformRoot: string, accountId: string, name: string): {
17
+ rec: ConnectorRecord;
18
+ secret: string;
19
+ } | null;
20
+ export declare function listConnectors(platformRoot: string, accountId: string): {
21
+ name: string;
22
+ baseUrl: string;
23
+ }[];
24
+ export {};
25
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../src/lib/store.ts"],"names":[],"mappings":"AAGA,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAE/D,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,UAAU,CAAC;IACvB,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,KAAK,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;AAChD,KAAK,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AAyBtC,wBAAgB,YAAY,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,QAAQ,CAE9E;AAED,wBAAgB,WAAW,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,GACb,IAAI,CAON;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CASlG;AAED,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EACpB,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,GACX;IAAE,GAAG,EAAE,eAAe,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAKjD;AAED,wBAAgB,cAAc,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EAAE,CAK3G"}