@noodleseed/one 0.161.2 → 0.162.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 (60) hide show
  1. package/dist/cli.d.ts.map +1 -1
  2. package/dist/cli.js +3 -0
  3. package/dist/cli.js.map +1 -1
  4. package/dist/commands/catalog.d.ts.map +1 -1
  5. package/dist/commands/catalog.js +1 -0
  6. package/dist/commands/catalog.js.map +1 -1
  7. package/dist/commands/solutions-ops.d.ts +7 -0
  8. package/dist/commands/solutions-ops.d.ts.map +1 -0
  9. package/dist/commands/solutions-ops.js +283 -0
  10. package/dist/commands/solutions-ops.js.map +1 -0
  11. package/dist/index.d.ts +1 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -1
  14. package/dist/index.js.map +1 -1
  15. package/node_modules/@noodle-borg/agent-kit/dist/curated/command-groups.js +4 -0
  16. package/node_modules/@noodle-borg/agent-kit/dist/curated/error-fixes.js +2 -1
  17. package/node_modules/@noodle-borg/agent-kit/dist/generated/example-files.js +3 -3
  18. package/node_modules/@noodle-borg/agent-kit/dist/generated/surface.js +3 -0
  19. package/node_modules/@noodle-borg/agent-kit/dist/skill-authoring-refs.js +7 -0
  20. package/node_modules/@noodle-borg/authoring/dist/index.d.ts +1 -0
  21. package/node_modules/@noodle-borg/authoring/dist/index.js +1 -0
  22. package/node_modules/@noodle-borg/authoring/dist/load-authored.js +1 -1
  23. package/node_modules/@noodle-borg/authoring/dist/managed-collection.d.ts +26 -0
  24. package/node_modules/@noodle-borg/authoring/dist/managed-collection.js +20 -0
  25. package/node_modules/@noodle-borg/authoring/dist/server.d.ts +3 -0
  26. package/node_modules/@noodle-borg/authoring/dist/server.js +2 -0
  27. package/node_modules/@noodle-borg/cli-catalog/dist/catalog-data-tenant-resources.js +241 -0
  28. package/node_modules/@noodle-borg/compiler/dist/artifact/assemble.js +4 -1
  29. package/node_modules/@noodle-borg/compiler/dist/artifact/types.d.ts +10 -0
  30. package/node_modules/@noodle-borg/compiler/dist/artifact/version.d.ts +4 -1
  31. package/node_modules/@noodle-borg/compiler/dist/artifact/version.js +4 -1
  32. package/node_modules/@noodle-borg/compiler/dist/compile.js +3 -0
  33. package/node_modules/@noodle-borg/compiler/dist/errors.d.ts +1 -1
  34. package/node_modules/@noodle-borg/compiler/dist/index.d.ts +2 -1
  35. package/node_modules/@noodle-borg/compiler/dist/index.js +1 -0
  36. package/node_modules/@noodle-borg/compiler/dist/managed-collections.d.ts +25 -0
  37. package/node_modules/@noodle-borg/compiler/dist/managed-collections.js +184 -0
  38. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.d.ts +14 -0
  39. package/node_modules/@noodle-borg/compiler/dist/manifest/schema.js +3 -0
  40. package/node_modules/@noodle-borg/service/dist/business-information/contracts.js +5 -0
  41. package/node_modules/@noodle-borg/service/dist/business-information/in-memory-store.js +402 -0
  42. package/node_modules/@noodle-borg/service/dist/business-information/model.js +292 -0
  43. package/node_modules/@noodle-borg/service/dist/business-information/pagination.js +50 -0
  44. package/node_modules/@noodle-borg/service/dist/business-information/portable.js +6 -0
  45. package/node_modules/@noodle-borg/service/dist/business-information/profiles.js +121 -0
  46. package/node_modules/@noodle-borg/service/dist/business-information/validation.js +200 -0
  47. package/node_modules/@noodle-borg/service/dist/oauth/store.d.ts +2 -2
  48. package/node_modules/@noodle-borg/service/dist/routes/business-information-dispatch.js +48 -0
  49. package/node_modules/@noodle-borg/service/dist/routes/business-information-paths.js +92 -0
  50. package/node_modules/@noodle-borg/service/dist/routes/business-information-wire.js +117 -0
  51. package/node_modules/@noodle-borg/service/dist/routes/business-information.js +551 -0
  52. package/node_modules/@noodle-borg/service/dist/service-resource-cleanup.js +2 -0
  53. package/node_modules/@noodle-borg/service/dist/service.js +25 -0
  54. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.d.ts +583 -0
  55. package/node_modules/@noodle-borg/wire-contracts/dist/business-information.js +205 -0
  56. package/node_modules/@noodle-borg/wire-contracts/dist/index.d.ts +4 -3
  57. package/node_modules/@noodle-borg/wire-contracts/dist/index.js +1 -0
  58. package/node_modules/@noodle-borg/wire-contracts/dist/knowledge.d.ts +3 -3
  59. package/node_modules/@noodle-borg/wire-contracts/dist/managed-assistant-sponsorship.d.ts +8 -8
  60. package/package.json +1 -1
@@ -10,6 +10,7 @@ import { type ServerContextOptions } from './context.js';
10
10
  import { type CustomerAuth } from './customer-auth.js';
11
11
  import { type JsonSchema } from './json-schema.js';
12
12
  import { type KnowledgeDeclaration } from './knowledge.js';
13
+ import * as collections from './managed-collection.js';
13
14
  import { type ConnectorClient, type SymbolicScope } from './recording.js';
14
15
  export type StateHandleKind = 'session' | 'draft' | 'selection' | 'search' | 'cart' | 'workflow';
15
16
  export type StateHandleScope = 'deployment' | 'caller';
@@ -50,6 +51,8 @@ export interface ServerOptions {
50
51
  readonly assistant?: EmbeddedAssistantConfig;
51
52
  /** Customer-owned knowledge components (ADR 0202): compile to generated `search_<name>` capabilities. */
52
53
  readonly knowledge?: readonly KnowledgeDeclaration[];
54
+ /** Typed managed records; operator-owned lifecycle and policy are bound outside reusable source. */
55
+ readonly collections?: readonly collections.ManagedCollectionDeclaration[];
53
56
  readonly branding?: {
54
57
  readonly name?: string;
55
58
  readonly accent?: string;
@@ -10,6 +10,7 @@ import { manifestContext } from './context.js';
10
10
  import { manifestCustomerAuth } from './customer-auth.js';
11
11
  import { toJsonSchema } from './json-schema.js';
12
12
  import { manifestKnowledge } from './knowledge.js';
13
+ import * as collections from './managed-collection.js';
13
14
  import { manifestToolAnnotations } from './model-tool-visibility.js';
14
15
  import { recordFulfilment, recordTool, } from './recording.js';
15
16
  const WIDGET_RESULT_META_KEY = '__noodleResultMeta';
@@ -206,6 +207,7 @@ class ServerBuilder {
206
207
  ...(this.options.knowledge && this.options.knowledge.length > 0
207
208
  ? { knowledge: this.options.knowledge.map(manifestKnowledge) }
208
209
  : {}),
210
+ ...collections.manifestCollections(this.options.collections),
209
211
  ...(this.options.branding ? { branding: this.options.branding } : {}),
210
212
  ...(this.options.shell ? { shell: manifestShell(this.options.shell) } : {}),
211
213
  },
@@ -76,6 +76,95 @@ const YES = {
76
76
  type: 'boolean',
77
77
  summary: 'Confirm non-interactively.',
78
78
  };
79
+ const RETENTION = {
80
+ ...OPTIONAL_FLAG,
81
+ name: 'retention-days',
82
+ type: 'integer',
83
+ value: '<days>',
84
+ summary: 'Managed-record retention in days.',
85
+ constraints: { choices: [7, 30, 90], default: 30 },
86
+ };
87
+ const INSTALLATION_ARGUMENT = {
88
+ ...REQUIRED_ARGUMENT,
89
+ name: 'installation',
90
+ summary: 'Solution installation identifier.',
91
+ };
92
+ const COLLECTION_ARGUMENT = {
93
+ ...REQUIRED_ARGUMENT,
94
+ name: 'collection',
95
+ summary: 'Managed collection key.',
96
+ };
97
+ const RECORD_ARGUMENT = {
98
+ ...REQUIRED_ARGUMENT,
99
+ name: 'record',
100
+ summary: 'Managed record identifier.',
101
+ };
102
+ const SOLUTION_COMMON_FLAGS = [ORG, SERVICE, AUTH_TOKEN, JSON_FLAG];
103
+ const RECORD_FLAGS = [
104
+ ...SOLUTION_COMMON_FLAGS,
105
+ {
106
+ ...OPTIONAL_FLAG,
107
+ name: 'data',
108
+ type: 'string',
109
+ value: '<json>',
110
+ summary: 'Structured JSON record data.',
111
+ },
112
+ {
113
+ ...OPTIONAL_FLAG,
114
+ name: 'idempotency-key',
115
+ type: 'string',
116
+ value: '<key>',
117
+ summary: 'Retry-safe create key.',
118
+ },
119
+ {
120
+ ...OPTIONAL_FLAG,
121
+ name: 'expected-revision',
122
+ type: 'integer',
123
+ value: '<revision>',
124
+ summary: 'Expected current record revision.',
125
+ },
126
+ {
127
+ ...OPTIONAL_FLAG,
128
+ name: 'status',
129
+ type: 'string',
130
+ value: '<status>',
131
+ summary: 'Record status or list filter.',
132
+ },
133
+ {
134
+ ...OPTIONAL_FLAG,
135
+ name: 'assignee',
136
+ type: 'string',
137
+ value: '<subject>',
138
+ summary: 'Assignee subject or list filter.',
139
+ },
140
+ {
141
+ ...OPTIONAL_FLAG,
142
+ name: 'note',
143
+ type: 'string',
144
+ value: '<text>',
145
+ summary: 'Operator note text.',
146
+ },
147
+ {
148
+ ...OPTIONAL_FLAG,
149
+ name: 'cursor',
150
+ type: 'string',
151
+ value: '<cursor>',
152
+ summary: 'Opaque page cursor.',
153
+ },
154
+ {
155
+ ...OPTIONAL_FLAG,
156
+ name: 'limit',
157
+ type: 'integer',
158
+ value: '<count>',
159
+ summary: 'Bounded page size.',
160
+ },
161
+ {
162
+ ...OPTIONAL_FLAG,
163
+ name: 'include-deleted',
164
+ type: 'boolean',
165
+ summary: 'Include payload-free tombstones.',
166
+ },
167
+ ];
79
168
  const WATCH_FLAGS = [
80
169
  {
81
170
  ...OPTIONAL_FLAG,
@@ -100,6 +189,158 @@ const DEPLOYMENT_BASE_FLAGS = [ORG, APP, ENV, SERVICE, AUTH_TOKEN];
100
189
  const DEPLOYMENT_INSPECT_FLAGS = [ORG, SERVICE, AUTH_TOKEN, JSON_FLAG];
101
190
  const _GITHUB_BASE_FLAGS = [ORG, APP, SERVICE, AUTH_TOKEN];
102
191
  export const CATALOG_TENANT_RESOURCES = [
192
+ {
193
+ name: 'solutions',
194
+ section: 'resources',
195
+ helpRank: 1,
196
+ summary: 'Install and operate data-driven business solutions.',
197
+ arguments: [],
198
+ flags: [],
199
+ subcommands: [
200
+ {
201
+ name: 'catalog',
202
+ summary: 'List centrally managed solution profiles.',
203
+ arguments: [],
204
+ flags: [SERVICE, AUTH_TOKEN, JSON_FLAG],
205
+ jsonOutput: { mode: 'single' },
206
+ },
207
+ {
208
+ name: 'list',
209
+ summary: 'List solution installations for an organization.',
210
+ arguments: [],
211
+ flags: SOLUTION_COMMON_FLAGS,
212
+ jsonOutput: { mode: 'single' },
213
+ },
214
+ {
215
+ name: 'install',
216
+ summary: 'Install one managed solution profile.',
217
+ arguments: [{ ...REQUIRED_ARGUMENT, name: 'profile', summary: 'Solution profile key.' }],
218
+ flags: [...SOLUTION_COMMON_FLAGS, APP, ENV, RETENTION],
219
+ jsonOutput: { mode: 'single' },
220
+ },
221
+ {
222
+ name: 'inspect',
223
+ summary: 'Inspect one solution installation.',
224
+ arguments: [INSTALLATION_ARGUMENT],
225
+ flags: SOLUTION_COMMON_FLAGS,
226
+ jsonOutput: { mode: 'single' },
227
+ },
228
+ {
229
+ name: 'grants',
230
+ summary: 'Manage installation-scoped business grants.',
231
+ arguments: [],
232
+ flags: [],
233
+ subcommands: [
234
+ {
235
+ name: 'list',
236
+ summary: 'List live business grants.',
237
+ arguments: [INSTALLATION_ARGUMENT],
238
+ flags: SOLUTION_COMMON_FLAGS,
239
+ jsonOutput: { mode: 'single' },
240
+ },
241
+ {
242
+ name: 'set',
243
+ summary: 'Create or update a business grant.',
244
+ arguments: [INSTALLATION_ARGUMENT],
245
+ flags: [
246
+ ...SOLUTION_COMMON_FLAGS,
247
+ {
248
+ ...OPTIONAL_FLAG,
249
+ name: 'subject',
250
+ type: 'string',
251
+ value: '<subject>',
252
+ summary: 'Canonical business-user subject.',
253
+ required: true,
254
+ },
255
+ {
256
+ ...OPTIONAL_FLAG,
257
+ name: 'email',
258
+ type: 'string',
259
+ value: '<email>',
260
+ summary: 'Business-user email address.',
261
+ required: true,
262
+ },
263
+ {
264
+ ...OPTIONAL_FLAG,
265
+ name: 'role',
266
+ type: 'string',
267
+ value: '<role>',
268
+ summary: 'Business role.',
269
+ required: true,
270
+ constraints: { choices: ['administrator', 'manager', 'operator', 'viewer'] },
271
+ },
272
+ {
273
+ ...OPTIONAL_FLAG,
274
+ name: 'expected-revision',
275
+ type: 'integer',
276
+ value: '<revision>',
277
+ summary: 'Expected current grant revision; 0 for a new grant.',
278
+ },
279
+ ],
280
+ jsonOutput: { mode: 'single' },
281
+ },
282
+ {
283
+ name: 'revoke',
284
+ summary: 'Revoke a business grant using optimistic concurrency.',
285
+ arguments: [INSTALLATION_ARGUMENT],
286
+ flags: [
287
+ ...SOLUTION_COMMON_FLAGS,
288
+ {
289
+ ...OPTIONAL_FLAG,
290
+ name: 'subject',
291
+ type: 'string',
292
+ value: '<subject>',
293
+ summary: 'Canonical business-user subject.',
294
+ required: true,
295
+ },
296
+ {
297
+ ...OPTIONAL_FLAG,
298
+ name: 'expected-revision',
299
+ type: 'integer',
300
+ value: '<revision>',
301
+ summary: 'Expected current grant revision.',
302
+ required: true,
303
+ },
304
+ ],
305
+ jsonOutput: { mode: 'single' },
306
+ },
307
+ ],
308
+ },
309
+ {
310
+ name: 'records',
311
+ summary: 'Operate one installed managed collection.',
312
+ arguments: [],
313
+ flags: [],
314
+ usage: 'solutions records <list|create|get|update|assign|status|note|activity|delete|export> <installation> <collection> [record] [options]',
315
+ subcommands: [
316
+ ...[
317
+ 'list',
318
+ 'create',
319
+ 'get',
320
+ 'update',
321
+ 'assign',
322
+ 'status',
323
+ 'note',
324
+ 'activity',
325
+ 'delete',
326
+ 'export',
327
+ ].map((name) => ({
328
+ name,
329
+ summary: `${name[0]?.toUpperCase()}${name.slice(1)} managed records.`,
330
+ arguments: [
331
+ INSTALLATION_ARGUMENT,
332
+ COLLECTION_ARGUMENT,
333
+ ...(name === 'list' || name === 'create' || name === 'export'
334
+ ? []
335
+ : [RECORD_ARGUMENT]),
336
+ ],
337
+ flags: RECORD_FLAGS,
338
+ jsonOutput: { mode: 'single' },
339
+ })),
340
+ ],
341
+ },
342
+ ],
343
+ },
103
344
  {
104
345
  name: 'apps',
105
346
  section: 'resources',
@@ -1,6 +1,6 @@
1
1
  import { artifactConfig } from './config.js';
2
2
  import { ARTIFACT_SCHEMA_VERSION, } from './types.js';
3
- export function assembleRuntimeArtifact({ manifest, options, runtimeBranding, runtimeShell, artifactAmbientContext, state, artifactTools, allResources, artifactPrompts, packagedAssets, requirements, declared, customerEndpoints, knowledge, }) {
3
+ export function assembleRuntimeArtifact({ manifest, options, runtimeBranding, runtimeShell, artifactAmbientContext, state, artifactTools, allResources, artifactPrompts, packagedAssets, requirements, declared, customerEndpoints, knowledge, managedCollections, }) {
4
4
  // 4. Assemble the artifact. `resources`/`prompts` and their capability lists are emitted only when
5
5
  // present, keeping a tools-only artifact byte-identical to before this slice.
6
6
  const capabilities = {
@@ -40,6 +40,9 @@ export function assembleRuntimeArtifact({ manifest, options, runtimeBranding, ru
40
40
  : {}),
41
41
  ...(manifest.server.auth !== undefined ? { auth: manifest.server.auth } : {}),
42
42
  ...(knowledge !== undefined && knowledge.length > 0 ? { knowledge } : {}),
43
+ ...(managedCollections !== undefined && managedCollections.length > 0
44
+ ? { managedCollections }
45
+ : {}),
43
46
  ...(manifest.server.assistant !== undefined ? { assistant: manifest.server.assistant } : {}),
44
47
  ...(runtimeBranding !== undefined ? { branding: runtimeBranding } : {}),
45
48
  ...(runtimeShell !== undefined ? { shell: runtimeShell } : {}),
@@ -165,6 +165,14 @@ export interface ArtifactServerContext {
165
165
  readonly fulfilment: ArtifactFulfilment;
166
166
  };
167
167
  }
168
+ export interface ArtifactManagedCollection {
169
+ readonly name: string;
170
+ readonly title: string;
171
+ readonly description: string;
172
+ readonly schemaVersion: number;
173
+ readonly schemaDigest: string;
174
+ readonly recordSchema: JsonSchema;
175
+ }
168
176
  interface ArtifactOidcAuth {
169
177
  readonly kind?: 'oidc' | undefined;
170
178
  readonly issuer: string;
@@ -227,6 +235,8 @@ export interface ArtifactServer {
227
235
  readonly auth?: ArtifactAuth;
228
236
  /** Compiled knowledge components (ADR 0202, Core v2): descriptors + generated tool metadata, never bytes. */
229
237
  readonly knowledge?: readonly CompiledKnowledgeComponent[];
238
+ /** Compiled managed-record schema intent; lifecycle and operator state remain outside artifacts. */
239
+ readonly managedCollections?: readonly ArtifactManagedCollection[];
230
240
  readonly assistant?: {
231
241
  readonly model: NonNullable<Manifest['server']['assistant']>['model'];
232
242
  readonly allowedOrigins: readonly string[];
@@ -50,8 +50,11 @@
50
50
  *
51
51
  * `0.16.0` (Anonymous-to-authenticated onboarding): additive — finite caller-scoped state handles may
52
52
  * opt into atomic ownership adoption when a single-use assistant sign-in ticket is spent.
53
+ *
54
+ * `0.17.0` (Managed collection declaration): additive — Core v2 reusable managed-record schema intent
55
+ * may be projected under `server.managedCollections`; lifecycle and operator state remain separate.
53
56
  */
54
- export declare const ARTIFACT_SCHEMA_VERSION = "0.16.0";
57
+ export declare const ARTIFACT_SCHEMA_VERSION = "0.17.0";
55
58
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
56
59
  export declare const MCP_APP_MIME_TYPE = "text/html;profile=mcp-app";
57
60
  //# sourceMappingURL=version.d.ts.map
@@ -50,8 +50,11 @@
50
50
  *
51
51
  * `0.16.0` (Anonymous-to-authenticated onboarding): additive — finite caller-scoped state handles may
52
52
  * opt into atomic ownership adoption when a single-use assistant sign-in ticket is spent.
53
+ *
54
+ * `0.17.0` (Managed collection declaration): additive — Core v2 reusable managed-record schema intent
55
+ * may be projected under `server.managedCollections`; lifecycle and operator state remain separate.
53
56
  */
54
- export const ARTIFACT_SCHEMA_VERSION = '0.16.0';
57
+ export const ARTIFACT_SCHEMA_VERSION = '0.17.0';
55
58
  /** mimeType for an MCP Apps UI resource (SEP-1865). Widgets are served under this profile. */
56
59
  export const MCP_APP_MIME_TYPE = 'text/html;profile=mcp-app';
57
60
  //# sourceMappingURL=version.js.map
@@ -12,6 +12,7 @@ import { brandingWarnings, normalizeRuntimeBranding } from './branding.js';
12
12
  import { validateInteractiveFlow } from './confirmation-flow.js';
13
13
  import { parseAmbientContext } from './context-compile.js';
14
14
  import { findExternalRef, parseFulfilment } from './fulfilment-structural.js';
15
+ import { compileManagedCollections } from './managed-collections.js';
15
16
  import { cspOriginFaults } from './manifest/csp-origins.js';
16
17
  import { parseManifestDocument } from './manifest/parse-document.js';
17
18
  import { manifestSchema } from './manifest/schema.js';
@@ -143,6 +144,7 @@ export function compileManifest(raw, options = {}) {
143
144
  // 2. Structural passes (catalog-independent): duplicate names, `$use` resolution, external refs,
144
145
  // fulfilment parsing. `$use` is resolved first so external-ref detection also scans bundled defs.
145
146
  const errors = widgetHtmlSizeErrors(manifest, runtimeBranding);
147
+ const managedCollections = compileManagedCollections(manifest.manifestVersion === '2' ? (manifest.server.collections ?? []) : [], manifest.tools.map((tool) => tool.name), errors);
146
148
  const requirements = parseCapabilityRequirements(manifest.requires, errors);
147
149
  const seen = new Set();
148
150
  const schemasMap = manifest.schemas ?? {};
@@ -434,6 +436,7 @@ export function compileManifest(raw, options = {}) {
434
436
  declared,
435
437
  customerEndpoints,
436
438
  ...(knowledge.length > 0 ? { knowledge } : {}),
439
+ ...(managedCollections.length > 0 ? { managedCollections } : {}),
437
440
  });
438
441
  const warnings = [
439
442
  ...brandingWarnings(manifest.server.branding),
@@ -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' | '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' | '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';
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. */
@@ -3,7 +3,7 @@ export { APP_PACKAGE_V1_VALIDATION_LIMITS, appPackageArtifactV1Schema, canonical
3
3
  export { type ParsedUri, type ParseUriResult, parseUriTemplate, type TemplateUri, } from '@noodle-borg/uri-template';
4
4
  export { compileAppPackage } from './app-package/compile.js';
5
5
  export { isSafeReadTool, requiresToolConfirmation } from './artifact/consent.js';
6
- export { ARTIFACT_SCHEMA_VERSION, type ArtifactConnectionSource, type ArtifactConnectorBinding, type ArtifactCustomerAuthRouting, type ArtifactFulfilment, type ArtifactMeta, type ArtifactPackagedAsset, type ArtifactPrompt, type ArtifactPromptArgument, type ArtifactResource, type ArtifactServer, type ArtifactServerContext, type ArtifactState, type ArtifactStateHandle, type ArtifactStateHandleKind, type ArtifactStateHandleScope, type ArtifactStep, type ArtifactTool, type ArtifactToolAuthorization, type ExprMap, type JsonSchema, MCP_APP_MIME_TYPE, type OperationRef, type ResolvedCredentialBinding, type ResolvedOperationRef, type RuntimeArtifact, type UnresolvedOperationRef, type WidgetUiMeta, } from './artifact/types.js';
6
+ export { ARTIFACT_SCHEMA_VERSION, type ArtifactConnectionSource, type ArtifactConnectorBinding, type ArtifactCustomerAuthRouting, type ArtifactFulfilment, type ArtifactManagedCollection, type ArtifactMeta, type ArtifactPackagedAsset, type ArtifactPrompt, type ArtifactPromptArgument, type ArtifactResource, type ArtifactServer, type ArtifactServerContext, type ArtifactState, type ArtifactStateHandle, type ArtifactStateHandleKind, type ArtifactStateHandleScope, type ArtifactStep, type ArtifactTool, type ArtifactToolAuthorization, type ExprMap, type JsonSchema, MCP_APP_MIME_TYPE, type OperationRef, type ResolvedCredentialBinding, type ResolvedOperationRef, type RuntimeArtifact, type UnresolvedOperationRef, type WidgetUiMeta, } from './artifact/types.js';
7
7
  export { assetReference, type HostedAssetOptions, type HostedPackagedAsset, isPackagedAssetReference, type LocalAssetOptions, localAssetRoutePrefix, type PackagedAsset, type PackagedAssetReference, type PreparedPackagedAsset, prepareLocalAssets, } from './assets.js';
8
8
  export { InMemoryCatalog } from './catalog/in-memory.js';
9
9
  export { isLegacyFieldMap, normalizeOperationIoSchema } from './catalog/io-schema.js';
@@ -13,6 +13,7 @@ export { type CompileOptions, compile, compileManifest, type ValidateResult, val
13
13
  export { type CustomerEndpointPolicy, type CustomerEndpointRef, isCustomerEndpointRef, isValidCustomerEndpointName, normalizeCustomerEndpointPolicy, resolveCustomerEndpointBaseUrl, } from './customer-endpoint.js';
14
14
  export type { CompileError, CompileErrorCode, CompileResult } from './errors.js';
15
15
  export { computeConnectionConfigRevision } from './fulfilment-emit.js';
16
+ export { MAX_MANAGED_COLLECTION_DESCRIPTION_LENGTH, MAX_MANAGED_COLLECTION_NAME_LENGTH, MAX_MANAGED_COLLECTION_RECORD_FIELDS, MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES, MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH, MAX_MANAGED_COLLECTION_SCHEMA_VERSION, MAX_MANAGED_COLLECTION_TITLE_LENGTH, MAX_MANAGED_COLLECTIONS, type ManagedCollectionManifest, } from './managed-collections.js';
16
17
  export { type CspFault, type CspList, cspFaultsInManifest, cspOriginFaults, isHonorableCspOrigin, } from './manifest/csp-origins.js';
17
18
  export { type ArrayNode, type CoalesceNode, type CondNode, type ExprNode, type ObjectEntry, type ObjectNode, type PathNode, type PathSegment, parseCondition, parseValue, } from './manifest/expression.js';
18
19
  export { isValidName, parseOperationRef } from './manifest/naming.js';
@@ -10,6 +10,7 @@ export { computeSignatureHash } from './catalog/signature.js';
10
10
  export { compile, compileManifest, validateManifest, } from './compile.js';
11
11
  export { isCustomerEndpointRef, isValidCustomerEndpointName, normalizeCustomerEndpointPolicy, resolveCustomerEndpointBaseUrl, } from './customer-endpoint.js';
12
12
  export { computeConnectionConfigRevision } from './fulfilment-emit.js';
13
+ export { MAX_MANAGED_COLLECTION_DESCRIPTION_LENGTH, MAX_MANAGED_COLLECTION_NAME_LENGTH, MAX_MANAGED_COLLECTION_RECORD_FIELDS, MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES, MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH, MAX_MANAGED_COLLECTION_SCHEMA_VERSION, MAX_MANAGED_COLLECTION_TITLE_LENGTH, MAX_MANAGED_COLLECTIONS, } from './managed-collections.js';
13
14
  export { cspFaultsInManifest, cspOriginFaults, isHonorableCspOrigin, } from './manifest/csp-origins.js';
14
15
  export { parseCondition, parseValue, } from './manifest/expression.js';
15
16
  export { isValidName, parseOperationRef } from './manifest/naming.js';
@@ -0,0 +1,25 @@
1
+ import { z } from 'zod';
2
+ import type { ArtifactManagedCollection } from './artifact/types.js';
3
+ import type { CompileError } from './errors.js';
4
+ export declare const MAX_MANAGED_COLLECTIONS = 16;
5
+ export declare const MAX_MANAGED_COLLECTION_NAME_LENGTH = 64;
6
+ export declare const MAX_MANAGED_COLLECTION_TITLE_LENGTH = 120;
7
+ export declare const MAX_MANAGED_COLLECTION_DESCRIPTION_LENGTH = 1000;
8
+ export declare const MAX_MANAGED_COLLECTION_SCHEMA_VERSION = 2147483647;
9
+ export declare const MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES: number;
10
+ export declare const MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH = 12;
11
+ export declare const MAX_MANAGED_COLLECTION_RECORD_FIELDS = 128;
12
+ export declare const managedCollectionManifestSchema: z.ZodObject<{
13
+ name: z.ZodString;
14
+ title: z.ZodString;
15
+ description: z.ZodString;
16
+ schemaVersion: z.ZodNumber;
17
+ recordSchema: z.ZodRecord<z.ZodString, z.ZodUnknown>;
18
+ }, z.core.$strict>;
19
+ export type ManagedCollectionManifest = z.infer<typeof managedCollectionManifestSchema>;
20
+ /**
21
+ * Validate and lower reusable collection intent. Operator lifecycle, grants, residency, and
22
+ * retention deliberately do not enter this compiled definition.
23
+ */
24
+ export declare function compileManagedCollections(collections: readonly ManagedCollectionManifest[], toolNames: readonly string[], errors: CompileError[]): readonly ArtifactManagedCollection[];
25
+ //# sourceMappingURL=managed-collections.d.ts.map
@@ -0,0 +1,184 @@
1
+ import { canonicalJson, sha256Canonical } from '@noodle-borg/app-package';
2
+ import { z } from 'zod';
3
+ export const MAX_MANAGED_COLLECTIONS = 16;
4
+ export const MAX_MANAGED_COLLECTION_NAME_LENGTH = 64;
5
+ export const MAX_MANAGED_COLLECTION_TITLE_LENGTH = 120;
6
+ export const MAX_MANAGED_COLLECTION_DESCRIPTION_LENGTH = 1_000;
7
+ export const MAX_MANAGED_COLLECTION_SCHEMA_VERSION = 2_147_483_647;
8
+ export const MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES = 64 * 1024;
9
+ export const MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH = 12;
10
+ export const MAX_MANAGED_COLLECTION_RECORD_FIELDS = 128;
11
+ const collectionNameSchema = z
12
+ .string()
13
+ .min(1)
14
+ .max(MAX_MANAGED_COLLECTION_NAME_LENGTH)
15
+ .regex(/^[a-z][a-z0-9_]*$/, 'must start with a letter and use lowercase letters, numbers, and underscores');
16
+ const jsonSchemaSchema = z.record(z.string(), z.unknown());
17
+ export const managedCollectionManifestSchema = z
18
+ .object({
19
+ name: collectionNameSchema,
20
+ title: z.string().trim().min(1).max(MAX_MANAGED_COLLECTION_TITLE_LENGTH),
21
+ description: z.string().trim().min(1).max(MAX_MANAGED_COLLECTION_DESCRIPTION_LENGTH),
22
+ schemaVersion: z.number().int().positive().max(MAX_MANAGED_COLLECTION_SCHEMA_VERSION),
23
+ recordSchema: jsonSchemaSchema,
24
+ })
25
+ .strict();
26
+ const PROHIBITED_FIELD_NAME = /(?:card|cvv|cvc|password|passcode|token|secret|passport|governmentid|nationalid|socialsecurity|health|biometric)/i;
27
+ const SUBSCHEMA_MAP_KEYS = [
28
+ 'properties',
29
+ 'patternProperties',
30
+ '$defs',
31
+ 'dependentSchemas',
32
+ ];
33
+ const SUBSCHEMA_KEYS = [
34
+ 'items',
35
+ 'additionalProperties',
36
+ 'propertyNames',
37
+ 'not',
38
+ 'contains',
39
+ 'if',
40
+ 'then',
41
+ 'else',
42
+ ];
43
+ const SUBSCHEMA_LIST_KEYS = ['prefixItems', 'allOf', 'anyOf', 'oneOf'];
44
+ /**
45
+ * Validate and lower reusable collection intent. Operator lifecycle, grants, residency, and
46
+ * retention deliberately do not enter this compiled definition.
47
+ */
48
+ export function compileManagedCollections(collections, toolNames, errors) {
49
+ const compiled = [];
50
+ const seen = new Set();
51
+ collections.forEach((collection, index) => {
52
+ const path = `server.collections.${index}`;
53
+ if (seen.has(collection.name)) {
54
+ errors.push({
55
+ code: 'invalid_managed_collection',
56
+ path: `${path}.name`,
57
+ message: `duplicate managed collection name "${collection.name}"`,
58
+ });
59
+ return;
60
+ }
61
+ seen.add(collection.name);
62
+ const futureToolName = `submit_${collection.name}`;
63
+ const collision = toolNames.indexOf(futureToolName);
64
+ if (collision >= 0) {
65
+ errors.push({
66
+ code: 'reserved_name',
67
+ path: `tools.${collision}.name`,
68
+ message: `tool name "${futureToolName}" is reserved for managed collection "${collection.name}"`,
69
+ });
70
+ }
71
+ const schemaErrorsBefore = errors.length;
72
+ validateRecordSchema(collection.recordSchema, `${path}.recordSchema`, errors);
73
+ if (errors.length !== schemaErrorsBefore)
74
+ return;
75
+ compiled.push({
76
+ name: collection.name,
77
+ title: collection.title,
78
+ description: collection.description,
79
+ schemaVersion: collection.schemaVersion,
80
+ schemaDigest: sha256Canonical(collection.recordSchema),
81
+ recordSchema: collection.recordSchema,
82
+ });
83
+ });
84
+ return compiled;
85
+ }
86
+ function validateRecordSchema(schema, path, errors) {
87
+ const bytes = new TextEncoder().encode(canonicalJson(schema)).byteLength;
88
+ if (bytes > MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES) {
89
+ errors.push({
90
+ code: 'invalid_managed_collection',
91
+ path,
92
+ message: `record schema is ${bytes} UTF-8 bytes; the limit is ${MAX_MANAGED_COLLECTION_RECORD_SCHEMA_BYTES} bytes`,
93
+ });
94
+ return;
95
+ }
96
+ if (schema.type !== 'object' || schema.additionalProperties !== false) {
97
+ errors.push({
98
+ code: 'invalid_managed_collection',
99
+ path,
100
+ message: 'record schema must be a closed object with additionalProperties false',
101
+ });
102
+ return;
103
+ }
104
+ const state = { fields: 0, failure: undefined };
105
+ inspectSchema(schema, path, 1, state);
106
+ if (state.failure !== undefined)
107
+ errors.push(state.failure);
108
+ }
109
+ function inspectSchema(node, path, depth, state) {
110
+ if (state.failure !== undefined ||
111
+ node === null ||
112
+ typeof node !== 'object' ||
113
+ Array.isArray(node)) {
114
+ return;
115
+ }
116
+ if (depth > MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH) {
117
+ state.failure = {
118
+ code: 'invalid_managed_collection',
119
+ path,
120
+ message: `record schema depth exceeds ${MAX_MANAGED_COLLECTION_RECORD_SCHEMA_DEPTH}`,
121
+ };
122
+ return;
123
+ }
124
+ const schema = node;
125
+ if (schema.type === 'object' && schema.additionalProperties !== false) {
126
+ state.failure = {
127
+ code: 'invalid_managed_collection',
128
+ path,
129
+ message: 'every record object must set additionalProperties to false',
130
+ };
131
+ return;
132
+ }
133
+ const properties = schema.properties;
134
+ if (isRecord(properties)) {
135
+ for (const [name, child] of Object.entries(properties)) {
136
+ state.fields += 1;
137
+ if (state.fields > MAX_MANAGED_COLLECTION_RECORD_FIELDS) {
138
+ state.failure = {
139
+ code: 'invalid_managed_collection',
140
+ path,
141
+ message: `record schema declares more than ${MAX_MANAGED_COLLECTION_RECORD_FIELDS} fields`,
142
+ };
143
+ return;
144
+ }
145
+ if (PROHIBITED_FIELD_NAME.test(name.replace(/[^a-z0-9]/giu, ''))) {
146
+ state.failure = {
147
+ code: 'invalid_managed_collection',
148
+ path: `${path}.properties.${name}`,
149
+ message: 'managed collection record schemas cannot declare prohibited sensitive fields',
150
+ };
151
+ return;
152
+ }
153
+ inspectSchema(child, `${path}.properties.${name}`, depth + 1, state);
154
+ }
155
+ }
156
+ for (const key of SUBSCHEMA_MAP_KEYS) {
157
+ if (key === 'properties')
158
+ continue;
159
+ const map = schema[key];
160
+ if (!isRecord(map))
161
+ continue;
162
+ for (const [name, child] of Object.entries(map)) {
163
+ inspectSchema(child, `${path}.${key}.${name}`, depth + 1, state);
164
+ }
165
+ }
166
+ for (const key of SUBSCHEMA_KEYS) {
167
+ const child = schema[key];
168
+ if (child !== undefined && typeof child !== 'boolean') {
169
+ inspectSchema(child, `${path}.${key}`, depth + 1, state);
170
+ }
171
+ }
172
+ for (const key of SUBSCHEMA_LIST_KEYS) {
173
+ const children = schema[key];
174
+ if (!Array.isArray(children))
175
+ continue;
176
+ children.forEach((child, index) => {
177
+ inspectSchema(child, `${path}.${key}.${index}`, depth + 1, state);
178
+ });
179
+ }
180
+ }
181
+ function isRecord(value) {
182
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
183
+ }
184
+ //# sourceMappingURL=managed-collections.js.map