@noodleseed/one 0.164.0 → 0.166.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 (116) hide show
  1. package/dist/commands/deploy-status-ops.d.ts +2 -0
  2. package/dist/commands/deploy-status-ops.d.ts.map +1 -1
  3. package/dist/commands/deploy-status-ops.js +11 -0
  4. package/dist/commands/deploy-status-ops.js.map +1 -1
  5. package/dist/commands/solutions-coordination.d.ts +5 -0
  6. package/dist/commands/solutions-coordination.d.ts.map +1 -0
  7. package/dist/commands/solutions-coordination.js +94 -0
  8. package/dist/commands/solutions-coordination.js.map +1 -0
  9. package/dist/commands/solutions-ops.d.ts.map +1 -1
  10. package/dist/commands/solutions-ops.js +8 -4
  11. package/dist/commands/solutions-ops.js.map +1 -1
  12. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +2 -0
  13. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +3 -3
  14. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +2 -0
  15. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +4 -1
  16. package/node_modules/@noodle-borg/agent-kit/package.json +1 -1
  17. package/node_modules/@noodle-borg/assistant-gateway/dist/embed-store.d.ts +4 -0
  18. package/node_modules/@noodle-borg/assistant-gateway/dist/in-memory-embed-store.d.ts +4 -0
  19. package/node_modules/@noodle-borg/assistant-gateway/dist/in-memory-embed-store.js +6 -2
  20. package/node_modules/@noodle-borg/authoring/dist/config.d.ts +8 -2
  21. package/node_modules/@noodle-borg/authoring/dist/config.js +28 -1
  22. package/node_modules/@noodle-borg/authoring/dist/connectors.d.ts +37 -0
  23. package/node_modules/@noodle-borg/authoring/dist/connectors.js +4 -0
  24. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -1
  25. package/node_modules/@noodle-borg/authoring/dist/server.js +1 -0
  26. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solution-flags.js +83 -0
  27. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-solutions.js +70 -92
  28. package/node_modules/@noodle-borg/compiler/dist/artifact/operation-ref.d.ts +2 -0
  29. package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +4 -1
  30. package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +4 -1
  31. package/node_modules/@noodle-borg/compiler/dist/catalog/types.d.ts +7 -0
  32. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
  33. package/node_modules/@noodle-borg/compiler/dist/fulfilment-emit.js +15 -2
  34. package/node_modules/@noodle-borg/compiler/dist/nested-operations.js +71 -0
  35. package/node_modules/@noodle-borg/compute/dist/code-connector.js +14 -2
  36. package/node_modules/@noodle-borg/compute/dist/deterministic-helpers.js +138 -0
  37. package/node_modules/@noodle-borg/compute/dist/quickjs-engine.js +48 -0
  38. package/node_modules/@noodle-borg/compute/dist/sandbox-eval.js +39 -5
  39. package/node_modules/@noodle-borg/compute/dist/worker-entry.js +7 -0
  40. package/node_modules/@noodle-borg/compute/dist/worker-pool.js +14 -3
  41. package/node_modules/@noodle-borg/connector-defs/dist/compile-http.js +31 -2
  42. package/node_modules/@noodle-borg/connector-defs/dist/compile.d.ts +1 -1
  43. package/node_modules/@noodle-borg/connector-defs/dist/compile.js +20 -0
  44. package/node_modules/@noodle-borg/connector-defs/dist/schema.d.ts +84 -0
  45. package/node_modules/@noodle-borg/connector-defs/dist/schema.js +44 -1
  46. package/node_modules/@noodle-borg/connector-http/dist/http-connector.d.ts +7 -0
  47. package/node_modules/@noodle-borg/connector-http/dist/http-connector.js +34 -6
  48. package/node_modules/@noodle-borg/connector-http/dist/http-response.d.ts +8 -1
  49. package/node_modules/@noodle-borg/connector-http/dist/http-response.js +19 -10
  50. package/node_modules/@noodle-borg/connector-http/dist/index.d.ts +1 -1
  51. package/node_modules/@noodle-borg/module/dist/customer-auth-access.d.ts +7 -0
  52. package/node_modules/@noodle-borg/module/dist/customer-auth-access.js +6 -0
  53. package/node_modules/@noodle-borg/module/dist/index.d.ts +1 -0
  54. package/node_modules/@noodle-borg/module/dist/index.js +1 -0
  55. package/node_modules/@noodle-borg/runtime/dist/connector/types.d.ts +7 -1
  56. package/node_modules/@noodle-borg/runtime/dist/connector-snapshot.js +8 -0
  57. package/node_modules/@noodle-borg/runtime/dist/execute.d.ts +2 -0
  58. package/node_modules/@noodle-borg/runtime/dist/index.d.ts +1 -0
  59. package/node_modules/@noodle-borg/runtime/dist/nested-operation-host.js +25 -0
  60. package/node_modules/@noodle-borg/runtime/dist/operation-coordination-execution.js +50 -0
  61. package/node_modules/@noodle-borg/runtime/dist/operation-coordination.d.ts +34 -0
  62. package/node_modules/@noodle-borg/runtime/dist/operation-evidence.d.ts +4 -0
  63. package/node_modules/@noodle-borg/runtime/dist/operation-execution.js +173 -94
  64. package/node_modules/@noodle-borg/service/dist/application-activity.js +152 -18
  65. package/node_modules/@noodle-borg/service/dist/application-runtime-target.js +15 -2
  66. package/node_modules/@noodle-borg/service/dist/business-information/definition-resolver.js +19 -0
  67. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +1 -1
  68. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-blueprints.js +7 -0
  69. package/node_modules/@noodle-borg/service/dist/business-information/managed-solution-executable.js +11 -1
  70. package/node_modules/@noodle-borg/service/dist/business-information/model.js +2 -2
  71. package/node_modules/@noodle-borg/service/dist/business-information/portable.js +1 -1
  72. package/node_modules/@noodle-borg/service/dist/business-information/profiles.js +37 -1
  73. package/node_modules/@noodle-borg/service/dist/credential-binding-index.js +19 -1
  74. package/node_modules/@noodle-borg/service/dist/customer-auth-audience-binding.js +16 -5
  75. package/node_modules/@noodle-borg/service/dist/deployment-authentication.js +19 -0
  76. package/node_modules/@noodle-borg/service/dist/deployment-execution.js +1 -1
  77. package/node_modules/@noodle-borg/service/dist/deployment-record-version.js +31 -0
  78. package/node_modules/@noodle-borg/service/dist/developer-mcp/inspection.js +15 -1
  79. package/node_modules/@noodle-borg/service/dist/operation-coordination.js +185 -0
  80. package/node_modules/@noodle-borg/service/dist/operation-evidence.js +3 -1
  81. package/node_modules/@noodle-borg/service/dist/registry-access.js +18 -3
  82. package/node_modules/@noodle-borg/service/dist/registry-compile.js +42 -1
  83. package/node_modules/@noodle-borg/service/dist/registry-deploy-transaction.js +15 -0
  84. package/node_modules/@noodle-borg/service/dist/registry-rollback.js +2 -0
  85. package/node_modules/@noodle-borg/service/dist/registry-state.d.ts +1 -0
  86. package/node_modules/@noodle-borg/service/dist/registry-state.js +12 -5
  87. package/node_modules/@noodle-borg/service/dist/registry-status.js +3 -0
  88. package/node_modules/@noodle-borg/service/dist/registry-targets.js +8 -0
  89. package/node_modules/@noodle-borg/service/dist/registry-types.d.ts +1 -1
  90. package/node_modules/@noodle-borg/service/dist/registry.js +31 -36
  91. package/node_modules/@noodle-borg/service/dist/routes/access.js +5 -0
  92. package/node_modules/@noodle-borg/service/dist/routes/business-information-activity.js +48 -53
  93. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +2 -1
  94. package/node_modules/@noodle-borg/service/dist/routes/business-information-installation.js +51 -17
  95. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +6 -4
  96. package/node_modules/@noodle-borg/service/dist/routes/business-information-staff.js +4 -3
  97. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +11 -6
  98. package/node_modules/@noodle-borg/service/dist/routes/deploy-public-embed.js +7 -2
  99. package/node_modules/@noodle-borg/service/dist/service.js +2 -1
  100. package/node_modules/@noodle-borg/service/dist/solution-installation-activation.js +58 -3
  101. package/node_modules/@noodle-borg/service/dist/store/in-memory.d.ts +1 -0
  102. package/node_modules/@noodle-borg/service/dist/store/in-memory.js +10 -3
  103. package/node_modules/@noodle-borg/service/dist/store/json-file.d.ts +1 -0
  104. package/node_modules/@noodle-borg/service/dist/store/json-file.js +10 -3
  105. package/node_modules/@noodle-borg/service/dist/store/records.js +4 -2
  106. package/node_modules/@noodle-borg/service/dist/store.d.ts +5 -1
  107. package/node_modules/@noodle-borg/service/package.json +1 -1
  108. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +52 -0
  109. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +6 -0
  110. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.d.ts +23 -0
  111. package/node_modules/@noodle-borg/wire-contracts/dist/control-plane.js +34 -4
  112. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +1 -0
  113. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +1 -0
  114. package/node_modules/@noodle-borg/wire-contracts/dist/operation-coordination.d.ts +59 -0
  115. package/node_modules/@noodle-borg/wire-contracts/dist/operation-coordination.js +51 -0
  116. package/package.json +2 -2
@@ -15,7 +15,34 @@ export function variable(name, options) {
15
15
  const errors = validateVariableDeclaration(declaration);
16
16
  if (errors.length > 0)
17
17
  throw new Error(`variable("${name}") ${errors.map((error) => `${error.path}: ${error.message}`).join('; ')}`);
18
- return { ...ref, kind: 'variable', declaration: structuredClone(declaration) };
18
+ return {
19
+ ...makeVariableValueRef(name, [], declaration.valueSchema),
20
+ declaration: structuredClone(declaration),
21
+ };
22
+ }
23
+ function makeVariableValueRef(name, fields, schema) {
24
+ const expression = () => `\${env.${[name, ...fields].join('.')}}`;
25
+ return {
26
+ ...makeConfigRef('variable', name),
27
+ kind: 'variable',
28
+ toExpression: expression,
29
+ toString: expression,
30
+ field(key) {
31
+ const properties = schema.properties;
32
+ if (!/^[A-Za-z_][A-Za-z0-9_]*$/.test(key) ||
33
+ ['__proto__', 'constructor', 'prototype'].includes(key) ||
34
+ schema.type !== 'object' ||
35
+ !properties ||
36
+ typeof properties !== 'object' ||
37
+ Array.isArray(properties) ||
38
+ !Object.hasOwn(properties, key))
39
+ throw new Error('variable.field() requires a declared object field with a safe identifier');
40
+ const child = properties[key];
41
+ if (!child || typeof child !== 'object' || Array.isArray(child))
42
+ throw new Error('variable.field() requires a declared object field schema');
43
+ return makeVariableValueRef(name, [...fields, key], child);
44
+ },
45
+ };
19
46
  }
20
47
  export function manifestVariables(refs) {
21
48
  if (refs === undefined || refs.length === 0)
@@ -125,6 +125,35 @@ export interface ComputeLimits {
125
125
  readonly maxHostCalls?: number;
126
126
  }
127
127
  export interface ComputeHost {
128
+ /** Trusted external-operation identity; unavailable outside governed action execution. */
129
+ readonly execution?: {
130
+ readonly id: string;
131
+ };
132
+ readonly coordination?: {
133
+ readonly acquired: boolean;
134
+ readonly previous?: {
135
+ readonly reference: string;
136
+ readonly operationDigest: string;
137
+ };
138
+ };
139
+ reportOutcome(evidence: {
140
+ readonly outcome: 'completed' | 'rejected' | 'unknown';
141
+ readonly reference?: string;
142
+ }): unknown;
143
+ resolveCoordination(): unknown;
144
+ /** Pure helpers over explicit instants, with no access to the current clock. */
145
+ readonly time: {
146
+ parse(instant: string): number;
147
+ format(epochMilliseconds: number): string;
148
+ parts(epochMilliseconds: number, timeZone: string): {
149
+ readonly date: string;
150
+ readonly weekday: number;
151
+ readonly hour: number;
152
+ readonly minute: number;
153
+ };
154
+ };
155
+ /** Bounded SHA-256 over explicit input; no keys, secrets or randomness. */
156
+ digest(value: string, encoding?: 'hex' | 'base32hex'): string;
128
157
  callOperation(name: string, args: Readonly<Record<string, unknown>>): unknown;
129
158
  }
130
159
  /**
@@ -142,6 +171,13 @@ export interface ComputeOperationOptions {
142
171
  readonly run: (input: any, host: ComputeHost) => unknown;
143
172
  readonly limits?: ComputeLimits;
144
173
  readonly calls?: Readonly<Record<string, string>>;
174
+ /** Serialize one externally coordinated resource; host owns durable custody and exact release. */
175
+ readonly coordination?: {
176
+ readonly connectionId: string;
177
+ readonly namespace: string;
178
+ readonly key: string;
179
+ readonly reference: string;
180
+ };
145
181
  }
146
182
  /** A connector operation's fulfilment, carried by the builder so it can be emitted to a catalog. */
147
183
  export interface ConnectorOpDefinition {
@@ -152,6 +188,7 @@ export interface ConnectorOpDefinition {
152
188
  readonly code: string;
153
189
  readonly limits?: ComputeLimits;
154
190
  readonly calls?: Readonly<Record<string, string>>;
191
+ readonly coordination?: ComputeOperationOptions['coordination'];
155
192
  }
156
193
  export interface ConnectorRef<CredentialProfileKey extends string = string> {
157
194
  readonly id: string;
@@ -213,6 +213,7 @@ export class ConnectorBuilder {
213
213
  code: serializeRun(options.run),
214
214
  ...(options.limits ? { limits: options.limits } : {}),
215
215
  ...(options.calls ? { calls: options.calls } : {}),
216
+ ...(options.coordination ? { coordination: options.coordination } : {}),
216
217
  },
217
218
  }, undefined, this.credentialProfiles, undefined);
218
219
  }
@@ -263,6 +264,9 @@ function normalizeOperation(id, name, operation) {
263
264
  ...(operation.response !== undefined
264
265
  ? { response: normalizeConfigRefs(operation.response, `${path}.response`) }
265
266
  : {}),
267
+ ...(operation.responses !== undefined
268
+ ? { responses: normalizeConfigRefs(operation.responses, `${path}.responses`) }
269
+ : {}),
266
270
  ...(operation.headers !== undefined
267
271
  ? { headers: normalizeConfigRefs(operation.headers, `${path}.headers`) }
268
272
  : {}),
@@ -3,7 +3,7 @@ import { z } from 'zod';
3
3
  export type { PackagedAssetReference } from '@noodle-borg/compiler';
4
4
  export type { AgentCapabilityKind, AgentCapabilityRef, AgentExampleSource, AgentGuideSource, AgentWorkflowSource, AgentWorkflowStepSource, } from './agent-guide.js';
5
5
  export { type AssistantAccess, type AssistantCapability, type AssistantLabels, type AssistantLayoutMode, type AssistantModel, type AssistantPosition, type AssistantPresentationOptions, type AssistantPresentationTone, type AssistantSurfaceConfig, type AssistantSurfaceMode, type AssistantThemeMode, type AssistantUiOptions, type AuthenticatedWebsiteAccess, type AuthenticatedWebsiteInput, authenticatedWebsite, type CapabilityRef, type EmbeddedAssistantConfig, type EmbeddedAssistantOptions, embeddedAssistant, type NoodleManagedModel, noodleManaged, type OpenAICompatibleModel, type OpenAICompatibleModelInput, type OpenAICompatibleTransport, openAICompatible, type PublicWebsiteAccess, type PublicWebsiteInput, publicWebsite, } from './assistant.js';
6
- export { type ConfigRef, type ConfigRefKind, type DeclaredVariableRef, secret, type VariableOptions, variable, } from './config.js';
6
+ export { type ConfigRef, type ConfigRefKind, type DeclaredVariableRef, secret, type VariableOptions, type VariableValueRef, variable, } from './config.js';
7
7
  export { type BoundConnectorRef, bind, type ConnectionBinding, type ConnectionRef, type ConnectionSource, clientCredentials, connection, externalExchange, type GoogleWorkloadIdentityAccess, googleWorkloadIdentity, managedSecret, } from './connections.js';
8
8
  export { type ComputeHost, type ComputeLimits, type ComputeOperationOptions, ConnectorBuilder, type ConnectorCatalogDoc, type ConnectorOpDefinition, type ConnectorOperationOptions, type ConnectorRef, connector, type HttpConnectorOptions, type McpAuthOptions, type McpConnectorOptions, } from './connectors.js';
9
9
  export type { AmbientContextOptions, AmbientProviderContext, ServerContextOptions, } from './context.js';
@@ -288,6 +288,7 @@ class ServerBuilder {
288
288
  code: def.code,
289
289
  ...(def.limits ? { limits: def.limits } : {}),
290
290
  ...(def.calls ? { calls: def.calls } : {}),
291
+ ...(def.coordination ? { coordination: def.coordination } : {}),
291
292
  };
292
293
  }
293
294
  const computeConnector = {
@@ -0,0 +1,83 @@
1
+ export const OPTIONAL_FLAG = {
2
+ required: false,
3
+ repeatable: false,
4
+ sensitive: false,
5
+ aliases: [],
6
+ conflictsWith: [],
7
+ };
8
+ export const REQUIRED_ARGUMENT = {
9
+ type: 'string',
10
+ required: true,
11
+ variadic: false,
12
+ sensitive: false,
13
+ constraints: {},
14
+ };
15
+ const ORG = {
16
+ ...OPTIONAL_FLAG,
17
+ name: 'org',
18
+ type: 'string',
19
+ value: '<slug>',
20
+ summary: 'Organization slug.',
21
+ };
22
+ export const SERVICE = {
23
+ ...OPTIONAL_FLAG,
24
+ name: 'service',
25
+ type: 'string',
26
+ value: '<url>',
27
+ summary: 'Control-plane service URL.',
28
+ };
29
+ export const AUTH_TOKEN = {
30
+ ...OPTIONAL_FLAG,
31
+ name: 'auth-token',
32
+ type: 'string',
33
+ value: '<token>',
34
+ summary: 'Control-plane authentication token.',
35
+ sensitive: true,
36
+ };
37
+ export const JSON_FLAG = {
38
+ ...OPTIONAL_FLAG,
39
+ name: 'json',
40
+ type: 'boolean',
41
+ summary: 'Emit JSON output.',
42
+ };
43
+ export const INSTALLATION_ARGUMENT = {
44
+ ...REQUIRED_ARGUMENT,
45
+ name: 'installation',
46
+ summary: 'Solution installation identifier.',
47
+ };
48
+ export const SOLUTION_COMMON_FLAGS = [ORG, SERVICE, AUTH_TOKEN, JSON_FLAG];
49
+ export const EXPECTED_REVISION = {
50
+ ...OPTIONAL_FLAG,
51
+ name: 'expected-revision',
52
+ type: 'integer',
53
+ value: '<revision>',
54
+ summary: 'Expected current resource revision.',
55
+ required: true,
56
+ constraints: { minimum: 1 },
57
+ };
58
+ export const IDEMPOTENCY_KEY = {
59
+ ...OPTIONAL_FLAG,
60
+ name: 'idempotency-key',
61
+ type: 'string',
62
+ value: '<key>',
63
+ summary: 'Retry-safe operation key.',
64
+ required: true,
65
+ };
66
+ export const PAGING_FLAGS = [
67
+ {
68
+ ...OPTIONAL_FLAG,
69
+ name: 'cursor',
70
+ type: 'string',
71
+ value: '<cursor>',
72
+ summary: 'Opaque page cursor.',
73
+ },
74
+ {
75
+ ...OPTIONAL_FLAG,
76
+ name: 'limit',
77
+ type: 'integer',
78
+ value: '<count>',
79
+ summary: 'Bounded page size.',
80
+ constraints: { minimum: 1, maximum: 100 },
81
+ },
82
+ ];
83
+ //# sourceMappingURL=catalog-data-solution-flags.js.map
@@ -1,24 +1,5 @@
1
- const OPTIONAL_FLAG = {
2
- required: false,
3
- repeatable: false,
4
- sensitive: false,
5
- aliases: [],
6
- conflictsWith: [],
7
- };
8
- const REQUIRED_ARGUMENT = {
9
- type: 'string',
10
- required: true,
11
- variadic: false,
12
- sensitive: false,
13
- constraints: {},
14
- };
15
- const ORG = {
16
- ...OPTIONAL_FLAG,
17
- name: 'org',
18
- type: 'string',
19
- value: '<slug>',
20
- summary: 'Organization slug.',
21
- };
1
+ /** Solution installation/operator catalog. Imports only dependency-free sibling data. */
2
+ import { AUTH_TOKEN, EXPECTED_REVISION, IDEMPOTENCY_KEY, INSTALLATION_ARGUMENT, JSON_FLAG, OPTIONAL_FLAG, PAGING_FLAGS, REQUIRED_ARGUMENT, SERVICE, SOLUTION_COMMON_FLAGS, } from './catalog-data-solution-flags.js';
22
3
  const APP = {
23
4
  ...OPTIONAL_FLAG,
24
5
  name: 'app',
@@ -33,27 +14,6 @@ const ENV = {
33
14
  value: '<slug>',
34
15
  summary: 'Environment slug.',
35
16
  };
36
- const SERVICE = {
37
- ...OPTIONAL_FLAG,
38
- name: 'service',
39
- type: 'string',
40
- value: '<url>',
41
- summary: 'Control-plane service URL.',
42
- };
43
- const AUTH_TOKEN = {
44
- ...OPTIONAL_FLAG,
45
- name: 'auth-token',
46
- type: 'string',
47
- value: '<token>',
48
- summary: 'Control-plane authentication token.',
49
- sensitive: true,
50
- };
51
- const JSON_FLAG = {
52
- ...OPTIONAL_FLAG,
53
- name: 'json',
54
- type: 'boolean',
55
- summary: 'Emit JSON output.',
56
- };
57
17
  const RETENTION = {
58
18
  ...OPTIONAL_FLAG,
59
19
  name: 'retention-days',
@@ -62,11 +22,6 @@ const RETENTION = {
62
22
  summary: 'Managed-record retention in days.',
63
23
  constraints: { choices: [7, 30, 90], default: 30 },
64
24
  };
65
- const INSTALLATION_ARGUMENT = {
66
- ...REQUIRED_ARGUMENT,
67
- name: 'installation',
68
- summary: 'Solution installation identifier.',
69
- };
70
25
  const COLLECTION_ARGUMENT = {
71
26
  ...REQUIRED_ARGUMENT,
72
27
  name: 'collection',
@@ -77,41 +32,6 @@ const RECORD_ARGUMENT = {
77
32
  name: 'record',
78
33
  summary: 'Managed record identifier.',
79
34
  };
80
- const SOLUTION_COMMON_FLAGS = [ORG, SERVICE, AUTH_TOKEN, JSON_FLAG];
81
- const EXPECTED_REVISION = {
82
- ...OPTIONAL_FLAG,
83
- name: 'expected-revision',
84
- type: 'integer',
85
- value: '<revision>',
86
- summary: 'Expected current resource revision.',
87
- required: true,
88
- constraints: { minimum: 1 },
89
- };
90
- const IDEMPOTENCY_KEY = {
91
- ...OPTIONAL_FLAG,
92
- name: 'idempotency-key',
93
- type: 'string',
94
- value: '<key>',
95
- summary: 'Retry-safe operation key.',
96
- required: true,
97
- };
98
- const PAGING_FLAGS = [
99
- {
100
- ...OPTIONAL_FLAG,
101
- name: 'cursor',
102
- type: 'string',
103
- value: '<cursor>',
104
- summary: 'Opaque page cursor.',
105
- },
106
- {
107
- ...OPTIONAL_FLAG,
108
- name: 'limit',
109
- type: 'integer',
110
- value: '<count>',
111
- summary: 'Bounded page size.',
112
- constraints: { minimum: 1, maximum: 100 },
113
- },
114
- ];
115
35
  const RECORD_QUERY_FLAGS = [
116
36
  {
117
37
  ...OPTIONAL_FLAG,
@@ -285,6 +205,64 @@ export const CATALOG_SOLUTIONS = {
285
205
  },
286
206
  ],
287
207
  })),
208
+ {
209
+ name: 'operations',
210
+ summary: 'Inspect and recover application operation custody.',
211
+ arguments: [],
212
+ flags: [],
213
+ subcommands: [
214
+ {
215
+ name: 'coordination',
216
+ summary: 'Administrator-only review of held external operations.',
217
+ arguments: [],
218
+ flags: [],
219
+ subcommands: ['list', 'resolve'].map((name) => ({
220
+ name,
221
+ summary: name === 'list'
222
+ ? 'List held operations in one installation.'
223
+ : 'Release an inactive exact hold after reviewing the external outcome.',
224
+ arguments: [INSTALLATION_ARGUMENT],
225
+ flags: [
226
+ ...SOLUTION_COMMON_FLAGS,
227
+ ...(name === 'list'
228
+ ? [
229
+ {
230
+ ...OPTIONAL_FLAG,
231
+ name: 'limit',
232
+ type: 'integer',
233
+ value: '<count>',
234
+ summary: 'Maximum records in this page.',
235
+ constraints: { minimum: 1, maximum: 100 },
236
+ },
237
+ {
238
+ ...OPTIONAL_FLAG,
239
+ name: 'before-resource',
240
+ type: 'string',
241
+ value: '<hash>',
242
+ summary: 'Continuation resource returned by the previous list.',
243
+ },
244
+ ]
245
+ : [
246
+ ...[
247
+ ['resource', 'Exact resource hash from list.'],
248
+ ['token', 'Exact custody token from list.'],
249
+ ['reason', 'Single-line review reason; 1 to 256 characters.'],
250
+ ].map(([flag, summary]) => ({
251
+ ...OPTIONAL_FLAG,
252
+ name: flag,
253
+ summary,
254
+ required: true,
255
+ sensitive: flag === 'token',
256
+ type: 'string',
257
+ value: '<value>',
258
+ })),
259
+ ]),
260
+ ],
261
+ jsonOutput: { mode: 'single' },
262
+ })),
263
+ },
264
+ ],
265
+ },
288
266
  {
289
267
  name: 'activity',
290
268
  summary: 'Inspect payload-free operation evidence and its retention policy.',
@@ -485,18 +463,18 @@ export const CATALOG_SOLUTIONS = {
485
463
  ],
486
464
  jsonOutput: { mode: 'single' },
487
465
  },
488
- {
489
- name: 'inspect',
490
- summary: 'Inspect one solution installation.',
491
- arguments: [INSTALLATION_ARGUMENT],
492
- flags: SOLUTION_COMMON_FLAGS,
493
- jsonOutput: { mode: 'single' },
494
- },
495
- ...['pause', 'resume'].map((name) => ({
466
+ ...Object.entries({
467
+ inspect: 'Inspect one solution installation.',
468
+ activate: 'Retry activation of a saved installation without changing its intake setting.',
469
+ pause: 'Pause anonymous public intake.',
470
+ resume: 'Resume anonymous public intake.',
471
+ }).map(([name, summary]) => ({
496
472
  name,
497
- summary: `${name === 'pause' ? 'Pause' : 'Resume'} anonymous public intake.`,
473
+ summary,
498
474
  arguments: [INSTALLATION_ARGUMENT],
499
- flags: [...SOLUTION_COMMON_FLAGS, EXPECTED_REVISION],
475
+ flags: ['pause', 'resume'].includes(name)
476
+ ? [...SOLUTION_COMMON_FLAGS, EXPECTED_REVISION]
477
+ : SOLUTION_COMMON_FLAGS,
500
478
  jsonOutput: { mode: 'single' },
501
479
  })),
502
480
  {
@@ -31,6 +31,8 @@ export interface ResolvedOperationRef {
31
31
  readonly operation: string;
32
32
  /** Stable hash of the operation signature: `sha256:<hex>`. See catalog/signature.ts. */
33
33
  readonly signatureHash: string;
34
+ /** Exact allowed nested operations with their independently resolved account authority. */
35
+ readonly calls?: readonly ResolvedOperationRef[];
34
36
  /** Core-v2 credential selection resolved from the stable alias; absent on legacy artifacts. */
35
37
  readonly credentialBinding?: ResolvedCredentialBinding;
36
38
  /** Customer-derived base-URL key for a directly routed HTTP operation; never the resolved URL. */
@@ -58,8 +58,11 @@
58
58
  * authority or exact resolved read-only connector operations for an external replica.
59
59
  *
60
60
  * `0.19.0` (Business settings): optional typed managed-variable declarations and definition digests.
61
+ *
62
+ * `0.20.0` (Nested operation authority): resolved operation references carry exact declared calls,
63
+ * including independently validated credential bindings for sandboxed compute dependencies.
61
64
  */
62
- export declare const ARTIFACT_SCHEMA_VERSION = "0.19.0";
65
+ export declare const ARTIFACT_SCHEMA_VERSION = "0.20.0";
63
66
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
64
67
  export declare const MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
65
68
  //# sourceMappingURL=version.d.ts.map
@@ -58,8 +58,11 @@
58
58
  * authority or exact resolved read-only connector operations for an external replica.
59
59
  *
60
60
  * `0.19.0` (Business settings): optional typed managed-variable declarations and definition digests.
61
+ *
62
+ * `0.20.0` (Nested operation authority): resolved operation references carry exact declared calls,
63
+ * including independently validated credential bindings for sandboxed compute dependencies.
61
64
  */
62
- export const ARTIFACT_SCHEMA_VERSION = '0.19.0';
65
+ export const ARTIFACT_SCHEMA_VERSION = '0.20.0';
63
66
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
64
67
  export const MCP_APP_MIME_TYPE = 'text/html;profile=mcp-app';
65
68
  //# sourceMappingURL=version.js.map
@@ -58,6 +58,13 @@ export interface CatalogConnector {
58
58
  readonly credentialProfiles?: Readonly<Record<string, CredentialProfile>>;
59
59
  readonly operationCredentials?: Readonly<Record<string, OperationCredentialRequirement>>;
60
60
  readonly operations: Readonly<Record<string, OperationSignature>>;
61
+ /** System-derived declared compute call graph, including exact resolved target identities. */
62
+ readonly operationCalls?: Readonly<Record<string, readonly {
63
+ readonly connectorId: string;
64
+ readonly connectorVersion: string;
65
+ readonly operation: string;
66
+ readonly signatureHash: string;
67
+ }[]>>;
61
68
  readonly customerRouting?: CatalogCustomerRouting;
62
69
  }
63
70
  /** Read-only lookup of connectors by catalog id and pinned version. */
@@ -1,7 +1,7 @@
1
1
  import type { AppPackageArtifactV1 } from '@noodle-borg/app-package';
2
2
  import type { RuntimeArtifact } from './artifact/types.js';
3
3
  import type { PackagedAsset } from './assets.js';
4
- export type CompileErrorCode = 'invalid_context_provider' | 'yaml_parse_error' | 'invalid_shape' | 'invalid_name' | 'duplicate_name' | 'reserved_name' | 'unsupported_manifest_version' | 'reserved_for_future_version' | 'invalid_operation_ref' | 'external_ref' | 'invalid_schema_ref' | 'unknown_schema_ref' | 'schema_ref_conflict' | 'invalid_expression' | 'expr_unknown_root' | 'expr_root_unavailable' | 'expr_operator_not_allowed' | 'expr_if_not_boolean' | 'unknown_step_ref' | 'forward_step_ref' | 'self_step_ref' | 'duplicate_step_id' | 'invalid_fulfilment' | 'invalid_elicitation_schema' | 'invalid_elicitation_flow' | 'invalid_confirmation_flow' | 'arg_type_mismatch' | 'ambient_context_action' | 'duplicate_resource' | 'duplicate_prompt' | 'duplicate_resource_uri' | 'unsupported_uri_template' | 'duplicate_widget' | 'unknown_widget_tool' | 'unknown_widget_action_tool' | 'duplicate_widget_tool' | 'invalid_widget_binding' | 'invalid_widget_state_handle' | 'widget_html_too_large' | 'widget_html_total_too_large' | 'invalid_asset' | 'invalid_capability_requirement' | 'state_secret_field' | 'invalid_knowledge' | 'knowledge_unhashed' | 'invalid_managed_collection' | 'invalid_variable_declaration' | 'invalid_managed_collection_source' | 'unknown_connector_alias' | 'connector_not_in_catalog' | 'unknown_operation' | 'connector_binding_required' | 'unsupported_credential_profile' | 'credential_scope_mismatch' | 'credential_audience_mismatch' | 'customer_endpoint_auth_required' | 'customer_endpoint_mapping_required' | 'customer_endpoint_unknown_mapping' | 'customer_endpoint_bridge_unsupported' | 'assistant_capability_unknown' | 'assistant_public_user_reference' | 'assistant_public_effect_unconfirmed' | 'customer_endpoint_action_unsupported' | 'customer_endpoint_surface_unsupported' | 'customer_endpoint_credential_source_unsupported' | 'customer_endpoint_policy_conflict' | 'customer_endpoint_routing_inconsistent' | 'unused_connector_alias' | 'arg_mismatch' | 'agent_guide_invalid' | 'agent_guide_duplicate_workflow' | 'agent_guide_duplicate_example' | 'agent_guide_example_workflow_missing' | 'agent_guide_capability_missing' | 'agent_guide_capability_kind' | 'app_package_sensitive_content';
4
+ export type CompileErrorCode = 'invalid_context_provider' | 'yaml_parse_error' | 'invalid_shape' | 'invalid_name' | 'duplicate_name' | 'reserved_name' | 'unsupported_manifest_version' | 'reserved_for_future_version' | 'invalid_operation_ref' | 'external_ref' | 'invalid_schema_ref' | 'unknown_schema_ref' | 'schema_ref_conflict' | 'invalid_expression' | 'expr_unknown_root' | 'expr_root_unavailable' | 'expr_operator_not_allowed' | 'expr_if_not_boolean' | 'unknown_step_ref' | 'forward_step_ref' | 'self_step_ref' | 'duplicate_step_id' | 'invalid_fulfilment' | 'invalid_elicitation_schema' | 'invalid_elicitation_flow' | 'invalid_confirmation_flow' | 'arg_type_mismatch' | 'ambient_context_action' | 'duplicate_resource' | 'duplicate_prompt' | 'duplicate_resource_uri' | 'unsupported_uri_template' | 'duplicate_widget' | 'unknown_widget_tool' | 'unknown_widget_action_tool' | 'duplicate_widget_tool' | 'invalid_widget_binding' | 'invalid_widget_state_handle' | 'widget_html_too_large' | 'widget_html_total_too_large' | 'invalid_asset' | 'invalid_capability_requirement' | 'state_secret_field' | 'invalid_knowledge' | 'knowledge_unhashed' | 'invalid_managed_collection' | 'invalid_variable_declaration' | 'invalid_managed_collection_source' | 'unknown_connector_alias' | 'connector_not_in_catalog' | 'unknown_operation' | 'connector_binding_required' | 'ambiguous_nested_connector_binding' | 'invalid_connector_call_graph' | 'unsupported_credential_profile' | 'credential_scope_mismatch' | 'credential_audience_mismatch' | 'customer_endpoint_auth_required' | 'customer_endpoint_mapping_required' | 'customer_endpoint_unknown_mapping' | 'customer_endpoint_bridge_unsupported' | 'assistant_capability_unknown' | 'assistant_public_user_reference' | 'assistant_public_effect_unconfirmed' | 'customer_endpoint_action_unsupported' | 'customer_endpoint_surface_unsupported' | 'customer_endpoint_credential_source_unsupported' | 'customer_endpoint_policy_conflict' | 'customer_endpoint_routing_inconsistent' | 'unused_connector_alias' | 'arg_mismatch' | 'agent_guide_invalid' | 'agent_guide_duplicate_workflow' | 'agent_guide_duplicate_example' | 'agent_guide_example_workflow_missing' | 'agent_guide_capability_missing' | 'agent_guide_capability_kind' | 'app_package_sensitive_content';
5
5
  export interface CompileError {
6
6
  readonly code: CompileErrorCode;
7
7
  /** Dotted path to the offending location (e.g. `tools.1.name`); empty string for the document root. */
@@ -1,5 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
2
  import { computeSignatureHash } from './catalog/signature.js';
3
+ import { resolveNestedOperations } from './nested-operations.js';
3
4
  import { docAnchorFor, suggestionFields } from './suggest.js';
4
5
  const JSON_SCHEMA_2020_12 = 'https://json-schema.org/draft/2020-12/schema';
5
6
  /** Build the artifact fulfilment, resolving each operation occurrence against the catalog (if any). */
@@ -31,7 +32,7 @@ export function emitFulfilment(struct, catalog, declared, usedAliases, errors, o
31
32
  * Resolve one operation occurrence against the catalog (docs/SPEC.md "Runtime Invariants"). Without a
32
33
  * catalog, returns an unresolved reference (shape-only). Pushes a CompileError per failure.
33
34
  */
34
- function resolveOp(op, catalog, declared, usedAliases, errors, options) {
35
+ function resolveOp(op, catalog, declared, usedAliases, errors, options, traversal) {
35
36
  const unresolved = {
36
37
  connector: op.connectorAlias,
37
38
  operation: op.operation,
@@ -85,17 +86,29 @@ function resolveOp(op, catalog, declared, usedAliases, errors, options) {
85
86
  got: operation.type,
86
87
  });
87
88
  }
88
- checkArgs(op.args, connector, op.operation, operation, `${op.path}.args`, errors);
89
+ if (traversal === undefined)
90
+ checkArgs(op.args, connector, op.operation, operation, `${op.path}.args`, errors);
89
91
  const credentialRequirement = connector.operationCredentials?.[op.operation];
90
92
  const credentialPresentation = connectorRef.binding === undefined
91
93
  ? undefined
92
94
  : connector.credentialProfiles?.[connectorRef.binding.profile];
95
+ const calls = resolveNestedOperations({
96
+ connector,
97
+ operation: op.operation,
98
+ path: op.path,
99
+ catalog,
100
+ declared,
101
+ errors,
102
+ ...(traversal === undefined ? {} : { traversal }),
103
+ resolve: (child, childDeclared, childTraversal) => resolveOp(child, catalog, childDeclared, usedAliases, errors, options, childTraversal),
104
+ });
93
105
  return {
94
106
  alias: op.connectorAlias,
95
107
  connectorId: connector.id,
96
108
  connectorVersion: connector.version,
97
109
  operation: op.operation,
98
110
  signatureHash: computeSignatureHash(op.operation, operation),
111
+ ...(calls === undefined ? {} : { calls }),
99
112
  ...(customerOperationRouting?.directEndpoint === undefined
100
113
  ? {}
101
114
  : { customerEndpoint: customerOperationRouting.directEndpoint }),
@@ -0,0 +1,71 @@
1
+ import { computeSignatureHash } from './catalog/signature.js';
2
+ /** Resolve reachable system-derived dependency identities without guessing between account aliases. */
3
+ export function resolveNestedOperations(input) {
4
+ const calls = input.connector.operationCalls?.[input.operation];
5
+ if (calls === undefined)
6
+ return undefined;
7
+ const identity = JSON.stringify([input.connector.id, input.connector.version, input.operation]);
8
+ const traversal = input.traversal ?? { ancestors: [], budget: { remaining: 1024 } };
9
+ if (!Array.isArray(calls) ||
10
+ traversal.ancestors.includes(identity) ||
11
+ traversal.ancestors.length >= 32 ||
12
+ traversal.budget.remaining-- <= 0) {
13
+ input.errors.push({
14
+ code: 'invalid_connector_call_graph',
15
+ path: input.path,
16
+ message: 'Nested connector calls must be acyclic and within the compiler graph bounds',
17
+ });
18
+ return [];
19
+ }
20
+ const next = { ancestors: [...traversal.ancestors, identity], budget: traversal.budget };
21
+ const output = [];
22
+ const seen = new Set();
23
+ for (const target of calls) {
24
+ if (traversal.budget.remaining-- <= 0) {
25
+ input.errors.push({
26
+ code: 'invalid_connector_call_graph',
27
+ path: input.path,
28
+ message: 'Nested connector call graph exceeds the compiler bound',
29
+ });
30
+ break;
31
+ }
32
+ const targetConnector = input.catalog.get(target.connectorId, target.connectorVersion);
33
+ const signature = targetConnector?.operations[target.operation];
34
+ if (signature === undefined ||
35
+ computeSignatureHash(target.operation, signature) !== target.signatureHash) {
36
+ input.errors.push({
37
+ code: 'invalid_connector_call_graph',
38
+ path: input.path,
39
+ message: 'Nested connector identity or signature does not match the declared catalog',
40
+ });
41
+ continue;
42
+ }
43
+ const key = JSON.stringify([target.connectorId, target.connectorVersion, target.operation]);
44
+ if (seen.has(key))
45
+ continue;
46
+ seen.add(key);
47
+ const aliases = Object.entries(input.declared).filter(([, ref]) => ref.id === target.connectorId && ref.version === target.connectorVersion);
48
+ if (aliases.length > 1) {
49
+ input.errors.push({
50
+ code: 'ambiguous_nested_connector_binding',
51
+ path: input.path,
52
+ message: `Nested connector "${target.connectorId}@${target.connectorVersion}" matches multiple aliases; declare one unambiguous account binding for this connector`,
53
+ });
54
+ continue;
55
+ }
56
+ // Unbound catalog-only dependencies retain their existing behavior; credential-required targets
57
+ // still fail normal profile validation when no exact manifest account binding exists.
58
+ const alias = aliases[0]?.[0] ?? `#${target.connectorId}@${target.connectorVersion}`;
59
+ const declared = aliases.length === 0
60
+ ? {
61
+ ...input.declared,
62
+ [alias]: { id: target.connectorId, version: target.connectorVersion },
63
+ }
64
+ : input.declared;
65
+ const resolved = input.resolve({ connectorAlias: alias, operation: target.operation, args: {}, path: `${input.path}.calls` }, declared, next);
66
+ if (resolved.resolved)
67
+ output.push(resolved);
68
+ }
69
+ return output;
70
+ }
71
+ //# sourceMappingURL=nested-operations.js.map
@@ -24,6 +24,13 @@ export class CodeConnector {
24
24
  signature(operation) {
25
25
  return this.#operations[operation]?.signature;
26
26
  }
27
+ executionBoundMs(operation) {
28
+ const op = this.#operations[operation];
29
+ return op === undefined ? undefined : (op.limits ?? DEFAULT_LIMITS).timeoutMs;
30
+ }
31
+ coordination(operation) {
32
+ return this.#operations[operation]?.coordination;
33
+ }
27
34
  async invoke(call) {
28
35
  const op = this.#operations[call.operation];
29
36
  if (!op)
@@ -31,7 +38,7 @@ export class CodeConnector {
31
38
  const instance = await this.#engine.instantiate(op.module);
32
39
  let timings;
33
40
  try {
34
- const output = await instance.invoke(call.args, op.limits ?? DEFAULT_LIMITS, op.calls ? computeHost(op.calls, call.host) : undefined, (t) => {
41
+ const output = await instance.invoke(call.args, op.limits ?? DEFAULT_LIMITS, computeHost(op.calls ?? {}, call), (t) => {
35
42
  timings = t;
36
43
  });
37
44
  // Queue wait and execution are recorded independently so burst head-of-line blocking is
@@ -79,8 +86,13 @@ function classifyInvocationFailure(error, timings) {
79
86
  }),
80
87
  });
81
88
  }
82
- function computeHost(calls, host) {
89
+ function computeHost(calls, call) {
90
+ const host = call.host;
83
91
  return {
92
+ ...(call.execution ? { execution: call.execution } : {}),
93
+ ...(call.coordination ? { coordination: call.coordination } : {}),
94
+ ...(call.resolveCoordination ? { resolveCoordination: call.resolveCoordination } : {}),
95
+ ...(call.reportOutcome ? { reportOutcome: call.reportOutcome } : {}),
84
96
  callOperation(name, args) {
85
97
  if (!host) {
86
98
  throw new ComputeError('host_call_failed', 'host call unavailable');