@zackbart/connecta 0.7.8 → 0.8.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.
Files changed (187) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +67 -144
  3. package/dist/activity.d.ts +1 -1
  4. package/dist/activity.d.ts.map +1 -1
  5. package/dist/activity.js.map +1 -1
  6. package/dist/auth/bearer.d.ts +1 -1
  7. package/dist/auth/bearer.js +4 -4
  8. package/dist/auth/bearer.js.map +1 -1
  9. package/dist/auth/clerk.d.ts +1 -1
  10. package/dist/auth/clerk.js +1 -1
  11. package/dist/call-admission.d.ts +81 -0
  12. package/dist/call-admission.d.ts.map +1 -0
  13. package/dist/call-admission.js +345 -0
  14. package/dist/call-admission.js.map +1 -0
  15. package/dist/catalog-fingerprint.d.ts +20 -0
  16. package/dist/catalog-fingerprint.d.ts.map +1 -0
  17. package/dist/catalog-fingerprint.js +34 -0
  18. package/dist/catalog-fingerprint.js.map +1 -0
  19. package/dist/catalog-limits.d.ts +10 -0
  20. package/dist/catalog-limits.d.ts.map +1 -0
  21. package/dist/catalog-limits.js +10 -0
  22. package/dist/catalog-limits.js.map +1 -0
  23. package/dist/catalog-service.d.ts +138 -0
  24. package/dist/catalog-service.d.ts.map +1 -0
  25. package/dist/catalog-service.js +407 -0
  26. package/dist/catalog-service.js.map +1 -0
  27. package/dist/catalog.js +2 -2
  28. package/dist/catalog.js.map +1 -1
  29. package/dist/concurrency.d.ts +4 -0
  30. package/dist/concurrency.d.ts.map +1 -0
  31. package/dist/concurrency.js +31 -0
  32. package/dist/concurrency.js.map +1 -0
  33. package/dist/connectors/api.d.ts +3 -1
  34. package/dist/connectors/api.d.ts.map +1 -1
  35. package/dist/connectors/api.js +22 -11
  36. package/dist/connectors/api.js.map +1 -1
  37. package/dist/connectors/remote-mcp.d.ts +3 -1
  38. package/dist/connectors/remote-mcp.d.ts.map +1 -1
  39. package/dist/connectors/remote-mcp.js +44 -18
  40. package/dist/connectors/remote-mcp.js.map +1 -1
  41. package/dist/credential-health.d.ts +0 -22
  42. package/dist/credential-health.d.ts.map +1 -1
  43. package/dist/credential-health.js +14 -10
  44. package/dist/credential-health.js.map +1 -1
  45. package/dist/credentials.d.ts +3 -2
  46. package/dist/credentials.d.ts.map +1 -1
  47. package/dist/errors.d.ts +1 -1
  48. package/dist/errors.d.ts.map +1 -1
  49. package/dist/errors.js.map +1 -1
  50. package/dist/execute.d.ts +9 -8
  51. package/dist/execute.d.ts.map +1 -1
  52. package/dist/execute.js +144 -291
  53. package/dist/execute.js.map +1 -1
  54. package/dist/executor-result.d.ts +0 -3
  55. package/dist/executor-result.d.ts.map +1 -1
  56. package/dist/executor-result.js +2 -2
  57. package/dist/executor-result.js.map +1 -1
  58. package/dist/executors/quickjs-child.js +3 -3
  59. package/dist/executors/quickjs-child.js.map +1 -1
  60. package/dist/executors/quickjs-protocol.d.ts +4 -1
  61. package/dist/executors/quickjs-protocol.d.ts.map +1 -1
  62. package/dist/executors/quickjs-runtime.d.ts.map +1 -1
  63. package/dist/executors/quickjs-runtime.js +7 -2
  64. package/dist/executors/quickjs-runtime.js.map +1 -1
  65. package/dist/executors/quickjs.d.ts.map +1 -1
  66. package/dist/executors/quickjs.js +4 -1
  67. package/dist/executors/quickjs.js.map +1 -1
  68. package/dist/favicon.js +2 -2
  69. package/dist/favicon.js.map +1 -1
  70. package/dist/index.d.ts +6 -1
  71. package/dist/index.d.ts.map +1 -1
  72. package/dist/index.js +45 -17
  73. package/dist/index.js.map +1 -1
  74. package/dist/invocation.d.ts +96 -0
  75. package/dist/invocation.d.ts.map +1 -0
  76. package/dist/invocation.js +369 -0
  77. package/dist/invocation.js.map +1 -0
  78. package/dist/meta-tools.d.ts +11 -86
  79. package/dist/meta-tools.d.ts.map +1 -1
  80. package/dist/meta-tools.js +145 -485
  81. package/dist/meta-tools.js.map +1 -1
  82. package/dist/operator-ui/generated.d.ts +3 -0
  83. package/dist/operator-ui/generated.d.ts.map +1 -0
  84. package/dist/operator-ui/generated.js +5 -0
  85. package/dist/operator-ui/generated.js.map +1 -0
  86. package/dist/operator-ui/model.d.ts +94 -0
  87. package/dist/operator-ui/model.d.ts.map +1 -0
  88. package/dist/operator-ui/model.js +28 -0
  89. package/dist/operator-ui/model.js.map +1 -0
  90. package/dist/registry.d.ts +47 -6
  91. package/dist/registry.d.ts.map +1 -1
  92. package/dist/registry.js +356 -35
  93. package/dist/registry.js.map +1 -1
  94. package/dist/routes/activity.d.ts +3 -0
  95. package/dist/routes/activity.d.ts.map +1 -0
  96. package/dist/routes/activity.js +173 -0
  97. package/dist/routes/activity.js.map +1 -0
  98. package/dist/routes/credentials.d.ts +3 -0
  99. package/dist/routes/credentials.d.ts.map +1 -0
  100. package/dist/routes/credentials.js +181 -0
  101. package/dist/routes/credentials.js.map +1 -0
  102. package/dist/routes/mcp.d.ts +8 -0
  103. package/dist/routes/mcp.d.ts.map +1 -0
  104. package/dist/routes/mcp.js +383 -0
  105. package/dist/routes/mcp.js.map +1 -0
  106. package/dist/routes/oauth.d.ts +4 -0
  107. package/dist/routes/oauth.d.ts.map +1 -0
  108. package/dist/routes/oauth.js +268 -0
  109. package/dist/routes/oauth.js.map +1 -0
  110. package/dist/routes/shared.d.ts +97 -0
  111. package/dist/routes/shared.d.ts.map +1 -0
  112. package/dist/routes/shared.js +199 -0
  113. package/dist/routes/shared.js.map +1 -0
  114. package/dist/routes/ui.d.ts +3 -0
  115. package/dist/routes/ui.d.ts.map +1 -0
  116. package/dist/routes/ui.js +122 -0
  117. package/dist/routes/ui.js.map +1 -0
  118. package/dist/server.d.ts +9 -40
  119. package/dist/server.d.ts.map +1 -1
  120. package/dist/server.js +67 -1292
  121. package/dist/server.js.map +1 -1
  122. package/dist/skills.d.ts +0 -15
  123. package/dist/skills.d.ts.map +1 -1
  124. package/dist/skills.js +6 -5
  125. package/dist/skills.js.map +1 -1
  126. package/dist/storage/file.d.ts.map +1 -1
  127. package/dist/storage/file.js +3 -1
  128. package/dist/storage/file.js.map +1 -1
  129. package/dist/storage/memory.d.ts.map +1 -1
  130. package/dist/storage/memory.js +3 -1
  131. package/dist/storage/memory.js.map +1 -1
  132. package/dist/toolkits.d.ts +0 -22
  133. package/dist/toolkits.d.ts.map +1 -1
  134. package/dist/toolkits.js +2 -2
  135. package/dist/toolkits.js.map +1 -1
  136. package/dist/types.d.ts +64 -2
  137. package/dist/types.d.ts.map +1 -1
  138. package/dist/ui.d.ts +3 -93
  139. package/dist/ui.d.ts.map +1 -1
  140. package/dist/ui.js +26 -1389
  141. package/dist/ui.js.map +1 -1
  142. package/dist/version.d.ts +1 -1
  143. package/dist/version.js +1 -1
  144. package/package.json +15 -8
  145. package/src/activity.ts +5 -1
  146. package/src/auth/bearer.ts +4 -4
  147. package/src/auth/clerk.ts +1 -1
  148. package/src/call-admission.ts +522 -0
  149. package/src/catalog-fingerprint.ts +52 -0
  150. package/src/catalog-limits.ts +11 -0
  151. package/src/catalog-service.ts +601 -0
  152. package/src/catalog.ts +2 -2
  153. package/src/concurrency.ts +39 -0
  154. package/src/connectors/api.ts +25 -11
  155. package/src/connectors/remote-mcp.ts +55 -21
  156. package/src/credential-health.ts +13 -10
  157. package/src/credentials.ts +2 -2
  158. package/src/errors.ts +1 -1
  159. package/src/execute.ts +194 -377
  160. package/src/executor-result.ts +2 -2
  161. package/src/executors/quickjs-child.ts +8 -4
  162. package/src/executors/quickjs-protocol.ts +1 -1
  163. package/src/executors/quickjs-runtime.ts +5 -1
  164. package/src/executors/quickjs.ts +11 -8
  165. package/src/favicon.ts +2 -2
  166. package/src/index.ts +54 -17
  167. package/src/invocation.ts +527 -0
  168. package/src/meta-tools.ts +369 -797
  169. package/src/operator-ui/browser.css +413 -0
  170. package/src/operator-ui/browser.ts +1121 -0
  171. package/src/operator-ui/generated.ts +4 -0
  172. package/src/operator-ui/model.ts +127 -0
  173. package/src/registry.ts +489 -44
  174. package/src/routes/activity.ts +220 -0
  175. package/src/routes/credentials.ts +266 -0
  176. package/src/routes/mcp.ts +485 -0
  177. package/src/routes/oauth.ts +328 -0
  178. package/src/routes/shared.ts +330 -0
  179. package/src/routes/ui.ts +153 -0
  180. package/src/server.ts +70 -1702
  181. package/src/skills.ts +6 -5
  182. package/src/storage/file.ts +3 -1
  183. package/src/storage/memory.ts +3 -1
  184. package/src/toolkits.ts +2 -2
  185. package/src/types.ts +70 -2
  186. package/src/ui.ts +52 -1489
  187. package/src/version.ts +1 -1
@@ -0,0 +1,153 @@
1
+ import { CONNECTA_FAVICON_ICO } from "../favicon.js";
2
+ import {
3
+ buildUiData,
4
+ CONNECTA_FAVICON_SVG,
5
+ credentialManagementCapability,
6
+ operatorPageForPath,
7
+ renderUiHtml,
8
+ } from "../ui.js";
9
+ import {
10
+ authorize,
11
+ isToolkitRestricted,
12
+ privateJson,
13
+ restrictedOperatorSurface,
14
+ type RouteContext,
15
+ } from "./shared.js";
16
+
17
+ /**
18
+ * Headers that make an operator-supplied favicon body inert on this origin.
19
+ * The SVG route is the sharp one: `image/svg+xml` is an *active* content type,
20
+ * so a `<script>` inside a branding SVG would run on the deployment origin the
21
+ * moment anyone navigated straight to `/favicon.svg` — strictly more powerful
22
+ * than the `favicon.href` vector the branding gates close, because the payload
23
+ * is same-origin. Neutralizing the response rather than inspecting the body
24
+ * keeps every valid static SVG (the built-in mark included) byte-identical:
25
+ *
26
+ * - `sandbox` (no tokens ⇒ every restriction) drops the document into an opaque
27
+ * origin with scripting off, so even a script that ran would have nothing to
28
+ * reach.
29
+ * - `default-src 'none'` denies script, network, and framing outright.
30
+ * - `style-src 'unsafe-inline'` is the single allowance: the default mark styles
31
+ * itself inline to follow the OS colour scheme, and CSS cannot script.
32
+ * - `nosniff` keeps the declared type authoritative in both directions — an SVG
33
+ * can never be re-read as HTML, and `.ico` bytes can never be re-read as SVG.
34
+ *
35
+ * `.ico` bodies are deliberately in scope: they are inert bytes rather than
36
+ * active content, so they are still served verbatim, but they carry the same
37
+ * headers so the invariant is "every favicon route is neutralized" rather than
38
+ * "whichever route got attention".
39
+ */
40
+ const INERT_ICON_HEADERS = {
41
+ "Content-Security-Policy":
42
+ "default-src 'none'; style-src 'unsafe-inline'; sandbox",
43
+ "X-Content-Type-Options": "nosniff",
44
+ };
45
+
46
+ /** Per-request base64 nonce for an operator shell's scripts (Node 20+ and Workers). */
47
+ function uiScriptNonce(): string {
48
+ const bytes = crypto.getRandomValues(new Uint8Array(16));
49
+ let binary = "";
50
+ for (const byte of bytes) binary += String.fromCharCode(byte);
51
+ return btoa(binary);
52
+ }
53
+
54
+ export async function routeUi(
55
+ context: RouteContext,
56
+ ): Promise<Response | null> {
57
+ const { request, url, path, baseUrl, opts, defer, sweepCredentials } =
58
+ context;
59
+ if (request.method === "GET" && path === "/favicon.svg") {
60
+ return new Response(opts.branding?.favicon?.svg ?? CONNECTA_FAVICON_SVG, {
61
+ headers: {
62
+ "Content-Type": "image/svg+xml",
63
+ "Cache-Control": "public, max-age=86400",
64
+ ...INERT_ICON_HEADERS,
65
+ },
66
+ });
67
+ }
68
+ if (request.method === "GET" && path === "/favicon.ico") {
69
+ return new Response(opts.branding?.favicon?.ico ?? CONNECTA_FAVICON_ICO, {
70
+ headers: {
71
+ "Content-Type": "image/x-icon",
72
+ "Cache-Control": "public, max-age=86400",
73
+ ...INERT_ICON_HEADERS,
74
+ },
75
+ });
76
+ }
77
+ if (path === "/ui") {
78
+ if (request.method !== "GET") {
79
+ return privateJson({ error: "method not allowed" }, { status: 405 });
80
+ }
81
+ const target = new URL(`/${url.search}`, baseUrl);
82
+ return new Response(null, {
83
+ status: 308,
84
+ headers: { Location: target.toString() },
85
+ });
86
+ }
87
+
88
+ const operatorPage = operatorPageForPath(path);
89
+ if (operatorPage) {
90
+ if (request.method !== "GET" && request.method !== "HEAD") {
91
+ return privateJson({ error: "method not allowed" }, { status: 405 });
92
+ }
93
+ // Open shell — carries no operator data; everything comes from the
94
+ // authenticated /ui/* APIs after the browser establishes a session.
95
+ const uiAuth = opts.auth.find((provider) => provider.uiAuth)?.uiAuth;
96
+ const mcpUrl = new URL("/mcp", baseUrl).toString();
97
+ // Nonce the page's inline script (and the Clerk loader). 'strict-dynamic'
98
+ // lets scripts the nonced Clerk loader injects at runtime execute; the
99
+ // https:/'unsafe-inline' fallbacks are ignored by CSP3 browsers that
100
+ // honour the nonce and only cover legacy ones. No default-src, so Clerk's
101
+ // style/font/network needs and the page's inline <style> stay unrestricted
102
+ // — only script execution, the XSS sink, is gated.
103
+ const nonce = uiScriptNonce();
104
+ return new Response(
105
+ request.method === "HEAD"
106
+ ? null
107
+ : renderUiHtml(uiAuth, mcpUrl, opts.branding, nonce, operatorPage),
108
+ {
109
+ status: 200,
110
+ headers: {
111
+ "Content-Type": "text/html; charset=utf-8",
112
+ "Content-Security-Policy":
113
+ `script-src 'nonce-${nonce}' 'strict-dynamic' https: 'unsafe-inline'; ` +
114
+ "object-src 'none'; base-uri 'none'; frame-ancestors 'none'",
115
+ "X-Content-Type-Options": "nosniff",
116
+ },
117
+ },
118
+ );
119
+ }
120
+ if (path !== "/ui/data") return null;
121
+
122
+ const authz = await authorize(request, baseUrl, opts.auth, opts.logger);
123
+ if (!authz.ok) return authz.response;
124
+ if (isToolkitRestricted(authz.toolkitBinding)) {
125
+ return restrictedOperatorSurface();
126
+ }
127
+ // After the restriction check, not before: an identity that may not
128
+ // read this surface should not get to trigger background work from it.
129
+ sweepCredentials();
130
+ const eligibleClerkOperator = authz.uiAdminEligible === true;
131
+ const credentialManagement = credentialManagementCapability({
132
+ eligibleClerkOperator,
133
+ hasCredentialSlots: opts.registry
134
+ .listConnectors()
135
+ .some((connector) => Boolean(connector.credential)),
136
+ hasCredentialVault: Boolean(opts.credentialVault),
137
+ });
138
+ const data = await buildUiData(
139
+ opts.registry,
140
+ baseUrl,
141
+ opts.serverInfo,
142
+ // The static headless bearer may read connector health, but only a
143
+ // Clerk-authenticated operator receives credential metadata.
144
+ eligibleClerkOperator ? opts.credentialVault : undefined,
145
+ Boolean(opts.activity?.list),
146
+ credentialManagement,
147
+ opts.toolkits,
148
+ defer,
149
+ eligibleClerkOperator,
150
+ opts.discoveryConcurrency,
151
+ );
152
+ return privateJson(data);
153
+ }