@harness-gw/sdk 0.11.0 → 0.12.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 CHANGED
@@ -63,7 +63,7 @@ You need a running harness. Hermes is the primary one; see
63
63
  docker run --rm \
64
64
  -v "$PWD/config.yaml:/run/harness-gw/config.yaml:ro" \
65
65
  -v "$PWD/hermes-token:/run/secrets/hermes-token:ro" \
66
- ghcr.io/almogbaku/harness-gw:0.11.0 \
66
+ ghcr.io/almogbaku/harness-gw:0.12.0 \
67
67
  config check --config /run/harness-gw/config.yaml
68
68
  ```
69
69
 
@@ -73,7 +73,7 @@ You need a running harness. Hermes is the primary one; see
73
73
  docker run --rm -p 127.0.0.1:4100:4100 \
74
74
  -v "$PWD/config.yaml:/run/harness-gw/config.yaml:ro" \
75
75
  -v "$PWD/hermes-token:/run/secrets/hermes-token:ro" \
76
- ghcr.io/almogbaku/harness-gw:0.11.0 \
76
+ ghcr.io/almogbaku/harness-gw:0.12.0 \
77
77
  serve --config /run/harness-gw/config.yaml
78
78
  ```
79
79
 
@@ -1186,25 +1186,81 @@ var McpAppResourceReadRequestSchema2 = z4.strictObject({
1186
1186
  uri: z4.string().min(1).max(2048)
1187
1187
  });
1188
1188
  var MCP_APP_SANDBOX_PATH2 = "/mcp-app-sandbox.html";
1189
- var LOOPBACK_SOURCES = (scheme) => ["127.0.0.1", "localhost", "*.localhost"].map((host) => `${scheme}://${host}:*`);
1190
- var MCP_APP_SANDBOX_CSP2 = [
1191
- "default-src 'none'",
1192
- "script-src 'self' 'unsafe-inline' 'wasm-unsafe-eval' https:",
1193
- "style-src 'self' 'unsafe-inline' https:",
1194
- "img-src 'self' data: https:",
1195
- "font-src 'self' data: https:",
1196
- ["media-src 'self' data: https:", ...LOOPBACK_SOURCES("http")].join(" "),
1197
- [
1198
- "connect-src https: wss:",
1199
- ...LOOPBACK_SOURCES("http"),
1200
- ...LOOPBACK_SOURCES("ws")
1201
- ].join(" "),
1202
- "worker-src 'self' blob: data:",
1203
- "frame-src https:",
1204
- "base-uri https:",
1205
- "object-src 'none'",
1206
- "form-action 'none'",
1207
- "frame-ancestors 'self'"
1208
- ].join("; ");
1189
+ var POLICY_ORIGIN = new RegExp(`^https?://${HOST}${PORT}$`, "u");
1190
+ function isMcpAppPolicyOrigin2(value) {
1191
+ try {
1192
+ return POLICY_ORIGIN.test(value) && new URL(value).origin === value;
1193
+ } catch {
1194
+ return false;
1195
+ }
1196
+ }
1197
+ function ownHosts({
1198
+ frameAncestors,
1199
+ sandboxOrigin
1200
+ }) {
1201
+ const origins = [...frameAncestors, sandboxOrigin];
1202
+ const invalid = origins.find((origin) => !isMcpAppPolicyOrigin2(origin));
1203
+ if (invalid !== undefined)
1204
+ throw new Error(`Not an exact origin a sandbox policy can name: ${invalid}`);
1205
+ if (frameAncestors.includes(sandboxOrigin))
1206
+ throw new Error(`The sandbox origin is one of the host's: ${sandboxOrigin}`);
1207
+ return new Set(origins.map((origin) => new URL(origin).host));
1208
+ }
1209
+ function namesHost(domain, hosts) {
1210
+ try {
1211
+ return hosts.has(new URL(domain).host);
1212
+ } catch {
1213
+ return false;
1214
+ }
1215
+ }
1216
+ var CSP_LISTS = McpUiCspSchema2.keyof().options;
1217
+ function appliedMcpAppCsp2({
1218
+ csp,
1219
+ ...origins
1220
+ }) {
1221
+ const own = ownHosts(origins);
1222
+ const applied = {};
1223
+ for (const list of CSP_LISTS) {
1224
+ const domains = new Set((csp?.[list] ?? []).filter((domain) => isMcpAppCspDomain2(list, domain)).map((domain) => domain.toLowerCase()).filter((domain) => !namesHost(domain, own)));
1225
+ if (domains.size > 0)
1226
+ applied[list] = [...domains];
1227
+ }
1228
+ return Object.keys(applied).length > 0 ? applied : undefined;
1229
+ }
1230
+ function policyFileLocation(value, origins) {
1231
+ try {
1232
+ const url = new URL(value);
1233
+ if (!["http:", "https:"].includes(url.protocol) || !origins.includes(url.origin) || url.pathname.endsWith("/"))
1234
+ return;
1235
+ const path = url.pathname.split("/").map((segment) => encodeURIComponent(decodeURIComponent(segment)).replaceAll("'", "%27")).join("/");
1236
+ return `${url.origin}${path}`;
1237
+ } catch {
1238
+ return;
1239
+ }
1240
+ }
1241
+ var sources = (base, domains = []) => [...base, ...domains].join(" ") || "'none'";
1242
+ function mcpAppSandboxPolicy2({
1243
+ fileLocations = [],
1244
+ ...view
1245
+ }) {
1246
+ const applied = appliedMcpAppCsp2(view) ?? {};
1247
+ const files = fileLocations.flatMap((location) => policyFileLocation(location, view.frameAncestors) ?? []);
1248
+ const resource = applied.resourceDomains ?? [];
1249
+ return [
1250
+ "default-src 'none'",
1251
+ `script-src ${sources(["'self'", "'unsafe-inline'", "'wasm-unsafe-eval'"], resource)}`,
1252
+ `style-src ${sources(["'self'", "'unsafe-inline'"], resource)}`,
1253
+ `img-src ${sources(["'self'", "data:"], resource)}`,
1254
+ `font-src ${sources(["'self'", "data:"], resource)}`,
1255
+ `media-src ${sources(["'self'", "data:"], [...resource, ...files])}`,
1256
+ `connect-src ${sources(applied.connectDomains ?? [], files)}`,
1257
+ "worker-src 'self' blob: data:",
1258
+ `frame-src ${sources([], applied.frameDomains)}`,
1259
+ `base-uri ${sources([], applied.baseUriDomains)}`,
1260
+ "object-src 'none'",
1261
+ "form-action 'none'",
1262
+ `frame-ancestors ${sources([], view.frameAncestors)}`
1263
+ ].join("; ");
1264
+ }
1209
1265
 
1210
- export { SESSION_CATALOG_MAX_WINDOW2, RuntimeAuthStateSchema2, OperationCapabilitySchema2, RuntimeInfoSchema2, AgentAvatarSchema2, AgentCatalogEntrySchema2, AgentCatalogResponseSchema2, AgentUpdateFields2, writesAgentField2, AgentUpdateRequestSchema2, AgentUpdateResponseSchema2, SessionStatusSchema2, SessionPlatformSchema2, SessionSchema2, newestSessionFirst2, SessionCatalogResponseSchema2, StopReason2, ToolKind2, ToolLocationSchema2, DiffOperation2, DiffChangeSchema2, ToolDiffSchema2, SessionMessageErrorStatusSchema2, SessionMessageSchema2, SessionPlanActivityMessageSchema2, SessionCompactionActivityMessageSchema2, SessionChildActivityMessageSchema2, SessionActivityMessageSchema2, SessionHistoryResponseSchema2, SessionCreateRequestSchema2, SessionCreateResponseSchema2, SessionPatchRequestSchema2, TurnStopResponseSchema2, TurnSteerRequestSchema2, TurnSteerResponseSchema2, SlashCommandSchema2, MAX_SLASH_COMMANDS2, INTERACTION_PROTOCOL2, SessionWorkspaceCapabilitiesResponseSchema2, GuestRuntimeCapabilitiesResponseSchema2, SessionModelsResponseSchema2, SessionModelUpdateRequestSchema2, SessionModelUpdateResponseSchema2, SessionContextResponseSchema2, ArtifactDescriptorSchema2, SessionTodosResponseSchema2, SessionActivityResponseSchema2, SessionAttachmentStageRequestSchema2, SessionAttachmentStageResponseSchema2, SessionAudioResponseSchema2, SessionTranscriptionRequestSchema2, SessionTranscriptionResponseSchema2, SessionSpeechRequestSchema2, ErrorResponseSchema2, ACP_PROTOCOL_VERSION2, HGW_API_PREFIX2, HGW_ACP_PATH2, HGW_ACP_AGENTS_PATH2, hgwAcpAgentPath2, HGW_META_KEY2, HGW_EXTENSION_VERSION2, HGW_AUTH_METHOD_INVITE2, HGW_ATTACHMENT_URI_SCHEME2, HGW_ARTIFACT_URI_SCHEME2, HGW_METHODS2, HGW_PERMISSION_KIND_SESSION2, HGW_PLAN_ID2, HGW_JSONRPC_ERRORS2, HGW_MAX_FRAME_BYTES2, IdentifierSchema2, HgwExtensionsSchema2, HgwClientCapabilitiesMetaSchema2, HgwInitializeMetaSchema2, HgwLoginMetaSchema2, HgwSessionNewMetaSchema2, HgwSessionListMetaSchema2, HgwSessionSearchMetaSchema2, HgwSessionSearchResponseSchema2, HgwSessionInfoMetaSchema2, HgwSessionResumeMetaSchema2, HGW_REPLAY_POSITION2, HgwReplayPositionSchema2, HGW_REPLAY_BEFORE2, HgwReplayBeforeSchema2, HgwHistoryCursorSchema2, HgwHistoryPageResponseMetaSchema2, HgwHistoryPageTagSchema2, HgwSessionResumeResponseMetaSchema2, HgwPromptMetaSchema2, HgwSessionUpdateRequestSchema2, HgwSessionPartRequestSchema2, HgwSteerRequestSchema2, HgwSteerResponseSchema2, HgwFocusRequestSchema2, HgwAgentsListResponseSchema2, HgwAgentUpdateRequestSchema2, HgwAgentUpdateResponseSchema2, HgwTurnMetaSchema2, HgwNoticeMetaSchema2, HgwMessageMetaSchema2, HgwCostSchema2, HgwChildSessionMetaSchema2, HgwStateMetaSchema2, HgwChunkMetaSchema2, HgwToolCallMetaSchema2, HgwPlanMetaSchema2, HgwUsageMetaSchema2, HgwAvailableCommandsMetaSchema2, HgwPermissionMetaSchema2, HgwQuestionOptionSchema2, HgwQuestionSchema2, HgwElicitationMetaSchema2, HgwArtifactDescriptorSchema2, formatArtifactUri2, parseArtifactUri2, HgwComposerPrefillNotificationSchema2, HgwErrorNotificationSchema2, HGW_REQUEST_TEXT_MAX2, HgwActivityNotificationSchema2, PushCategorySchema2, categoryOf2, PushLocaleSchema2, PRESENCE_IDLE_MS2, PRESENCE_HEARTBEAT_MS2, PRESENCE_GRACE_MS2, PRESENCE_CLOSED_GRACE_MS2, COALESCE_WINDOW_MS2, PUSH_TEXT_LIMITS2, PushMessageSchema2, PushCategoriesSchema2, PushSubscriptionJsonSchema2, PushInfoSchema2, PushRegistrationSchema2, PushUnregistrationSchema2, CallToolResultSchema2, ReadResourceResultSchema2, McpUiCspSchema2, isMcpAppCspDomain2, McpUiPermissionsSchema2, McpAppFilesSchema2, McpAppViewSchema2, viewerFileResult2, McpAppToolCallRequestSchema2, McpAppResourceReadRequestSchema2, MCP_APP_SANDBOX_PATH2, MCP_APP_SANDBOX_CSP2 };
1266
+ export { SESSION_CATALOG_MAX_WINDOW2, RuntimeAuthStateSchema2, OperationCapabilitySchema2, RuntimeInfoSchema2, AgentAvatarSchema2, AgentCatalogEntrySchema2, AgentCatalogResponseSchema2, AgentUpdateFields2, writesAgentField2, AgentUpdateRequestSchema2, AgentUpdateResponseSchema2, SessionStatusSchema2, SessionPlatformSchema2, SessionSchema2, newestSessionFirst2, SessionCatalogResponseSchema2, StopReason2, ToolKind2, ToolLocationSchema2, DiffOperation2, DiffChangeSchema2, ToolDiffSchema2, SessionMessageErrorStatusSchema2, SessionMessageSchema2, SessionPlanActivityMessageSchema2, SessionCompactionActivityMessageSchema2, SessionChildActivityMessageSchema2, SessionActivityMessageSchema2, SessionHistoryResponseSchema2, SessionCreateRequestSchema2, SessionCreateResponseSchema2, SessionPatchRequestSchema2, TurnStopResponseSchema2, TurnSteerRequestSchema2, TurnSteerResponseSchema2, SlashCommandSchema2, MAX_SLASH_COMMANDS2, INTERACTION_PROTOCOL2, SessionWorkspaceCapabilitiesResponseSchema2, GuestRuntimeCapabilitiesResponseSchema2, SessionModelsResponseSchema2, SessionModelUpdateRequestSchema2, SessionModelUpdateResponseSchema2, SessionContextResponseSchema2, ArtifactDescriptorSchema2, SessionTodosResponseSchema2, SessionActivityResponseSchema2, SessionAttachmentStageRequestSchema2, SessionAttachmentStageResponseSchema2, SessionAudioResponseSchema2, SessionTranscriptionRequestSchema2, SessionTranscriptionResponseSchema2, SessionSpeechRequestSchema2, ErrorResponseSchema2, ACP_PROTOCOL_VERSION2, HGW_API_PREFIX2, HGW_ACP_PATH2, HGW_ACP_AGENTS_PATH2, hgwAcpAgentPath2, HGW_META_KEY2, HGW_EXTENSION_VERSION2, HGW_AUTH_METHOD_INVITE2, HGW_ATTACHMENT_URI_SCHEME2, HGW_ARTIFACT_URI_SCHEME2, HGW_METHODS2, HGW_PERMISSION_KIND_SESSION2, HGW_PLAN_ID2, HGW_JSONRPC_ERRORS2, HGW_MAX_FRAME_BYTES2, IdentifierSchema2, HgwExtensionsSchema2, HgwClientCapabilitiesMetaSchema2, HgwInitializeMetaSchema2, HgwLoginMetaSchema2, HgwSessionNewMetaSchema2, HgwSessionListMetaSchema2, HgwSessionSearchMetaSchema2, HgwSessionSearchResponseSchema2, HgwSessionInfoMetaSchema2, HgwSessionResumeMetaSchema2, HGW_REPLAY_POSITION2, HgwReplayPositionSchema2, HGW_REPLAY_BEFORE2, HgwReplayBeforeSchema2, HgwHistoryCursorSchema2, HgwHistoryPageResponseMetaSchema2, HgwHistoryPageTagSchema2, HgwSessionResumeResponseMetaSchema2, HgwPromptMetaSchema2, HgwSessionUpdateRequestSchema2, HgwSessionPartRequestSchema2, HgwSteerRequestSchema2, HgwSteerResponseSchema2, HgwFocusRequestSchema2, HgwAgentsListResponseSchema2, HgwAgentUpdateRequestSchema2, HgwAgentUpdateResponseSchema2, HgwTurnMetaSchema2, HgwNoticeMetaSchema2, HgwMessageMetaSchema2, HgwCostSchema2, HgwChildSessionMetaSchema2, HgwStateMetaSchema2, HgwChunkMetaSchema2, HgwToolCallMetaSchema2, HgwPlanMetaSchema2, HgwUsageMetaSchema2, HgwAvailableCommandsMetaSchema2, HgwPermissionMetaSchema2, HgwQuestionOptionSchema2, HgwQuestionSchema2, HgwElicitationMetaSchema2, HgwArtifactDescriptorSchema2, formatArtifactUri2, parseArtifactUri2, HgwComposerPrefillNotificationSchema2, HgwErrorNotificationSchema2, HGW_REQUEST_TEXT_MAX2, HgwActivityNotificationSchema2, PushCategorySchema2, categoryOf2, PushLocaleSchema2, PRESENCE_IDLE_MS2, PRESENCE_HEARTBEAT_MS2, PRESENCE_GRACE_MS2, PRESENCE_CLOSED_GRACE_MS2, COALESCE_WINDOW_MS2, PUSH_TEXT_LIMITS2, PushMessageSchema2, PushCategoriesSchema2, PushSubscriptionJsonSchema2, PushInfoSchema2, PushRegistrationSchema2, PushUnregistrationSchema2, CallToolResultSchema2, ReadResourceResultSchema2, McpUiCspSchema2, isMcpAppCspDomain2, McpUiPermissionsSchema2, McpAppFilesSchema2, McpAppViewSchema2, viewerFileResult2, McpAppToolCallRequestSchema2, McpAppResourceReadRequestSchema2, MCP_APP_SANDBOX_PATH2, isMcpAppPolicyOrigin2, appliedMcpAppCsp2, mcpAppSandboxPolicy2 };
@@ -199,13 +199,57 @@ export declare const McpAppResourceReadRequestSchema: z.ZodObject<{
199
199
  }, z.core.$strict>;
200
200
  export type McpAppResourceReadRequest = z.infer<typeof McpAppResourceReadRequestSchema>;
201
201
  /**
202
- * The MCP App sandbox gateway: a static page, served beside the workspace on
203
- * every listener, that holds only the relay creating the App's own frame. It
204
- * is a real document rather than `srcdoc` so it carries this policy instead of
205
- * inheriting the embedding page's, which on the guest surface forbids inline
206
- * scripts. The App frame inherits it too, so it is the widest any view may
207
- * reach — every source `buildMcpAppCsp` can grant — and the view's own policy,
208
- * injected into its document, narrows it to what it declared.
202
+ * The MCP App sandbox page: a static page that holds only the relay creating
203
+ * the App's own frame. A host serves it from a sandbox origin of its own,
204
+ * apart from its pages' origins as the spec requires, and frames it with
205
+ * `allow-scripts allow-same-origin`, so the view runs on that origin with
206
+ * storage of its own. The page is a real document rather than `srcdoc` so it
207
+ * carries the view's own policy, `mcpAppSandboxPolicy`, as its header; the
208
+ * view's `srcdoc` frame inherits it.
209
209
  */
210
210
  export declare const MCP_APP_SANDBOX_PATH = "/mcp-app-sandbox.html";
211
- export declare const MCP_APP_SANDBOX_CSP: string;
211
+ /** What one view's sandbox policy is built from. */
212
+ export type McpAppSandboxPolicyInput = {
213
+ /**
214
+ * The exact origins of the host's own pages, the only ones that may frame
215
+ * the sandbox page.
216
+ */
217
+ frameAncestors: readonly string[];
218
+ /** The exact origin the sandbox page is served from. */
219
+ sandboxOrigin: string;
220
+ /** The view's declared `_meta.ui.csp`. */
221
+ csp?: McpUiCsp | undefined;
222
+ /** The call's absolute file addresses; no pass is written. */
223
+ fileLocations?: readonly string[] | undefined;
224
+ };
225
+ /**
226
+ * Whether a sandbox policy can name `value` as a framing page or as the
227
+ * sandbox: an `http(s)` origin exactly as `URL` writes it, whose host is a name
228
+ * or an IPv4 address. `mcpAppSandboxPolicy` throws for any other, so a host
229
+ * checks its settings with this once, before it serves a view.
230
+ */
231
+ export declare function isMcpAppPolicyOrigin(value: string): boolean;
232
+ /**
233
+ * The domains a view's sandbox policy applies, per `_meta.ui.csp` list, as a
234
+ * host reports them in `hostCapabilities.sandbox.csp`: those
235
+ * `isMcpAppCspDomain` admits, lowercased and once each, without any that names
236
+ * the host and port of a framing page or of the sandbox itself, whatever its
237
+ * scheme. `undefined` when it applies none. Throws as `mcpAppSandboxPolicy`
238
+ * does for the origins.
239
+ */
240
+ export declare function appliedMcpAppCsp({ csp, ...origins }: Omit<McpAppSandboxPolicyInput, "fileLocations">): McpUiCsp | undefined;
241
+ /**
242
+ * One view's sandbox policy, sent as the sandbox page's header: the MCP Apps
243
+ * default policy (spec 2026-01-26), widened only by the domains
244
+ * `appliedMcpAppCsp` keeps and by the call's own file locations, each by its
245
+ * exact path, to read and to play; never allowing plugins or form posts, and
246
+ * framed only by `frameAncestors`. Views may compile WebAssembly, as a
247
+ * document renderer's decoders do.
248
+ *
249
+ * Anyone can ask for a sandbox page with any query, so every value is checked
250
+ * before it is written: an ancestor or a sandbox origin that is no exact
251
+ * origin (`isMcpAppPolicyOrigin`) throws, as does a sandbox origin among the
252
+ * ancestors, and a domain or a file location its rule refuses is dropped. A
253
+ * file location is kept only on a framing page's origin.
254
+ */
255
+ export declare function mcpAppSandboxPolicy({ fileLocations, ...view }: McpAppSandboxPolicyInput): string;
@@ -144,7 +144,9 @@ import {
144
144
  McpAppToolCallRequestSchema2,
145
145
  McpAppResourceReadRequestSchema2,
146
146
  MCP_APP_SANDBOX_PATH2,
147
- MCP_APP_SANDBOX_CSP2
147
+ isMcpAppPolicyOrigin2,
148
+ appliedMcpAppCsp2,
149
+ mcpAppSandboxPolicy2
148
150
  } from "../chunks/index.js";
149
151
  // protocol/audio.ts
150
152
  var RECORDING_MIME_TYPES = [
@@ -278,7 +280,6 @@ export {
278
280
  MAX_SPEECH_BYTES,
279
281
  MAX_SPEECH_TEXT_BYTES,
280
282
  MAX_TRANSCRIPT_BYTES,
281
- MCP_APP_SANDBOX_CSP2 as MCP_APP_SANDBOX_CSP,
282
283
  MCP_APP_SANDBOX_PATH2 as MCP_APP_SANDBOX_PATH,
283
284
  McpAppFilesSchema2 as McpAppFilesSchema,
284
285
  McpAppResourceReadRequestSchema2 as McpAppResourceReadRequestSchema,
@@ -342,10 +343,13 @@ export {
342
343
  TurnSteerRequestSchema2 as TurnSteerRequestSchema,
343
344
  TurnSteerResponseSchema2 as TurnSteerResponseSchema,
344
345
  TurnStopResponseSchema2 as TurnStopResponseSchema,
346
+ appliedMcpAppCsp2 as appliedMcpAppCsp,
345
347
  categoryOf2 as categoryOf,
346
348
  formatArtifactUri2 as formatArtifactUri,
347
349
  hgwAcpAgentPath2 as hgwAcpAgentPath,
348
350
  isMcpAppCspDomain2 as isMcpAppCspDomain,
351
+ isMcpAppPolicyOrigin2 as isMcpAppPolicyOrigin,
352
+ mcpAppSandboxPolicy2 as mcpAppSandboxPolicy,
349
353
  newestSessionFirst2 as newestSessionFirst,
350
354
  parseArtifactUri2 as parseArtifactUri,
351
355
  parseRecordingMime,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@harness-gw/sdk",
3
- "version": "0.11.0",
3
+ "version": "0.12.0",
4
4
  "description": "A gateway that puts Hermes, OpenClaw, and OpenCode behind one ACP WebSocket, and the browser client and protocol SDK for it.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",