@canonmsg/backend-contracts 2.3.0 → 3.0.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.
@@ -212,9 +212,68 @@
212
212
  ]
213
213
  },
214
214
  "sessionConfig": {
215
- "type": [
216
- "object",
217
- "null"
215
+ "oneOf": [
216
+ {
217
+ "type": "object",
218
+ "description": "Typed setup policy for an agent target. Values are stable runtime-advertised option ids and are validated against the target descriptor before session creation; labels, prompts, workspace paths, and arbitrary fields are not permitted.",
219
+ "additionalProperties": false,
220
+ "properties": {
221
+ "model": {
222
+ "type": "string",
223
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
224
+ "maxLength": 256
225
+ },
226
+ "permissionMode": {
227
+ "type": "string",
228
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
229
+ "maxLength": 256
230
+ },
231
+ "effort": {
232
+ "type": "string",
233
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
234
+ "maxLength": 256
235
+ },
236
+ "workspaceId": {
237
+ "type": "string",
238
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
239
+ "maxLength": 256
240
+ },
241
+ "executionMode": {
242
+ "enum": [
243
+ "worktree",
244
+ "locked"
245
+ ]
246
+ },
247
+ "runtimeControlValues": {
248
+ "type": "object",
249
+ "maxProperties": 24,
250
+ "propertyNames": {
251
+ "pattern": "^[A-Za-z0-9_-]{1,80}$",
252
+ "not": {
253
+ "enum": [
254
+ "model",
255
+ "workspace",
256
+ "executionMode",
257
+ "permissionMode",
258
+ "effort",
259
+ "interrupt",
260
+ "runtimeControlValues",
261
+ "updatedAt",
262
+ "updatedBy"
263
+ ]
264
+ }
265
+ },
266
+ "additionalProperties": {
267
+ "type": "string",
268
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
269
+ "maxLength": 256
270
+ }
271
+ }
272
+ }
273
+ },
274
+ {
275
+ "type": "null"
276
+ }
218
277
  ]
219
278
  },
220
279
  "idempotencyKey": {
@@ -253,7 +312,99 @@
253
312
  "$ref": "#/$defs/turn"
254
313
  },
255
314
  "native": {
256
- "type": "object"
315
+ "type": "object",
316
+ "description": "Content-free runtime correlation ids. Commands, paths, prompts, summaries, and model labels are not permitted in this public envelope.",
317
+ "maxProperties": 24,
318
+ "additionalProperties": false,
319
+ "properties": {
320
+ "runtime": {
321
+ "type": "string",
322
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
323
+ "maxLength": 256
324
+ },
325
+ "method": {
326
+ "type": "string",
327
+ "pattern": "^[A-Za-z0-9_][A-Za-z0-9_./:\\-]{0,255}$",
328
+ "maxLength": 256
329
+ },
330
+ "requestId": {
331
+ "type": "string",
332
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
333
+ "maxLength": 256
334
+ },
335
+ "provider": {
336
+ "type": "string",
337
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
338
+ "maxLength": 256
339
+ },
340
+ "origin": {
341
+ "type": "string",
342
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
343
+ "maxLength": 256
344
+ },
345
+ "surface": {
346
+ "type": "string",
347
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
348
+ "maxLength": 256
349
+ },
350
+ "threadId": {
351
+ "type": "string",
352
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
353
+ "maxLength": 256
354
+ },
355
+ "turnId": {
356
+ "type": "string",
357
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
358
+ "maxLength": 256
359
+ },
360
+ "runId": {
361
+ "type": "string",
362
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
363
+ "maxLength": 256
364
+ },
365
+ "itemId": {
366
+ "type": "string",
367
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
368
+ "maxLength": 256
369
+ },
370
+ "toolCallId": {
371
+ "type": "string",
372
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
373
+ "maxLength": 256
374
+ },
375
+ "approvalId": {
376
+ "type": "string",
377
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
378
+ "maxLength": 256
379
+ },
380
+ "pluginId": {
381
+ "type": "string",
382
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
383
+ "maxLength": 256
384
+ },
385
+ "sessionKey": {
386
+ "type": "string",
387
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
388
+ "maxLength": 256
389
+ },
390
+ "nodeId": {
391
+ "type": "string",
392
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
393
+ "maxLength": 256
394
+ },
395
+ "handles": {
396
+ "type": "object",
397
+ "maxProperties": 16,
398
+ "propertyNames": {
399
+ "pattern": "^[A-Za-z0-9_.:-]{1,80}$"
400
+ },
401
+ "additionalProperties": {
402
+ "type": "string",
403
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
404
+ "maxLength": 256
405
+ }
406
+ }
407
+ }
257
408
  },
258
409
  "runtimeId": {
259
410
  "type": "string",
@@ -38,6 +38,8 @@
38
38
  "nativeKeys": 24,
39
39
  "nativeValueChars": 256,
40
40
  "nativeHandles": 16,
41
+ "sessionConfigValues": 24,
42
+ "sessionConfigValueChars": 256,
41
43
  "minTimeoutMs": 1000,
42
44
  "maxTimeoutMs": 1800000,
43
45
  "maxApprovalTimeoutMs": 259200000,
@@ -55,7 +57,13 @@
55
57
  "cardId": "^[A-Za-z0-9_.:-]{1,80}$",
56
58
  "actionId": "^[A-Za-z0-9_.:-]{1,80}$",
57
59
  "questionId": "^[A-Za-z0-9_.:-]{1,120}$",
58
- "sessionRuleToolPattern": "^[\\w.*:-]{1,128}$"
60
+ "sessionRuleToolPattern": "^[\\w.*:-]{1,128}$",
61
+ "runtimeCorrelationValue": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
62
+ "runtimeMethod": "^[A-Za-z0-9_][A-Za-z0-9_./:\\-]{0,255}$",
63
+ "runtimeOptionValue": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
64
+ "workspaceOptionId": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
65
+ "runtimeHandleKey": "^[A-Za-z0-9_.:-]{1,80}$",
66
+ "runtimeControlId": "^[A-Za-z0-9_-]{1,80}$"
59
67
  },
60
68
  "byteSemantics": {
61
69
  "send_to.text": "utf8_bytes<=messageTextBytes",
@@ -424,8 +424,156 @@
424
424
  },
425
425
  "native": {
426
426
  "type": "object",
427
- "description": "Runtime correlation handles (<= 24 keys, string values <= 256 chars or a nested handles map <= 16; functions/src/api/interactionKinds.ts normalizeNative).",
428
- "additionalProperties": true
427
+ "description": "Content-free runtime correlation ids. Commands, paths, prompts, summaries, and model labels are not permitted in this public envelope.",
428
+ "maxProperties": 24,
429
+ "additionalProperties": false,
430
+ "properties": {
431
+ "runtime": {
432
+ "type": "string",
433
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
434
+ "maxLength": 256
435
+ },
436
+ "method": {
437
+ "type": "string",
438
+ "pattern": "^[A-Za-z0-9_][A-Za-z0-9_./:\\-]{0,255}$",
439
+ "maxLength": 256
440
+ },
441
+ "requestId": {
442
+ "type": "string",
443
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
444
+ "maxLength": 256
445
+ },
446
+ "provider": {
447
+ "type": "string",
448
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
449
+ "maxLength": 256
450
+ },
451
+ "origin": {
452
+ "type": "string",
453
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
454
+ "maxLength": 256
455
+ },
456
+ "surface": {
457
+ "type": "string",
458
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
459
+ "maxLength": 256
460
+ },
461
+ "threadId": {
462
+ "type": "string",
463
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
464
+ "maxLength": 256
465
+ },
466
+ "turnId": {
467
+ "type": "string",
468
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
469
+ "maxLength": 256
470
+ },
471
+ "runId": {
472
+ "type": "string",
473
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
474
+ "maxLength": 256
475
+ },
476
+ "itemId": {
477
+ "type": "string",
478
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
479
+ "maxLength": 256
480
+ },
481
+ "toolCallId": {
482
+ "type": "string",
483
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
484
+ "maxLength": 256
485
+ },
486
+ "approvalId": {
487
+ "type": "string",
488
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
489
+ "maxLength": 256
490
+ },
491
+ "pluginId": {
492
+ "type": "string",
493
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
494
+ "maxLength": 256
495
+ },
496
+ "sessionKey": {
497
+ "type": "string",
498
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
499
+ "maxLength": 256
500
+ },
501
+ "nodeId": {
502
+ "type": "string",
503
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
504
+ "maxLength": 256
505
+ },
506
+ "handles": {
507
+ "type": "object",
508
+ "maxProperties": 16,
509
+ "propertyNames": {
510
+ "pattern": "^[A-Za-z0-9_.:-]{1,80}$"
511
+ },
512
+ "additionalProperties": {
513
+ "type": "string",
514
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
515
+ "maxLength": 256
516
+ }
517
+ }
518
+ }
519
+ },
520
+ "sessionConfig": {
521
+ "type": "object",
522
+ "description": "Typed setup policy for an agent target. Values are stable runtime-advertised option ids and are validated against the target descriptor before session creation; labels, prompts, workspace paths, and arbitrary fields are not permitted.",
523
+ "additionalProperties": false,
524
+ "properties": {
525
+ "model": {
526
+ "type": "string",
527
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
528
+ "maxLength": 256
529
+ },
530
+ "permissionMode": {
531
+ "type": "string",
532
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
533
+ "maxLength": 256
534
+ },
535
+ "effort": {
536
+ "type": "string",
537
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
538
+ "maxLength": 256
539
+ },
540
+ "workspaceId": {
541
+ "type": "string",
542
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$",
543
+ "maxLength": 256
544
+ },
545
+ "executionMode": {
546
+ "enum": [
547
+ "worktree",
548
+ "locked"
549
+ ]
550
+ },
551
+ "runtimeControlValues": {
552
+ "type": "object",
553
+ "maxProperties": 24,
554
+ "propertyNames": {
555
+ "pattern": "^[A-Za-z0-9_-]{1,80}$",
556
+ "not": {
557
+ "enum": [
558
+ "model",
559
+ "workspace",
560
+ "executionMode",
561
+ "permissionMode",
562
+ "effort",
563
+ "interrupt",
564
+ "runtimeControlValues",
565
+ "updatedAt",
566
+ "updatedBy"
567
+ ]
568
+ }
569
+ },
570
+ "additionalProperties": {
571
+ "type": "string",
572
+ "pattern": "^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$",
573
+ "maxLength": 256
574
+ }
575
+ }
576
+ }
429
577
  },
430
578
  "send_to_input": {
431
579
  "type": "object",
@@ -466,9 +614,13 @@
466
614
  "$ref": "#/$defs/sessionSelection"
467
615
  },
468
616
  "sessionConfig": {
469
- "type": [
470
- "object",
471
- "null"
617
+ "oneOf": [
618
+ {
619
+ "$ref": "#/$defs/sessionConfig"
620
+ },
621
+ {
622
+ "type": "null"
623
+ }
472
624
  ],
473
625
  "description": "Coding-agent session setup (model/permissionMode/effort/workspaceId/executionMode); only applied to agent targets, stripped for humans."
474
626
  },
@@ -41,7 +41,8 @@
41
41
  * canon-verbs.limits.json) after schema validation.
42
42
  */
43
43
  Object.defineProperty(exports, "__esModule", { value: true });
44
- exports.CANON_VERB_LIMITS_ARTIFACT = exports.CREATE_GROUP_CREATOR_SETUP_REQUIRED_CODE = exports.CREATE_GROUP_NO_ADDABLE_MEMBERS_CODE = exports.CANON_VERB_NAMES = exports.SELF_CONTEXT_TYPE = exports.VERB_RATE_LIMITS = exports.VERB_LIMITS = exports.VERB_ID_PATTERNS = exports.CANON_CARD_SCHEMA_ID = exports.CANON_VERB_NAMESPACE = exports.CANON_VERBS_SCHEMA_ID = exports.CANON_VERBS_SCHEMA_VERSION = void 0;
44
+ exports.CANON_VERB_LIMITS_ARTIFACT = exports.CREATE_GROUP_CREATOR_SETUP_REQUIRED_CODE = exports.CREATE_GROUP_NO_ADDABLE_MEMBERS_CODE = exports.VERB_NATIVE_METADATA_KEYS = exports.CANON_VERB_NAMES = exports.SELF_CONTEXT_TYPE = exports.VERB_RATE_LIMITS = exports.VERB_LIMITS = exports.VERB_ID_PATTERNS = exports.CANON_CARD_SCHEMA_ID = exports.CANON_VERB_NAMESPACE = exports.CANON_VERBS_SCHEMA_ID = exports.CANON_VERBS_SCHEMA_VERSION = void 0;
45
+ exports.normalizeVerbNativeMetadata = normalizeVerbNativeMetadata;
45
46
  exports.canonVerbToolName = canonVerbToolName;
46
47
  exports.findVerbByteLimitViolations = findVerbByteLimitViolations;
47
48
  /** Identifier for this contract document. */
@@ -72,6 +73,12 @@ exports.VERB_ID_PATTERNS = {
72
73
  actionId: '^[A-Za-z0-9_.:-]{1,80}$',
73
74
  questionId: '^[A-Za-z0-9_.:-]{1,120}$',
74
75
  sessionRuleToolPattern: '^[\\w.*:-]{1,128}$',
76
+ runtimeCorrelationValue: '^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$',
77
+ runtimeMethod: '^[A-Za-z0-9_][A-Za-z0-9_./:\\-]{0,255}$',
78
+ runtimeOptionValue: '^[A-Za-z0-9@_][A-Za-z0-9_.:/@+\\-]{0,255}$',
79
+ workspaceOptionId: '^[A-Za-z0-9@_][A-Za-z0-9_.:@+\\-]{0,255}$',
80
+ runtimeHandleKey: '^[A-Za-z0-9_.:-]{1,80}$',
81
+ runtimeControlId: '^[A-Za-z0-9_-]{1,80}$',
75
82
  };
76
83
  /**
77
84
  * Server-enforced limits, single-sourced. Each value cites its enforcement
@@ -139,6 +146,9 @@ exports.VERB_LIMITS = {
139
146
  nativeKeys: 24,
140
147
  nativeValueChars: 256,
141
148
  nativeHandles: 16,
149
+ /** Initial agent-session setup carried by send_to. */
150
+ sessionConfigValues: 24,
151
+ sessionConfigValueChars: 256,
142
152
  /** Deadlines (functions/src/utils/runtimeRequestHelpers.ts). */
143
153
  minTimeoutMs: 1000,
144
154
  /** input/card/plan ceiling (30 minutes). */
@@ -186,6 +196,65 @@ exports.CANON_VERB_NAMES = [
186
196
  'list_contact_requests',
187
197
  'list_conversations',
188
198
  ];
199
+ exports.VERB_NATIVE_METADATA_KEYS = [
200
+ 'runtime',
201
+ 'method',
202
+ 'requestId',
203
+ 'provider',
204
+ 'origin',
205
+ 'surface',
206
+ 'threadId',
207
+ 'turnId',
208
+ 'runId',
209
+ 'itemId',
210
+ 'toolCallId',
211
+ 'approvalId',
212
+ 'pluginId',
213
+ 'sessionKey',
214
+ 'nodeId',
215
+ 'handles',
216
+ ];
217
+ const VERB_NATIVE_STRING_KEYS = exports.VERB_NATIVE_METADATA_KEYS.filter((key) => key !== 'handles');
218
+ const RUNTIME_CORRELATION_VALUE_PATTERN = new RegExp(exports.VERB_ID_PATTERNS.runtimeCorrelationValue);
219
+ const RUNTIME_METHOD_PATTERN = new RegExp(exports.VERB_ID_PATTERNS.runtimeMethod);
220
+ const RUNTIME_HANDLE_KEY_PATTERN = new RegExp(exports.VERB_ID_PATTERNS.runtimeHandleKey);
221
+ function isPlainRecord(value) {
222
+ return Boolean(value && typeof value === 'object' && !Array.isArray(value));
223
+ }
224
+ /**
225
+ * Keep only the typed, content-free runtime correlation contract. Invalid or
226
+ * unknown fields are omitted on compatibility REST paths; canon.verb-wire.v1
227
+ * rejects the same fields through its strict JSON Schema.
228
+ */
229
+ function normalizeVerbNativeMetadata(value) {
230
+ if (!isPlainRecord(value))
231
+ return undefined;
232
+ const native = {};
233
+ for (const key of VERB_NATIVE_STRING_KEYS) {
234
+ const raw = value[key];
235
+ if (typeof raw !== 'string')
236
+ continue;
237
+ const normalized = raw.trim();
238
+ const pattern = key === 'method'
239
+ ? RUNTIME_METHOD_PATTERN
240
+ : RUNTIME_CORRELATION_VALUE_PATTERN;
241
+ if (pattern.test(normalized))
242
+ native[key] = normalized;
243
+ }
244
+ if (isPlainRecord(value.handles)) {
245
+ const handles = {};
246
+ for (const [key, raw] of Object.entries(value.handles).slice(0, exports.VERB_LIMITS.nativeHandles)) {
247
+ if (!RUNTIME_HANDLE_KEY_PATTERN.test(key) || typeof raw !== 'string')
248
+ continue;
249
+ const normalized = raw.trim();
250
+ if (RUNTIME_CORRELATION_VALUE_PATTERN.test(normalized))
251
+ handles[key] = normalized;
252
+ }
253
+ if (Object.keys(handles).length > 0)
254
+ native.handles = handles;
255
+ }
256
+ return Object.keys(native).length > 0 ? native : undefined;
257
+ }
189
258
  /**
190
259
  * Error code on the 400 a create_group receives when NO member is directly
191
260
  * addable (approval-required members can only be invited to an existing
@@ -29,7 +29,7 @@
29
29
  * endpoints validate against these schemas directly).
30
30
  */
31
31
  Object.defineProperty(exports, "__esModule", { value: true });
32
- exports.CANON_VERB_SCHEMA_REFS = exports.CANON_VERBS_JSON_SCHEMA = void 0;
32
+ exports.CANON_VERB_SCHEMA_REFS = exports.CANON_VERBS_JSON_SCHEMA = exports.VERB_SESSION_CONFIG_JSON_SCHEMA = exports.VERB_NATIVE_METADATA_JSON_SCHEMA = void 0;
33
33
  exports.getVerbInputSchema = getVerbInputSchema;
34
34
  exports.getVerbResultSchema = getVerbResultSchema;
35
35
  const verbContract_js_1 = require("./verbContract.js");
@@ -252,12 +252,89 @@ const runtimeCardDef = {
252
252
  blocks: { type: 'array', minItems: 1, maxItems: verbContract_js_1.VERB_LIMITS.cardServerBlocks },
253
253
  },
254
254
  };
255
- const nativeDef = {
255
+ const runtimeCorrelationValueDef = {
256
+ type: 'string',
257
+ pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeCorrelationValue,
258
+ maxLength: verbContract_js_1.VERB_LIMITS.nativeValueChars,
259
+ };
260
+ const runtimeMethodDef = {
261
+ type: 'string',
262
+ pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeMethod,
263
+ maxLength: verbContract_js_1.VERB_LIMITS.nativeValueChars,
264
+ };
265
+ exports.VERB_NATIVE_METADATA_JSON_SCHEMA = {
256
266
  type: 'object',
257
- description: `Runtime correlation handles (<= ${verbContract_js_1.VERB_LIMITS.nativeKeys} keys, string values <= `
258
- + `${verbContract_js_1.VERB_LIMITS.nativeValueChars} chars or a nested handles map <= ${verbContract_js_1.VERB_LIMITS.nativeHandles}; `
259
- + 'functions/src/api/interactionKinds.ts normalizeNative).',
260
- additionalProperties: true,
267
+ description: 'Content-free runtime correlation ids. Commands, paths, prompts, summaries, '
268
+ + 'and model labels are not permitted in this public envelope.',
269
+ maxProperties: verbContract_js_1.VERB_LIMITS.nativeKeys,
270
+ additionalProperties: false,
271
+ properties: {
272
+ runtime: runtimeCorrelationValueDef,
273
+ method: runtimeMethodDef,
274
+ requestId: runtimeCorrelationValueDef,
275
+ provider: runtimeCorrelationValueDef,
276
+ origin: runtimeCorrelationValueDef,
277
+ surface: runtimeCorrelationValueDef,
278
+ threadId: runtimeCorrelationValueDef,
279
+ turnId: runtimeCorrelationValueDef,
280
+ runId: runtimeCorrelationValueDef,
281
+ itemId: runtimeCorrelationValueDef,
282
+ toolCallId: runtimeCorrelationValueDef,
283
+ approvalId: runtimeCorrelationValueDef,
284
+ pluginId: runtimeCorrelationValueDef,
285
+ sessionKey: runtimeCorrelationValueDef,
286
+ nodeId: runtimeCorrelationValueDef,
287
+ handles: {
288
+ type: 'object',
289
+ maxProperties: verbContract_js_1.VERB_LIMITS.nativeHandles,
290
+ propertyNames: { pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeHandleKey },
291
+ additionalProperties: runtimeCorrelationValueDef,
292
+ },
293
+ },
294
+ };
295
+ const sessionConfigValueDef = {
296
+ type: 'string',
297
+ pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeOptionValue,
298
+ maxLength: verbContract_js_1.VERB_LIMITS.sessionConfigValueChars,
299
+ };
300
+ exports.VERB_SESSION_CONFIG_JSON_SCHEMA = {
301
+ type: 'object',
302
+ description: 'Typed setup policy for an agent target. Values are stable runtime-advertised '
303
+ + 'option ids and are validated against the target descriptor before session creation; '
304
+ + 'labels, prompts, workspace paths, and arbitrary fields are not permitted.',
305
+ additionalProperties: false,
306
+ properties: {
307
+ model: sessionConfigValueDef,
308
+ permissionMode: sessionConfigValueDef,
309
+ effort: sessionConfigValueDef,
310
+ workspaceId: {
311
+ type: 'string',
312
+ pattern: verbContract_js_1.VERB_ID_PATTERNS.workspaceOptionId,
313
+ maxLength: verbContract_js_1.VERB_LIMITS.sessionConfigValueChars,
314
+ },
315
+ executionMode: { enum: ['worktree', 'locked'] },
316
+ runtimeControlValues: {
317
+ type: 'object',
318
+ maxProperties: verbContract_js_1.VERB_LIMITS.sessionConfigValues,
319
+ propertyNames: {
320
+ pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeControlId,
321
+ not: {
322
+ enum: [
323
+ 'model',
324
+ 'workspace',
325
+ 'executionMode',
326
+ 'permissionMode',
327
+ 'effort',
328
+ 'interrupt',
329
+ 'runtimeControlValues',
330
+ 'updatedAt',
331
+ 'updatedBy',
332
+ ],
333
+ },
334
+ },
335
+ additionalProperties: sessionConfigValueDef,
336
+ },
337
+ },
261
338
  };
262
339
  const timeoutFields = (maxMs, ceilingNote) => ({
263
340
  timeoutMs: {
@@ -313,7 +390,7 @@ const send_to_input = {
313
390
  },
314
391
  sessionSelection: REF('sessionSelection'),
315
392
  sessionConfig: {
316
- type: ['object', 'null'],
393
+ oneOf: [REF('sessionConfig'), { type: 'null' }],
317
394
  description: 'Coding-agent session setup (model/permissionMode/effort/workspaceId/executionMode); '
318
395
  + 'only applied to agent targets, stripped for humans.',
319
396
  },
@@ -1005,7 +1082,8 @@ exports.CANON_VERBS_JSON_SCHEMA = {
1005
1082
  unifiedDiff: unifiedDiffDef,
1006
1083
  sessionRule: sessionRuleDef,
1007
1084
  runtimeCard: runtimeCardDef,
1008
- native: nativeDef,
1085
+ native: exports.VERB_NATIVE_METADATA_JSON_SCHEMA,
1086
+ sessionConfig: exports.VERB_SESSION_CONFIG_JSON_SCHEMA,
1009
1087
  send_to_input,
1010
1088
  send_to_result,
1011
1089
  request_input_input,
@@ -32,6 +32,7 @@ exports.projectVerbIntentToWire = projectVerbIntentToWire;
32
32
  exports.mergeVerbWireToIntent = mergeVerbWireToIntent;
33
33
  exports.findVerbWireEnvelopeViolations = findVerbWireEnvelopeViolations;
34
34
  const verbContract_js_1 = require("./verbContract.js");
35
+ const verbSchemas_js_1 = require("./verbSchemas.js");
35
36
  exports.CANON_VERB_WIRE_SCHEMA_VERSION = 'canon.verb-wire.v1';
36
37
  exports.CANON_VERB_WIRE_SCHEMA_ID = 'https://canonmsg.com/schemas/canon.verb-wire.v1.json';
37
38
  // ---------------------------------------------------------------------------
@@ -204,7 +205,9 @@ const wireEnvelopeDef = {
204
205
  },
205
206
  ],
206
207
  },
207
- sessionConfig: { type: ['object', 'null'] },
208
+ sessionConfig: {
209
+ oneOf: [verbSchemas_js_1.VERB_SESSION_CONFIG_JSON_SCHEMA, { type: 'null' }],
210
+ },
208
211
  idempotencyKey: {
209
212
  type: 'string',
210
213
  pattern: verbContract_js_1.VERB_ID_PATTERNS.runtimeId,
@@ -227,7 +230,7 @@ const wireEnvelopeDef = {
227
230
  + 'overload the mention slot.',
228
231
  },
229
232
  turn: { $ref: '#/$defs/turn' },
230
- native: { type: 'object' },
233
+ native: verbSchemas_js_1.VERB_NATIVE_METADATA_JSON_SCHEMA,
231
234
  runtimeId: { type: 'string', maxLength: verbContract_js_1.VERB_LIMITS.turnIdChars },
232
235
  limit: { type: 'integer', minimum: 1 },
233
236
  },