@ifc-lite/flow-nodes 0.3.1 → 0.5.1

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 (94) hide show
  1. package/README.md +1 -0
  2. package/dist/aps-client.d.ts +55 -0
  3. package/dist/aps-client.d.ts.map +1 -0
  4. package/dist/aps-client.js +194 -0
  5. package/dist/aps-client.js.map +1 -0
  6. package/dist/aps-nodes.d.ts +3 -0
  7. package/dist/aps-nodes.d.ts.map +1 -0
  8. package/dist/aps-nodes.js +192 -0
  9. package/dist/aps-nodes.js.map +1 -0
  10. package/dist/aps-table.d.ts +24 -0
  11. package/dist/aps-table.d.ts.map +1 -0
  12. package/dist/aps-table.js +123 -0
  13. package/dist/aps-table.js.map +1 -0
  14. package/dist/base64.d.ts +8 -0
  15. package/dist/base64.d.ts.map +1 -0
  16. package/dist/base64.js +59 -0
  17. package/dist/base64.js.map +1 -0
  18. package/dist/bcf-client.d.ts +36 -0
  19. package/dist/bcf-client.d.ts.map +1 -0
  20. package/dist/bcf-client.js +108 -0
  21. package/dist/bcf-client.js.map +1 -0
  22. package/dist/bcf-nodes.d.ts +3 -0
  23. package/dist/bcf-nodes.d.ts.map +1 -0
  24. package/dist/bcf-nodes.js +181 -0
  25. package/dist/bcf-nodes.js.map +1 -0
  26. package/dist/documents-fetch.d.ts +23 -0
  27. package/dist/documents-fetch.d.ts.map +1 -0
  28. package/dist/documents-fetch.js +48 -0
  29. package/dist/documents-fetch.js.map +1 -0
  30. package/dist/documents-nodes.d.ts +5 -0
  31. package/dist/documents-nodes.d.ts.map +1 -0
  32. package/dist/documents-nodes.js +167 -0
  33. package/dist/documents-nodes.js.map +1 -0
  34. package/dist/host.d.ts +28 -0
  35. package/dist/host.d.ts.map +1 -1
  36. package/dist/host.js.map +1 -1
  37. package/dist/http-request-node.d.ts +9 -0
  38. package/dist/http-request-node.d.ts.map +1 -0
  39. package/dist/http-request-node.js +109 -0
  40. package/dist/http-request-node.js.map +1 -0
  41. package/dist/index.d.ts +20 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +34 -5
  44. package/dist/index.js.map +1 -1
  45. package/dist/model-nodes.d.ts.map +1 -1
  46. package/dist/model-nodes.js +11 -6
  47. package/dist/model-nodes.js.map +1 -1
  48. package/dist/open-model-node.d.ts +3 -0
  49. package/dist/open-model-node.d.ts.map +1 -0
  50. package/dist/open-model-node.js +47 -0
  51. package/dist/open-model-node.js.map +1 -0
  52. package/dist/script-node.d.ts.map +1 -1
  53. package/dist/script-node.js +55 -21
  54. package/dist/script-node.js.map +1 -1
  55. package/dist/secrets.d.ts +88 -0
  56. package/dist/secrets.d.ts.map +1 -0
  57. package/dist/secrets.js +202 -0
  58. package/dist/secrets.js.map +1 -0
  59. package/dist/speckle/client.d.ts +52 -0
  60. package/dist/speckle/client.d.ts.map +1 -0
  61. package/dist/speckle/client.js +153 -0
  62. package/dist/speckle/client.js.map +1 -0
  63. package/dist/speckle/geometry.d.ts +37 -0
  64. package/dist/speckle/geometry.d.ts.map +1 -0
  65. package/dist/speckle/geometry.js +126 -0
  66. package/dist/speckle/geometry.js.map +1 -0
  67. package/dist/speckle/mapping.d.ts +62 -0
  68. package/dist/speckle/mapping.d.ts.map +1 -0
  69. package/dist/speckle/mapping.js +208 -0
  70. package/dist/speckle/mapping.js.map +1 -0
  71. package/dist/speckle/parameters.d.ts +49 -0
  72. package/dist/speckle/parameters.d.ts.map +1 -0
  73. package/dist/speckle/parameters.js +95 -0
  74. package/dist/speckle/parameters.js.map +1 -0
  75. package/dist/speckle/refusals.d.ts +45 -0
  76. package/dist/speckle/refusals.d.ts.map +1 -0
  77. package/dist/speckle/refusals.js +40 -0
  78. package/dist/speckle/refusals.js.map +1 -0
  79. package/dist/speckle/units.d.ts +13 -0
  80. package/dist/speckle/units.d.ts.map +1 -0
  81. package/dist/speckle/units.js +59 -0
  82. package/dist/speckle/units.js.map +1 -0
  83. package/dist/speckle/url.d.ts +35 -0
  84. package/dist/speckle/url.d.ts.map +1 -0
  85. package/dist/speckle/url.js +48 -0
  86. package/dist/speckle/url.js.map +1 -0
  87. package/dist/speckle-receive-node.d.ts +9 -0
  88. package/dist/speckle-receive-node.d.ts.map +1 -0
  89. package/dist/speckle-receive-node.js +180 -0
  90. package/dist/speckle-receive-node.js.map +1 -0
  91. package/dist/xlsx-nodes.d.ts.map +1 -1
  92. package/dist/xlsx-nodes.js +1 -40
  93. package/dist/xlsx-nodes.js.map +1 -1
  94. package/package.json +13 -11
@@ -0,0 +1,3 @@
1
+ import { type FlowNodeDef } from './host.js';
2
+ export declare const openModelNode: FlowNodeDef;
3
+ //# sourceMappingURL=open-model-node.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-model-node.d.ts","sourceRoot":"","sources":["../src/open-model-node.ts"],"names":[],"mappings":"AAiBA,OAAO,EAAkC,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAE7E,eAAO,MAAM,aAAa,EAAE,WA2B3B,CAAC"}
@@ -0,0 +1,47 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * `model.openFromSource` — open a file a previous node fetched (typically
6
+ * `documents.download`) as a model, through the host's own load path
7
+ * (`FlowHost.openModel`): the viewer's canonical `addModel`/`loadFile`
8
+ * pipeline, or the CLI's / MCP's headless loader. The node never parses
9
+ * the bytes itself, so no second ingest pipeline exists.
10
+ *
11
+ * The `modelId` output is what sequences the rest of the graph: wire it
12
+ * into `model.select` / `model.byType`'s `modelId` input so those reads
13
+ * run after the model is open and address it.
14
+ */
15
+ import { fromBase64 } from './base64.js';
16
+ import { requireCapability, SCALAR_ITEM } from './host.js';
17
+ export const openModelNode = {
18
+ type: 'model.openFromSource',
19
+ title: 'Open model from source',
20
+ category: 'model',
21
+ doc: 'Opens a downloaded IFC file (base64 `data`, e.g. from Download document) as a model on the host. Wire `modelId` into a model read node to query the opened model.',
22
+ inputs: [
23
+ { name: 'data', type: SCALAR_ITEM },
24
+ { name: 'name', type: SCALAR_ITEM, optional: true, nullable: true },
25
+ ],
26
+ outputs: [{ name: 'modelId', type: SCALAR_ITEM }],
27
+ params: [{ name: 'name', kind: 'string', default: 'model.ifc', doc: 'File name, used when the `name` input is not wired; its extension picks the format.' }],
28
+ capabilities: ['model.create'],
29
+ requires: { backend: ['openModel'] },
30
+ // Loading a model changes what every later read sees, so it is a write
31
+ // (never memoised, and it advances the cache's write generation).
32
+ writes: 'model',
33
+ volatile: true,
34
+ run: async (ctx, i, p) => {
35
+ requireCapability(ctx, 'model.create');
36
+ const open = ctx.host.openModel;
37
+ if (!open)
38
+ throw new Error('model.openFromSource: this host cannot open models');
39
+ const bytes = fromBase64(typeof i.data === 'string' ? i.data : '');
40
+ if (bytes.byteLength === 0)
41
+ throw new Error('model.openFromSource: "data" is empty');
42
+ const name = typeof i.name === 'string' && i.name.length > 0 ? i.name : typeof p.name === 'string' && p.name.length > 0 ? p.name : 'model.ifc';
43
+ const { modelId } = await open.call(ctx.host, bytes, name);
44
+ return { modelId };
45
+ },
46
+ };
47
+ //# sourceMappingURL=open-model-node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"open-model-node.js","sourceRoot":"","sources":["../src/open-model-node.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAoB,MAAM,WAAW,CAAC;AAE7E,MAAM,CAAC,MAAM,aAAa,GAAgB;IACxC,IAAI,EAAE,sBAAsB;IAC5B,KAAK,EAAE,wBAAwB;IAC/B,QAAQ,EAAE,OAAO;IACjB,GAAG,EAAE,mKAAmK;IACxK,MAAM,EAAE;QACN,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE;QACnC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,IAAI,EAAE;KACpE;IACD,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACjD,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,GAAG,EAAE,qFAAqF,EAAE,CAAC;IAC5J,YAAY,EAAE,CAAC,cAAc,CAAC;IAC9B,QAAQ,EAAE,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,EAAE;IACpC,uEAAuE;IACvE,kEAAkE;IAClE,MAAM,EAAE,OAAO;IACf,QAAQ,EAAE,IAAI;IACd,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE;QACvB,iBAAiB,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;QACvC,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC;QAChC,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACjF,MAAM,KAAK,GAAG,UAAU,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACnE,IAAI,KAAK,CAAC,UAAU,KAAK,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QACrF,MAAM,IAAI,GAAG,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC;QAC/I,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,CAAC;IACrB,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"script-node.d.ts","sourceRoot":"","sources":["../src/script-node.ts"],"names":[],"mappings":"AAwBA,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AAiF9F,eAAO,MAAM,UAAU,EAAE,WAgBxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,WAsB5B,CAAC"}
1
+ {"version":3,"file":"script-node.d.ts","sourceRoot":"","sources":["../src/script-node.ts"],"names":[],"mappings":"AA8BA,OAAO,EAAmD,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AA0H9F,eAAO,MAAM,UAAU,EAAE,WAgBxB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,WAsB5B,CAAC"}
@@ -17,38 +17,57 @@
17
17
  * no `bcf`, `ids`, `spatial`); that difference is documented, not papered
18
18
  * over. Sandbox permissions are derived from the graph's grants: mutation
19
19
  * is only enabled when a `model.mutate` grant exists.
20
+ *
21
+ * A lane whose code made a network request calls `ctx.markVolatile()`, so
22
+ * the scheduler does not memoise that run: rerunning the graph fetches
23
+ * again instead of replaying a stale response. A script that never calls
24
+ * `bim.network.fetch` stays memoisable even in a graph holding a grant.
20
25
  */
21
26
  import { createSandbox } from '@ifc-lite/sandbox';
22
27
  import { ANY_ITEM, ANY_LIST, requireCapability } from './host.js';
23
28
  /**
24
- * One sandbox per (BimContext, permission set), kept for the lifetime of
25
- * the context: QuickJS module init is the expensive part, and a graph with
26
- * several Script nodes (or a re-run) must not pay it per lane. Created here
27
- * rather than through `bim.sandbox` because that path dynamically imports
28
- * `@ifc-lite/sandbox` relative to the SDK package, which a pnpm-isolated
29
- * install cannot resolve headlessly.
29
+ * One sandbox per (BimContext, transport, permission set), kept for the
30
+ * lifetime of the context: QuickJS module init is the expensive part, and a
31
+ * graph with several Script nodes (or a re-run) must not pay it per lane.
32
+ * Created here rather than through `bim.sandbox` because that path
33
+ * dynamically imports `@ifc-lite/sandbox` relative to the SDK package, which
34
+ * a pnpm-isolated install cannot resolve headlessly.
30
35
  */
31
36
  const sandboxes = new WeakMap();
32
- function sandboxFor(bim, permissions, timeoutMs) {
33
- const key = JSON.stringify({ permissions, timeoutMs });
37
+ function sandboxFor(bim, permissions, timeoutMs, networkGrants, transport) {
38
+ const key = JSON.stringify({ permissions, timeoutMs, networkGrants });
34
39
  let perContext = sandboxes.get(bim);
35
40
  if (!perContext) {
36
41
  perContext = new Map();
37
42
  sandboxes.set(bim, perContext);
38
43
  }
39
- let pending = perContext.get(key);
40
- if (!pending) {
44
+ let perTransport = perContext.get(transport);
45
+ if (!perTransport) {
46
+ perTransport = new Map();
47
+ perContext.set(transport, perTransport);
48
+ }
49
+ const cache = perTransport;
50
+ let entry = cache.get(key);
51
+ if (!entry) {
52
+ const counting = (url, init) => {
53
+ created.requests += 1;
54
+ return transport ? transport(url, init) : fetch(url, init);
55
+ };
41
56
  // A rejected creation (a wasm load failure, a transient resource limit)
42
57
  // must not be cached: every later lane would await the same rejection for
43
58
  // the lifetime of the context, turning one hiccup into a dead node.
44
- pending = createSandbox(bim, { permissions, limits: { timeoutMs } }).catch((err) => {
45
- if (perContext.get(key) === pending)
46
- perContext.delete(key);
59
+ const sandbox = createSandbox(bim, {
60
+ permissions, limits: { timeoutMs }, network: { grants: networkGrants, transport: counting },
61
+ }).catch((err) => {
62
+ if (cache.get(key) === created)
63
+ cache.delete(key);
47
64
  throw err;
48
65
  });
49
- perContext.set(key, pending);
66
+ const created = { sandbox, requests: 0 };
67
+ entry = created;
68
+ cache.set(key, entry);
50
69
  }
51
- return pending;
70
+ return entry;
52
71
  }
53
72
  /** Evaluate `params.code` with `inputs` in scope and return its last expression. */
54
73
  async function evaluate(ctx, inputs, params) {
@@ -57,6 +76,7 @@ async function evaluate(ctx, inputs, params) {
57
76
  // read the model through a capability the graph never had.
58
77
  requireCapability(ctx, 'model.read');
59
78
  const grants = ctx.host.grants;
79
+ const networkGrants = ctx.host.networkGrants ?? [];
60
80
  const has = (scope, action) => !grants || grants.some((g) => g.scope === scope && g.action === action);
61
81
  const permissions = {
62
82
  query: true,
@@ -67,6 +87,9 @@ async function evaluate(ctx, inputs, params) {
67
87
  export: has('export', 'create'),
68
88
  lens: true,
69
89
  files: true,
90
+ // `bim.network` exists only when the graph holds a `network.fetch` grant;
91
+ // every call is still checked against those grants (#5446 review).
92
+ network: networkGrants.some((g) => g.scope === 'network' && g.action === 'fetch'),
70
93
  };
71
94
  const injected = JSON.stringify({ a: inputs.a ?? null, b: inputs.b ?? null, c: inputs.c ?? null });
72
95
  // Every lane shares one sandbox, and QuickJS evaluates a program in the
@@ -79,12 +102,23 @@ async function evaluate(ctx, inputs, params) {
79
102
  // `inputs` in scope, and the last expression as the value (`eval` returns
80
103
  // its program's completion value, which a function body would not).
81
104
  const code = `(function (inputs) { return eval(${JSON.stringify(String(params.code ?? ''))}); })(${injected})`;
82
- const sandbox = await sandboxFor(ctx.host.bim, permissions, Number(params.timeoutMs) || 30_000);
83
- // Plain JavaScript by contract: skipping the TypeScript strip avoids
84
- // initialising esbuild-wasm, which only works in the browser. It is also
85
- // what keeps the wrapper above honest — the source reaches `eval`
86
- // verbatim, not as something a transpiler rewrote.
87
- const result = await sandbox.eval(code, { typescript: false });
105
+ const entry = sandboxFor(ctx.host.bim, permissions, Number(params.timeoutMs) || 30_000, networkGrants, ctx.host.networkTransport);
106
+ const sandbox = await entry.sandbox;
107
+ const requestsBefore = entry.requests;
108
+ let result;
109
+ try {
110
+ // Plain JavaScript by contract: skipping the TypeScript strip avoids
111
+ // initialising esbuild-wasm, which only works in the browser. It is also
112
+ // what keeps the wrapper above honest — the source reaches `eval`
113
+ // verbatim, not as something a transpiler rewrote.
114
+ result = await sandbox.eval(code, { typescript: false });
115
+ }
116
+ finally {
117
+ // In `finally`: a lane that fetched and then threw yields null under
118
+ // lifting, and that null must not be memoised either.
119
+ if (entry.requests !== requestsBefore)
120
+ ctx.markVolatile?.();
121
+ }
88
122
  for (const entry of result.logs) {
89
123
  const level = entry.level === 'error' ? 'error' : entry.level === 'warn' ? 'warn' : 'info';
90
124
  ctx.log(level, entry.args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' '));
@@ -1 +1 @@
1
- {"version":3,"file":"script-node.js","sourceRoot":"","sources":["../src/script-node.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"script-node.js","sourceRoot":"","sources":["../src/script-node.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Secrets from the host environment (#5167 phase 3.5).
3
+ *
4
+ * A node param references a secret with `{{secret:NAME}}` inside a
5
+ * string value (or a string nested inside a `json`-kind param, e.g. a
6
+ * header map). The grammar itself is recognised by `@ifc-lite/flow`'s
7
+ * `referencedSecrets` (availability needs it too); this module is the one
8
+ * place declared-vs-referenced is cross-checked and `process.env` is read —
9
+ * shared by `packages/cli/src/commands/flow.ts` (`flow run`) and
10
+ * `packages/mcp/src/tools/flow.ts` (`run_flow`), the only two callers
11
+ * allowed to read `process.env` for a flow graph. The viewer never calls
12
+ * this module: `HostFeatures.secrets` is always the empty set there, so
13
+ * a graph referencing a secret shows `unavailable` before it runs (see
14
+ * `availability.ts`), not this module's validation error.
15
+ *
16
+ * Two checks run BEFORE any node executes:
17
+ * 1. every `{{secret:NAME}}` reference must be covered by a declared
18
+ * `secret.read:NAME` capability in the graph — an undeclared
19
+ * reference is a validation error, not a silently-empty string;
20
+ * 2. every declared-and-referenced secret must actually be set in the
21
+ * environment — a referenced-but-unset secret is also a validation
22
+ * error, not an empty string interpolated into a request.
23
+ *
24
+ * Redaction (`buildRedactionMap` / `redactDeep`) is a separate, later
25
+ * step the caller applies at the OUTER boundary — right before writing
26
+ * to stdout, an MCP response, or a log sink — so a secret value that
27
+ * reaches a remote response body (a server echoing back an Authorization
28
+ * header) and comes back into the run's own output is still caught, not
29
+ * just the point where `{{secret:NAME}}` was first substituted. See the
30
+ * module doc trade-offs below on the minimum-length cutoff.
31
+ */
32
+ import { referencedSecrets, type FlowDocument } from '@ifc-lite/flow';
33
+ export { referencedSecrets };
34
+ export interface SecretValidationError {
35
+ readonly nodeId: string;
36
+ readonly param: string;
37
+ readonly name: string;
38
+ readonly reason: 'undeclared' | 'unset';
39
+ readonly message: string;
40
+ }
41
+ /** Every `secret:NAME` the graph's capabilities declare (from `secret.read:<NAME>` grants). */
42
+ export declare function declaredSecrets(doc: FlowDocument): ReadonlySet<string>;
43
+ /**
44
+ * Validate every `{{secret:NAME}}` reference against the graph's declared
45
+ * capabilities AND the environment, before any node runs. Returns an empty
46
+ * array when the graph is clean (including "no secrets used at all").
47
+ */
48
+ export declare function validateSecretReferences(doc: FlowDocument, env: Readonly<Record<string, string | undefined>>): SecretValidationError[];
49
+ /** Resolve every declared-and-referenced secret's value from `env`. Call only after `validateSecretReferences` returns no errors. */
50
+ export declare function resolveSecretValues(doc: FlowDocument, env: Readonly<Record<string, string | undefined>>): ReadonlyMap<string, string>;
51
+ /** Return a new document with every `{{secret:NAME}}` reference in node params replaced by its resolved value. The input document is never mutated. */
52
+ export declare function interpolateSecrets(doc: FlowDocument, values: ReadonlyMap<string, string>): FlowDocument;
53
+ /** Minimum secret length worth redacting (see module doc): shorter values risk mass-redacting incidental substrings of ordinary text. */
54
+ export declare const MIN_REDACTED_SECRET_LENGTH = 6;
55
+ /**
56
+ * Reverse map (value → marker) for every resolved secret at least
57
+ * `MIN_REDACTED_SECRET_LENGTH` characters long. A secret shorter than
58
+ * that is a real gap (documented, not silently accepted): a 4-character
59
+ * token could coincide with ordinary text often enough that scrubbing it
60
+ * everywhere would make legitimate output unreadable, so this module
61
+ * accepts that a very short secret is not redactable by substring match
62
+ * at all.
63
+ */
64
+ export declare function buildRedactionMap(values: ReadonlyMap<string, string>): ReadonlyMap<string, string>;
65
+ /**
66
+ * Replace every occurrence of a redacted secret value with its marker, in ONE
67
+ * pass, trying the longest value first at each position. Sequential
68
+ * replacement let a shorter secret inside a longer one match first
69
+ * (`abcdef` inside `abcdefghi` left `<secret:A>ghi`, exposing B's suffix),
70
+ * and could match inside a marker already written (#5446 review).
71
+ */
72
+ export declare function redactText(text: string, redaction: ReadonlyMap<string, string>): string;
73
+ /**
74
+ * Walk an arbitrary JSON-ish value (a run summary, a log entry, a thrown
75
+ * error's message) and redact every string found, at any depth — this is
76
+ * what catches a secret that travelled through a response body and back
77
+ * into the run's own output, not just the literal param it was
78
+ * interpolated into.
79
+ */
80
+ /**
81
+ * The env names a host may report as available secrets: set, and long
82
+ * enough to be redacted. `resolveSecretValues` refuses a shorter value, so
83
+ * counting it as available made `flow validate` pass a graph the run then
84
+ * refused (#5446 review).
85
+ */
86
+ export declare function usableSecretNames(env: Readonly<Record<string, string | undefined>>): string[];
87
+ export declare function redactDeep<T>(value: T, redaction: ReadonlyMap<string, string>): T;
88
+ //# sourceMappingURL=secrets.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.d.ts","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,iBAAiB,EAAqB,KAAK,YAAY,EAAiB,MAAM,gBAAgB,CAAC;AAExG,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAG7B,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC;IACxC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;CAC1B;AAED,+FAA+F;AAC/F,wBAAgB,eAAe,CAAC,GAAG,EAAE,YAAY,GAAG,WAAW,CAAC,MAAM,CAAC,CAWtE;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,qBAAqB,EAAE,CAyBtI;AAED,qIAAqI;AACrI,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,YAAY,EAAE,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAkBrI;AAaD,uJAAuJ;AACvJ,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,YAAY,CAQvG;AAED,yIAAyI;AACzI,eAAO,MAAM,0BAA0B,IAAI,CAAC;AAE5C;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAWlG;AAMD;;;;;;GAMG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,CAKvF;AAED;;;;;;GAMG;AACH;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC,GAAG,MAAM,EAAE,CAI7F;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,CAAC,CAejF"}
@@ -0,0 +1,202 @@
1
+ /* This Source Code Form is subject to the terms of the Mozilla Public
2
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
3
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4
+ /**
5
+ * Secrets from the host environment (#5167 phase 3.5).
6
+ *
7
+ * A node param references a secret with `{{secret:NAME}}` inside a
8
+ * string value (or a string nested inside a `json`-kind param, e.g. a
9
+ * header map). The grammar itself is recognised by `@ifc-lite/flow`'s
10
+ * `referencedSecrets` (availability needs it too); this module is the one
11
+ * place declared-vs-referenced is cross-checked and `process.env` is read —
12
+ * shared by `packages/cli/src/commands/flow.ts` (`flow run`) and
13
+ * `packages/mcp/src/tools/flow.ts` (`run_flow`), the only two callers
14
+ * allowed to read `process.env` for a flow graph. The viewer never calls
15
+ * this module: `HostFeatures.secrets` is always the empty set there, so
16
+ * a graph referencing a secret shows `unavailable` before it runs (see
17
+ * `availability.ts`), not this module's validation error.
18
+ *
19
+ * Two checks run BEFORE any node executes:
20
+ * 1. every `{{secret:NAME}}` reference must be covered by a declared
21
+ * `secret.read:NAME` capability in the graph — an undeclared
22
+ * reference is a validation error, not a silently-empty string;
23
+ * 2. every declared-and-referenced secret must actually be set in the
24
+ * environment — a referenced-but-unset secret is also a validation
25
+ * error, not an empty string interpolated into a request.
26
+ *
27
+ * Redaction (`buildRedactionMap` / `redactDeep`) is a separate, later
28
+ * step the caller applies at the OUTER boundary — right before writing
29
+ * to stdout, an MCP response, or a log sink — so a secret value that
30
+ * reaches a remote response body (a server echoing back an Authorization
31
+ * header) and comes back into the run's own output is still caught, not
32
+ * just the point where `{{secret:NAME}}` was first substituted. See the
33
+ * module doc trade-offs below on the minimum-length cutoff.
34
+ */
35
+ import { referencedSecrets, replaceSecretRefs } from '@ifc-lite/flow';
36
+ export { referencedSecrets };
37
+ import { parseCapabilities } from '@ifc-lite/extensions';
38
+ /** Every `secret:NAME` the graph's capabilities declare (from `secret.read:<NAME>` grants). */
39
+ export function declaredSecrets(doc) {
40
+ const parsed = parseCapabilities(doc.capabilities);
41
+ const names = new Set();
42
+ if (!parsed.ok)
43
+ return names;
44
+ for (const cap of parsed.value) {
45
+ if (cap.scope === 'secret' && cap.action === 'read' && cap.target?.segments.length === 1) {
46
+ const seg = cap.target.segments[0];
47
+ if (seg.kind === 'literal')
48
+ names.add(seg.value);
49
+ }
50
+ }
51
+ return names;
52
+ }
53
+ /**
54
+ * Validate every `{{secret:NAME}}` reference against the graph's declared
55
+ * capabilities AND the environment, before any node runs. Returns an empty
56
+ * array when the graph is clean (including "no secrets used at all").
57
+ */
58
+ export function validateSecretReferences(doc, env) {
59
+ const declared = declaredSecrets(doc);
60
+ const errors = [];
61
+ for (const ref of referencedSecrets(doc)) {
62
+ if (!declared.has(ref.name)) {
63
+ errors.push({
64
+ nodeId: ref.nodeId,
65
+ param: ref.param,
66
+ name: ref.name,
67
+ reason: 'undeclared',
68
+ message: `node "${ref.nodeId}" param "${ref.param}" references {{secret:${ref.name}}}, but the graph does not declare "secret.read:${ref.name}"`,
69
+ });
70
+ continue;
71
+ }
72
+ if (env[ref.name] === undefined) {
73
+ errors.push({
74
+ nodeId: ref.nodeId,
75
+ param: ref.param,
76
+ name: ref.name,
77
+ reason: 'unset',
78
+ message: `node "${ref.nodeId}" param "${ref.param}" references {{secret:${ref.name}}}, which is declared but not set in the environment`,
79
+ });
80
+ }
81
+ }
82
+ return errors;
83
+ }
84
+ /** Resolve every declared-and-referenced secret's value from `env`. Call only after `validateSecretReferences` returns no errors. */
85
+ export function resolveSecretValues(doc, env) {
86
+ const values = new Map();
87
+ for (const ref of referencedSecrets(doc)) {
88
+ const v = env[ref.name];
89
+ if (v === undefined)
90
+ continue;
91
+ // Redaction is a substring scrub, and a very short value cannot be
92
+ // scrubbed without mangling ordinary output — so rather than resolve a
93
+ // secret that would then travel unredacted, refuse it. The message names
94
+ // the variable, never the value.
95
+ if (v.length < MIN_REDACTED_SECRET_LENGTH) {
96
+ throw new Error(`secret ${ref.name} is shorter than ${MIN_REDACTED_SECRET_LENGTH} characters, so it could not be `
97
+ + 'redacted from run output; refusing to use it');
98
+ }
99
+ values.set(ref.name, v);
100
+ }
101
+ return values;
102
+ }
103
+ function substitute(value, values) {
104
+ if (typeof value === 'string') {
105
+ return replaceSecretRefs(value, (name, whole) => values.get(name) ?? whole);
106
+ }
107
+ if (Array.isArray(value))
108
+ return value.map((v) => substitute(v, values));
109
+ if (value && typeof value === 'object') {
110
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, substitute(v, values)]));
111
+ }
112
+ return value;
113
+ }
114
+ /** Return a new document with every `{{secret:NAME}}` reference in node params replaced by its resolved value. The input document is never mutated. */
115
+ export function interpolateSecrets(doc, values) {
116
+ if (values.size === 0)
117
+ return doc;
118
+ const nodes = doc.nodes.map((node) => {
119
+ if (!node.params)
120
+ return node;
121
+ const params = Object.fromEntries(Object.entries(node.params).map(([k, v]) => [k, substitute(v, values)]));
122
+ return { ...node, params };
123
+ });
124
+ return { ...doc, nodes };
125
+ }
126
+ /** Minimum secret length worth redacting (see module doc): shorter values risk mass-redacting incidental substrings of ordinary text. */
127
+ export const MIN_REDACTED_SECRET_LENGTH = 6;
128
+ /**
129
+ * Reverse map (value → marker) for every resolved secret at least
130
+ * `MIN_REDACTED_SECRET_LENGTH` characters long. A secret shorter than
131
+ * that is a real gap (documented, not silently accepted): a 4-character
132
+ * token could coincide with ordinary text often enough that scrubbing it
133
+ * everywhere would make legitimate output unreadable, so this module
134
+ * accepts that a very short secret is not redactable by substring match
135
+ * at all.
136
+ */
137
+ export function buildRedactionMap(values) {
138
+ // Secrets sharing one value share one marker naming all of them, rather
139
+ // than the last silently taking the value over (#5446 review).
140
+ const names = new Map();
141
+ for (const [name, value] of values) {
142
+ if (value.length < MIN_REDACTED_SECRET_LENGTH)
143
+ continue;
144
+ names.set(value, [...(names.get(value) ?? []), name]);
145
+ }
146
+ // Longest value first, so a secret containing another is matched whole.
147
+ const ordered = [...names].sort(([a], [b]) => b.length - a.length);
148
+ return new Map(ordered.map(([value, owners]) => [value, `<secret:${[...owners].sort().join('|')}>`]));
149
+ }
150
+ function escapeRegExp(text) {
151
+ return text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
152
+ }
153
+ /**
154
+ * Replace every occurrence of a redacted secret value with its marker, in ONE
155
+ * pass, trying the longest value first at each position. Sequential
156
+ * replacement let a shorter secret inside a longer one match first
157
+ * (`abcdef` inside `abcdefghi` left `<secret:A>ghi`, exposing B's suffix),
158
+ * and could match inside a marker already written (#5446 review).
159
+ */
160
+ export function redactText(text, redaction) {
161
+ if (redaction.size === 0)
162
+ return text;
163
+ const values = [...redaction.keys()].sort((a, b) => b.length - a.length);
164
+ const pattern = new RegExp(values.map(escapeRegExp).join('|'), 'g');
165
+ return text.replace(pattern, (match) => redaction.get(match) ?? match);
166
+ }
167
+ /**
168
+ * Walk an arbitrary JSON-ish value (a run summary, a log entry, a thrown
169
+ * error's message) and redact every string found, at any depth — this is
170
+ * what catches a secret that travelled through a response body and back
171
+ * into the run's own output, not just the literal param it was
172
+ * interpolated into.
173
+ */
174
+ /**
175
+ * The env names a host may report as available secrets: set, and long
176
+ * enough to be redacted. `resolveSecretValues` refuses a shorter value, so
177
+ * counting it as available made `flow validate` pass a graph the run then
178
+ * refused (#5446 review).
179
+ */
180
+ export function usableSecretNames(env) {
181
+ return Object.entries(env)
182
+ .filter(([, value]) => typeof value === 'string' && value.length >= MIN_REDACTED_SECRET_LENGTH)
183
+ .map(([name]) => name);
184
+ }
185
+ export function redactDeep(value, redaction) {
186
+ if (redaction.size === 0)
187
+ return value;
188
+ if (typeof value === 'string')
189
+ return redactText(value, redaction);
190
+ if (Array.isArray(value))
191
+ return value.map((v) => redactDeep(v, redaction));
192
+ // Keys too: a script can return an object keyed by a secret, and
193
+ // `core.groupBy` can group by one (#5446 review).
194
+ if (value instanceof Map) {
195
+ return new Map([...value.entries()].map(([k, v]) => [redactDeep(k, redaction), redactDeep(v, redaction)]));
196
+ }
197
+ if (value && typeof value === 'object') {
198
+ return Object.fromEntries(Object.entries(value).map(([k, v]) => [redactText(k, redaction), redactDeep(v, redaction)]));
199
+ }
200
+ return value;
201
+ }
202
+ //# sourceMappingURL=secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secrets.js","sourceRoot":"","sources":["../src/secrets.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAoC,MAAM,gBAAgB,CAAC;AAExG,OAAO,EAAE,iBAAiB,EAAE,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAUzD,+FAA+F;AAC/F,MAAM,UAAU,eAAe,CAAC,GAAiB;IAC/C,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,IAAI,CAAC,MAAM,CAAC,EAAE;QAAE,OAAO,KAAK,CAAC;IAC7B,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,KAAK,MAAM,IAAI,GAAG,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACzF,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;YACnC,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS;gBAAE,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QACnD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB,CAAC,GAAiB,EAAE,GAAiD;IAC3G,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAA4B,EAAE,CAAC;IAC3C,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YAC5B,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,YAAY;gBACpB,OAAO,EAAE,SAAS,GAAG,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,yBAAyB,GAAG,CAAC,IAAI,mDAAmD,GAAG,CAAC,IAAI,GAAG;aACjJ,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YAChC,MAAM,CAAC,IAAI,CAAC;gBACV,MAAM,EAAE,GAAG,CAAC,MAAM;gBAClB,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,IAAI,EAAE,GAAG,CAAC,IAAI;gBACd,MAAM,EAAE,OAAO;gBACf,OAAO,EAAE,SAAS,GAAG,CAAC,MAAM,YAAY,GAAG,CAAC,KAAK,yBAAyB,GAAG,CAAC,IAAI,sDAAsD;aACzI,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,qIAAqI;AACrI,MAAM,UAAU,mBAAmB,CAAC,GAAiB,EAAE,GAAiD;IACtG,MAAM,MAAM,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzC,KAAK,MAAM,GAAG,IAAI,iBAAiB,CAAC,GAAG,CAAC,EAAE,CAAC;QACzC,MAAM,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACxB,IAAI,CAAC,KAAK,SAAS;YAAE,SAAS;QAC9B,mEAAmE;QACnE,uEAAuE;QACvE,yEAAyE;QACzE,iCAAiC;QACjC,IAAI,CAAC,CAAC,MAAM,GAAG,0BAA0B,EAAE,CAAC;YAC1C,MAAM,IAAI,KAAK,CACb,UAAU,GAAG,CAAC,IAAI,oBAAoB,0BAA0B,kCAAkC;kBAChG,8CAA8C,CACjD,CAAC;QACJ,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,UAAU,CAAC,KAAc,EAAE,MAAmC;IACrE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,OAAO,iBAAiB,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,CAAC,CAAC;IAC9E,CAAC;IACD,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC;IACzE,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAC/F,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,uJAAuJ;AACvJ,MAAM,UAAU,kBAAkB,CAAC,GAAiB,EAAE,MAAmC;IACvF,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAClC,MAAM,KAAK,GAAe,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC/C,IAAI,CAAC,IAAI,CAAC,MAAM;YAAE,OAAO,IAAI,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3G,OAAO,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,CAAC;IAC7B,CAAC,CAAC,CAAC;IACH,OAAO,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,CAAC;AAC3B,CAAC;AAED,yIAAyI;AACzI,MAAM,CAAC,MAAM,0BAA0B,GAAG,CAAC,CAAC;AAE5C;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAmC;IACnE,wEAAwE;IACxE,+DAA+D;IAC/D,MAAM,KAAK,GAAG,IAAI,GAAG,EAAoB,CAAC;IAC1C,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,EAAE,CAAC;QACnC,IAAI,KAAK,CAAC,MAAM,GAAG,0BAA0B;YAAE,SAAS;QACxD,KAAK,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,wEAAwE;IACxE,MAAM,OAAO,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACnE,OAAO,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;AACxG,CAAC;AAED,SAAS,YAAY,CAAC,IAAY;IAChC,OAAO,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,IAAY,EAAE,SAAsC;IAC7E,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,MAAM,GAAG,CAAC,GAAG,SAAS,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC;IACzE,MAAM,OAAO,GAAG,IAAI,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC,CAAC;IACpE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC;AACzE,CAAC;AAED;;;;;;GAMG;AACH;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAiD;IACjF,OAAO,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC;SACvB,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,IAAI,0BAA0B,CAAC;SAC9F,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,UAAU,CAAI,KAAQ,EAAE,SAAsC;IAC5E,IAAI,SAAS,CAAC,IAAI,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACvC,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,KAAK,EAAE,SAAS,CAAiB,CAAC;IACnF,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAiB,CAAC;IAC5F,iEAAiE;IACjE,kDAAkD;IAClD,IAAI,KAAK,YAAY,GAAG,EAAE,CAAC;QACzB,OAAO,IAAI,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAAiB,CAAC;IAC7H,CAAC;IACD,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACvC,OAAO,MAAM,CAAC,WAAW,CACvB,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,EAAE,UAAU,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC,CAC5E,CAAC;IACpB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * The Speckle wire protocol, spoken ONLY through `coreNetworkRequest` (the
3
+ * gated, https-only, exact-host-grant request function every flow node
4
+ * uses). Nothing here calls `fetch`: the transport comes from the host, and
5
+ * the grant check runs before any byte moves.
6
+ *
7
+ * Three requests, the same three Speckle's own object loader makes:
8
+ *
9
+ * POST /graphql version → `referencedObject` (root object id)
10
+ * GET /objects/<project>/<object>/single the root object alone
11
+ * POST /api/getobjects/<project> a batch of objects by id, one `id\tjson` per line
12
+ *
13
+ * The walk is lazy and iterative: a round fetches only the ids the previous
14
+ * round referenced and has not yet seen, so display meshes and their data
15
+ * chunks (the bulk of any commit) are never downloaded — `speckle.receive`
16
+ * does not write them (see `mapping.ts`). A visited set stops cycles and
17
+ * revisits, and `maxObjects` bounds the total, failing loudly when reached.
18
+ */
19
+ import { type FetchTransport } from '@ifc-lite/sandbox';
20
+ import type { Capability } from '@ifc-lite/extensions';
21
+ import type { SpeckleTarget } from './url.js';
22
+ export type SpeckleObject = Readonly<Record<string, unknown>> & {
23
+ readonly id: string;
24
+ };
25
+ export interface SpeckleClientOptions {
26
+ readonly grants: readonly Capability[];
27
+ readonly transport?: FetchTransport;
28
+ /** Personal access token; sent as `Authorization: Bearer`. Empty = anonymous (public projects). */
29
+ readonly token?: string;
30
+ readonly timeoutMs: number;
31
+ /** Per-response byte cap. A response that hits it fails the receive: a truncated batch is missing objects. */
32
+ readonly maxBytes: number;
33
+ /** Upper bound on the number of objects fetched. */
34
+ readonly maxObjects: number;
35
+ readonly signal?: AbortSignal;
36
+ }
37
+ /** Keys whose values are display geometry: never followed, never fetched. */
38
+ export declare const DISPLAY_KEYS: ReadonlySet<string>;
39
+ /** The root object id a target points at, and the version it came from (if any). */
40
+ export declare function resolveRoot(opts: SpeckleClientOptions, target: SpeckleTarget): Promise<{
41
+ objectId: string;
42
+ versionId?: string;
43
+ }>;
44
+ /** Every `referencedId` in an object's own JSON tree, except under display keys. */
45
+ export declare function referencedIds(value: unknown, out?: Set<string>): Set<string>;
46
+ /**
47
+ * Fetch the root object and everything it references (display geometry
48
+ * excepted), keyed by id. Throws when an id the graph references is not
49
+ * returned by the server, or when `maxObjects` is reached.
50
+ */
51
+ export declare function fetchObjectGraph(opts: SpeckleClientOptions, target: SpeckleTarget, rootId: string): Promise<Map<string, SpeckleObject>>;
52
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/speckle/client.ts"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAA0C,KAAK,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAChG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAE9C,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC;AAExF,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,cAAc,CAAC;IACpC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,8GAA8G;IAC9G,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;IAC1B,oDAAoD;IACpD,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;CAC/B;AAED,6EAA6E;AAC7E,eAAO,MAAM,YAAY,EAAE,WAAW,CAAC,MAAM,CAA6E,CAAC;AA4C3H,oFAAoF;AACpF,wBAAsB,WAAW,CAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAwBtI;AAOD,oFAAoF;AACpF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,GAAE,GAAG,CAAC,MAAM,CAAa,GAAG,GAAG,CAAC,MAAM,CAAC,CAgBvF;AA0BD;;;;GAIG;AACH,wBAAsB,gBAAgB,CAAC,IAAI,EAAE,oBAAoB,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CA0B7I"}