@contractspec/example.locale-jurisdiction-gate 3.7.6 → 3.7.10

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 (83) hide show
  1. package/.turbo/turbo-build.log +72 -51
  2. package/AGENTS.md +50 -27
  3. package/CHANGELOG.md +21 -0
  4. package/README.md +87 -42
  5. package/dist/browser/entities/index.js +2 -2
  6. package/dist/browser/entities/models.js +2 -2
  7. package/dist/browser/events.js +1 -1
  8. package/dist/browser/forms/assistant-context.form.js +213 -0
  9. package/dist/browser/forms/index.js +213 -0
  10. package/dist/browser/index.js +362 -40
  11. package/dist/browser/locale-jurisdiction-gate.feature.js +66 -1
  12. package/dist/browser/operations/assistant.js +3 -3
  13. package/dist/browser/operations/index.js +3 -3
  14. package/dist/browser/policy/assistant-gate.policy.js +62 -0
  15. package/dist/browser/policy/index.js +62 -1
  16. package/dist/browser/translations/assistant-gate.en-GB.translation.js +48 -0
  17. package/dist/browser/translations/assistant-gate.en-US.translation.js +50 -0
  18. package/dist/browser/translations/assistant-gate.fr-FR.translation.js +52 -0
  19. package/dist/browser/translations/index.js +148 -0
  20. package/dist/contracts.test.d.ts +1 -0
  21. package/dist/entities/index.js +2 -2
  22. package/dist/entities/models.js +2 -2
  23. package/dist/events.js +1 -1
  24. package/dist/forms/assistant-context.form.d.ts +22 -0
  25. package/dist/forms/assistant-context.form.js +214 -0
  26. package/dist/forms/index.d.ts +1 -0
  27. package/dist/forms/index.js +214 -0
  28. package/dist/index.d.ts +5 -3
  29. package/dist/index.js +362 -40
  30. package/dist/locale-jurisdiction-gate.feature.js +66 -1
  31. package/dist/node/entities/index.js +2 -2
  32. package/dist/node/entities/models.js +2 -2
  33. package/dist/node/events.js +1 -1
  34. package/dist/node/forms/assistant-context.form.js +213 -0
  35. package/dist/node/forms/index.js +213 -0
  36. package/dist/node/index.js +362 -40
  37. package/dist/node/locale-jurisdiction-gate.feature.js +66 -1
  38. package/dist/node/operations/assistant.js +3 -3
  39. package/dist/node/operations/index.js +3 -3
  40. package/dist/node/policy/assistant-gate.policy.js +62 -0
  41. package/dist/node/policy/index.js +62 -1
  42. package/dist/node/translations/assistant-gate.en-GB.translation.js +48 -0
  43. package/dist/node/translations/assistant-gate.en-US.translation.js +50 -0
  44. package/dist/node/translations/assistant-gate.fr-FR.translation.js +52 -0
  45. package/dist/node/translations/index.js +148 -0
  46. package/dist/operations/assistant.js +3 -3
  47. package/dist/operations/index.js +3 -3
  48. package/dist/policy/assistant-gate.policy.d.ts +1 -0
  49. package/dist/policy/assistant-gate.policy.js +63 -0
  50. package/dist/policy/index.d.ts +2 -1
  51. package/dist/policy/index.js +62 -1
  52. package/dist/translations/assistant-gate.en-GB.translation.d.ts +1 -0
  53. package/dist/translations/assistant-gate.en-GB.translation.js +49 -0
  54. package/dist/translations/assistant-gate.en-US.translation.d.ts +1 -0
  55. package/dist/translations/assistant-gate.en-US.translation.js +51 -0
  56. package/dist/translations/assistant-gate.fr-FR.translation.d.ts +1 -0
  57. package/dist/translations/assistant-gate.fr-FR.translation.js +53 -0
  58. package/dist/translations/index.d.ts +3 -0
  59. package/dist/translations/index.js +149 -0
  60. package/package.json +105 -7
  61. package/src/contracts.test.ts +32 -0
  62. package/src/docs/locale-jurisdiction-gate.docblock.ts +21 -21
  63. package/src/entities/models.ts +87 -87
  64. package/src/events.ts +55 -55
  65. package/src/example.ts +28 -28
  66. package/src/forms/assistant-context.form.ts +112 -0
  67. package/src/forms/index.ts +1 -0
  68. package/src/handlers/demo.handlers.test.ts +46 -46
  69. package/src/handlers/demo.handlers.ts +133 -133
  70. package/src/index.ts +5 -3
  71. package/src/locale-jurisdiction-gate.feature.ts +40 -34
  72. package/src/operations/assistant.ts +82 -82
  73. package/src/policy/assistant-gate.policy.ts +65 -0
  74. package/src/policy/guard.test.ts +18 -18
  75. package/src/policy/guard.ts +75 -75
  76. package/src/policy/index.ts +2 -1
  77. package/src/policy/types.ts +12 -12
  78. package/src/translations/assistant-gate.en-GB.translation.ts +46 -0
  79. package/src/translations/assistant-gate.en-US.translation.ts +48 -0
  80. package/src/translations/assistant-gate.fr-FR.translation.ts +51 -0
  81. package/src/translations/index.ts +3 -0
  82. package/tsconfig.json +7 -15
  83. package/tsdown.config.js +7 -13
@@ -0,0 +1,213 @@
1
+ // src/entities/models.ts
2
+ import {
3
+ defineEnum,
4
+ defineSchemaModel,
5
+ ScalarTypeEnum
6
+ } from "@contractspec/lib.schema";
7
+ var AllowedScopeEnum = defineEnum("AllowedScope", [
8
+ "education_only",
9
+ "generic_info",
10
+ "escalation_required"
11
+ ]);
12
+ var UserProfileModel = defineSchemaModel({
13
+ name: "UserProfile",
14
+ description: "User profile inputs used to derive regulatory context.",
15
+ fields: {
16
+ preferredLocale: {
17
+ type: ScalarTypeEnum.String_unsecure(),
18
+ isOptional: true
19
+ },
20
+ residencyCountry: {
21
+ type: ScalarTypeEnum.String_unsecure(),
22
+ isOptional: true
23
+ },
24
+ taxResidenceCountry: {
25
+ type: ScalarTypeEnum.String_unsecure(),
26
+ isOptional: true
27
+ },
28
+ clientType: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
29
+ }
30
+ });
31
+ var RegulatoryContextModel = defineSchemaModel({
32
+ name: "RegulatoryContext",
33
+ description: "Explicit regulatory context (no guessing).",
34
+ fields: {
35
+ jurisdiction: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
36
+ region: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
37
+ clientType: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
38
+ allowedScope: { type: AllowedScopeEnum, isOptional: false }
39
+ }
40
+ });
41
+ var LLMCallEnvelopeModel = defineSchemaModel({
42
+ name: "LLMCallEnvelope",
43
+ description: "Mandatory envelope for assistant calls. All fields are explicit and required for policy gating.",
44
+ fields: {
45
+ traceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
46
+ locale: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
47
+ regulatoryContext: { type: RegulatoryContextModel, isOptional: false },
48
+ kbSnapshotId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
49
+ allowedScope: { type: AllowedScopeEnum, isOptional: false }
50
+ }
51
+ });
52
+ var AssistantCitationModel = defineSchemaModel({
53
+ name: "AssistantCitation",
54
+ description: "Citation referencing a KB snapshot + a specific item within it.",
55
+ fields: {
56
+ kbSnapshotId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
57
+ sourceType: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
58
+ sourceId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
59
+ title: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
60
+ excerpt: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
61
+ }
62
+ });
63
+ var AssistantAnswerSectionModel = defineSchemaModel({
64
+ name: "AssistantAnswerSection",
65
+ description: "Structured answer section.",
66
+ fields: {
67
+ heading: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
68
+ body: { type: ScalarTypeEnum.String_unsecure(), isOptional: false }
69
+ }
70
+ });
71
+ var AssistantAnswerIRModel = defineSchemaModel({
72
+ name: "AssistantAnswerIR",
73
+ description: "Structured assistant answer with mandatory citations and explicit locale/jurisdiction.",
74
+ fields: {
75
+ locale: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
76
+ jurisdiction: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
77
+ allowedScope: { type: AllowedScopeEnum, isOptional: false },
78
+ sections: {
79
+ type: AssistantAnswerSectionModel,
80
+ isArray: true,
81
+ isOptional: false
82
+ },
83
+ citations: {
84
+ type: AssistantCitationModel,
85
+ isArray: true,
86
+ isOptional: false
87
+ },
88
+ disclaimers: {
89
+ type: ScalarTypeEnum.String_unsecure(),
90
+ isArray: true,
91
+ isOptional: true
92
+ },
93
+ riskFlags: {
94
+ type: ScalarTypeEnum.String_unsecure(),
95
+ isArray: true,
96
+ isOptional: true
97
+ },
98
+ refused: { type: ScalarTypeEnum.Boolean(), isOptional: true },
99
+ refusalReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: true }
100
+ }
101
+ });
102
+
103
+ // src/forms/assistant-context.form.ts
104
+ import { defineFormSpec } from "@contractspec/lib.contracts-spec/forms";
105
+ import {
106
+ OwnersEnum,
107
+ StabilityEnum,
108
+ TagsEnum
109
+ } from "@contractspec/lib.contracts-spec/ownership";
110
+ import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
111
+ var AssistantContextFormModel = defineSchemaModel2({
112
+ name: "AssistantContextFormModel",
113
+ description: "Form values required before a policy-gated assistant request can be executed.",
114
+ fields: {
115
+ locale: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
116
+ jurisdiction: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
117
+ kbSnapshotId: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false },
118
+ allowedScope: { type: AllowedScopeEnum, isOptional: false },
119
+ question: { type: ScalarTypeEnum2.String_unsecure(), isOptional: false }
120
+ }
121
+ });
122
+ var AssistantContextForm = defineFormSpec({
123
+ meta: {
124
+ key: "locale-jurisdiction-gate.form.assistant-context",
125
+ version: "1.0.0",
126
+ title: "Assistant Context Gate",
127
+ description: "Collects the explicit locale, jurisdiction, scope, and knowledge snapshot required by the assistant gate.",
128
+ domain: "assistant",
129
+ owners: [OwnersEnum.PlatformFinance],
130
+ tags: [TagsEnum.I18n, "assistant", "form", "policy"],
131
+ stability: StabilityEnum.Experimental
132
+ },
133
+ model: AssistantContextFormModel,
134
+ fields: [
135
+ {
136
+ kind: "select",
137
+ name: "locale",
138
+ labelI18n: "assistantGate.locale.label",
139
+ descriptionI18n: "assistantGate.locale.description",
140
+ options: {
141
+ kind: "static",
142
+ options: [
143
+ { labelI18n: "assistantGate.locale.enUs", value: "en-US" },
144
+ { labelI18n: "assistantGate.locale.enGb", value: "en-GB" },
145
+ { labelI18n: "assistantGate.locale.frFr", value: "fr-FR" }
146
+ ]
147
+ },
148
+ required: true
149
+ },
150
+ {
151
+ kind: "text",
152
+ name: "jurisdiction",
153
+ labelI18n: "assistantGate.jurisdiction.label",
154
+ placeholderI18n: "assistantGate.jurisdiction.placeholder",
155
+ required: true
156
+ },
157
+ {
158
+ kind: "text",
159
+ name: "kbSnapshotId",
160
+ labelI18n: "assistantGate.kbSnapshotId.label",
161
+ placeholderI18n: "assistantGate.kbSnapshotId.placeholder",
162
+ required: true
163
+ },
164
+ {
165
+ kind: "radio",
166
+ name: "allowedScope",
167
+ labelI18n: "assistantGate.allowedScope.label",
168
+ options: {
169
+ kind: "static",
170
+ options: [
171
+ {
172
+ labelI18n: "assistantGate.allowedScope.educationOnly",
173
+ value: "education_only"
174
+ },
175
+ {
176
+ labelI18n: "assistantGate.allowedScope.genericInfo",
177
+ value: "generic_info"
178
+ },
179
+ {
180
+ labelI18n: "assistantGate.allowedScope.escalationRequired",
181
+ value: "escalation_required"
182
+ }
183
+ ]
184
+ },
185
+ required: true
186
+ },
187
+ {
188
+ kind: "textarea",
189
+ name: "question",
190
+ labelI18n: "assistantGate.question.label",
191
+ placeholderI18n: "assistantGate.question.placeholder",
192
+ required: true
193
+ }
194
+ ],
195
+ actions: [
196
+ {
197
+ key: "submit",
198
+ labelI18n: "assistantGate.submit.label",
199
+ op: { name: "assistant.answer", version: "1.0.0" }
200
+ }
201
+ ],
202
+ policy: {
203
+ flags: [],
204
+ pii: ["kbSnapshotId", "question"]
205
+ },
206
+ renderHints: {
207
+ ui: "custom",
208
+ form: "react-hook-form"
209
+ }
210
+ });
211
+ export {
212
+ AssistantContextForm
213
+ };
@@ -43,9 +43,9 @@ var docBlocks = [
43
43
  registerDocBlocks(docBlocks);
44
44
  // src/entities/models.ts
45
45
  import {
46
- ScalarTypeEnum,
47
46
  defineEnum,
48
- defineSchemaModel
47
+ defineSchemaModel,
48
+ ScalarTypeEnum
49
49
  } from "@contractspec/lib.schema";
50
50
  var AllowedScopeEnum = defineEnum("AllowedScope", [
51
51
  "education_only",
@@ -144,7 +144,7 @@ var AssistantAnswerIRModel = defineSchemaModel({
144
144
  });
145
145
  // src/events.ts
146
146
  import { defineEvent } from "@contractspec/lib.contracts-spec";
147
- import { ScalarTypeEnum as ScalarTypeEnum2, defineSchemaModel as defineSchemaModel2 } from "@contractspec/lib.schema";
147
+ import { defineSchemaModel as defineSchemaModel2, ScalarTypeEnum as ScalarTypeEnum2 } from "@contractspec/lib.schema";
148
148
  var AssistantAnswerRequestedPayload = defineSchemaModel2({
149
149
  name: "AssistantAnswerRequestedPayload",
150
150
  description: "Emitted when an assistant answer is requested (pre-gate).",
@@ -244,6 +244,114 @@ var example = defineExample({
244
244
  });
245
245
  var example_default = example;
246
246
 
247
+ // src/forms/assistant-context.form.ts
248
+ import { defineFormSpec } from "@contractspec/lib.contracts-spec/forms";
249
+ import {
250
+ OwnersEnum,
251
+ StabilityEnum,
252
+ TagsEnum
253
+ } from "@contractspec/lib.contracts-spec/ownership";
254
+ import { defineSchemaModel as defineSchemaModel3, ScalarTypeEnum as ScalarTypeEnum3 } from "@contractspec/lib.schema";
255
+ var AssistantContextFormModel = defineSchemaModel3({
256
+ name: "AssistantContextFormModel",
257
+ description: "Form values required before a policy-gated assistant request can be executed.",
258
+ fields: {
259
+ locale: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
260
+ jurisdiction: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
261
+ kbSnapshotId: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false },
262
+ allowedScope: { type: AllowedScopeEnum, isOptional: false },
263
+ question: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
264
+ }
265
+ });
266
+ var AssistantContextForm = defineFormSpec({
267
+ meta: {
268
+ key: "locale-jurisdiction-gate.form.assistant-context",
269
+ version: "1.0.0",
270
+ title: "Assistant Context Gate",
271
+ description: "Collects the explicit locale, jurisdiction, scope, and knowledge snapshot required by the assistant gate.",
272
+ domain: "assistant",
273
+ owners: [OwnersEnum.PlatformFinance],
274
+ tags: [TagsEnum.I18n, "assistant", "form", "policy"],
275
+ stability: StabilityEnum.Experimental
276
+ },
277
+ model: AssistantContextFormModel,
278
+ fields: [
279
+ {
280
+ kind: "select",
281
+ name: "locale",
282
+ labelI18n: "assistantGate.locale.label",
283
+ descriptionI18n: "assistantGate.locale.description",
284
+ options: {
285
+ kind: "static",
286
+ options: [
287
+ { labelI18n: "assistantGate.locale.enUs", value: "en-US" },
288
+ { labelI18n: "assistantGate.locale.enGb", value: "en-GB" },
289
+ { labelI18n: "assistantGate.locale.frFr", value: "fr-FR" }
290
+ ]
291
+ },
292
+ required: true
293
+ },
294
+ {
295
+ kind: "text",
296
+ name: "jurisdiction",
297
+ labelI18n: "assistantGate.jurisdiction.label",
298
+ placeholderI18n: "assistantGate.jurisdiction.placeholder",
299
+ required: true
300
+ },
301
+ {
302
+ kind: "text",
303
+ name: "kbSnapshotId",
304
+ labelI18n: "assistantGate.kbSnapshotId.label",
305
+ placeholderI18n: "assistantGate.kbSnapshotId.placeholder",
306
+ required: true
307
+ },
308
+ {
309
+ kind: "radio",
310
+ name: "allowedScope",
311
+ labelI18n: "assistantGate.allowedScope.label",
312
+ options: {
313
+ kind: "static",
314
+ options: [
315
+ {
316
+ labelI18n: "assistantGate.allowedScope.educationOnly",
317
+ value: "education_only"
318
+ },
319
+ {
320
+ labelI18n: "assistantGate.allowedScope.genericInfo",
321
+ value: "generic_info"
322
+ },
323
+ {
324
+ labelI18n: "assistantGate.allowedScope.escalationRequired",
325
+ value: "escalation_required"
326
+ }
327
+ ]
328
+ },
329
+ required: true
330
+ },
331
+ {
332
+ kind: "textarea",
333
+ name: "question",
334
+ labelI18n: "assistantGate.question.label",
335
+ placeholderI18n: "assistantGate.question.placeholder",
336
+ required: true
337
+ }
338
+ ],
339
+ actions: [
340
+ {
341
+ key: "submit",
342
+ labelI18n: "assistantGate.submit.label",
343
+ op: { name: "assistant.answer", version: "1.0.0" }
344
+ }
345
+ ],
346
+ policy: {
347
+ flags: [],
348
+ pii: ["kbSnapshotId", "question"]
349
+ },
350
+ renderHints: {
351
+ ui: "custom",
352
+ form: "react-hook-form"
353
+ }
354
+ });
247
355
  // src/policy/guard.ts
248
356
  var SUPPORTED_LOCALES = new Set(["en-US", "en-GB", "fr-FR"]);
249
357
  function err(code, message) {
@@ -393,23 +501,126 @@ function createDemoAssistantHandlers() {
393
501
  }
394
502
  return { answer, explainConcept };
395
503
  }
504
+ // src/policy/assistant-gate.policy.ts
505
+ import {
506
+ OwnersEnum as OwnersEnum2,
507
+ StabilityEnum as StabilityEnum2,
508
+ TagsEnum as TagsEnum2
509
+ } from "@contractspec/lib.contracts-spec/ownership";
510
+ import { definePolicy } from "@contractspec/lib.contracts-spec/policy";
511
+ var AssistantGatePolicy = definePolicy({
512
+ meta: {
513
+ key: "locale-jurisdiction-gate.policy.gate",
514
+ version: "1.0.0",
515
+ title: "Assistant Locale and Jurisdiction Gate",
516
+ description: "Requires explicit locale, jurisdiction, knowledge snapshot, and allowed scope before assistant requests may proceed.",
517
+ domain: "assistant",
518
+ scope: "operation",
519
+ owners: [OwnersEnum2.PlatformFinance],
520
+ tags: [TagsEnum2.I18n, "assistant", "policy", "jurisdiction"],
521
+ stability: StabilityEnum2.Experimental
522
+ },
523
+ rules: [
524
+ {
525
+ effect: "deny",
526
+ actions: ["assistant.answer", "assistant.explainConcept"],
527
+ resource: { type: "assistant-call" },
528
+ conditions: [
529
+ {
530
+ expression: "!context.locale || !context.jurisdiction || !context.kbSnapshotId || !context.allowedScope"
531
+ }
532
+ ],
533
+ reason: "Assistant requests fail closed until locale, jurisdiction, kbSnapshotId, and allowedScope are explicit."
534
+ },
535
+ {
536
+ effect: "deny",
537
+ actions: ["assistant.answer", "assistant.explainConcept"],
538
+ resource: { type: "assistant-call" },
539
+ conditions: [
540
+ {
541
+ expression: "!['en-US', 'en-GB', 'fr-FR'].includes(context.locale ?? '')"
542
+ }
543
+ ],
544
+ reason: "Only the explicitly reviewed assistant locales are permitted."
545
+ },
546
+ {
547
+ effect: "allow",
548
+ actions: ["assistant.answer", "assistant.explainConcept"],
549
+ resource: { type: "assistant-call" },
550
+ conditions: [
551
+ {
552
+ expression: "['en-US', 'en-GB', 'fr-FR'].includes(context.locale ?? '') && !!context.jurisdiction && !!context.kbSnapshotId && !!context.allowedScope"
553
+ }
554
+ ],
555
+ reason: "Explicit context is present, so the request may continue to citation and scope validation."
556
+ }
557
+ ],
558
+ pii: {
559
+ fields: ["kbSnapshotId"],
560
+ retentionDays: 30
561
+ }
562
+ });
563
+
564
+ // src/locale-jurisdiction-gate.feature.ts
565
+ import { defineFeature } from "@contractspec/lib.contracts-spec";
566
+ var LocaleJurisdictionGateFeature = defineFeature({
567
+ meta: {
568
+ key: "locale-jurisdiction-gate",
569
+ version: "1.0.0",
570
+ title: "Locale + Jurisdiction Gate",
571
+ description: "Fail-closed gating for assistant calls requiring locale/jurisdiction/snapshot/scope and citations.",
572
+ domain: "knowledge",
573
+ owners: ["@examples"],
574
+ tags: ["assistant", "policy", "locale", "jurisdiction", "knowledge"],
575
+ stability: "experimental"
576
+ },
577
+ operations: [
578
+ { key: "assistant.answer", version: "1.0.0" },
579
+ { key: "assistant.explainConcept", version: "1.0.0" }
580
+ ],
581
+ events: [
582
+ { key: "assistant.answer.requested", version: "1.0.0" },
583
+ { key: "assistant.answer.blocked", version: "1.0.0" },
584
+ { key: "assistant.answer.delivered", version: "1.0.0" }
585
+ ],
586
+ presentations: [],
587
+ opToPresentation: [],
588
+ presentationsTargets: [],
589
+ capabilities: {
590
+ requires: [{ key: "knowledge", version: "1.0.0" }]
591
+ },
592
+ policies: [
593
+ {
594
+ key: AssistantGatePolicy.meta.key,
595
+ version: AssistantGatePolicy.meta.version
596
+ }
597
+ ],
598
+ knowledge: [
599
+ { key: "locale-jurisdiction-gate.knowledge.rules", version: "1.0.0" }
600
+ ],
601
+ docs: [
602
+ "docs.examples.locale-jurisdiction-gate.goal",
603
+ "docs.examples.locale-jurisdiction-gate.reference"
604
+ ]
605
+ });
606
+
396
607
  // src/operations/assistant.ts
397
608
  import { defineCommand } from "@contractspec/lib.contracts-spec";
398
- import { ScalarTypeEnum as ScalarTypeEnum3, defineSchemaModel as defineSchemaModel3 } from "@contractspec/lib.schema";
399
- var AssistantQuestionInput = defineSchemaModel3({
609
+ import { defineSchemaModel as defineSchemaModel4, ScalarTypeEnum as ScalarTypeEnum4 } from "@contractspec/lib.schema";
610
+ var AssistantQuestionInput = defineSchemaModel4({
400
611
  name: "AssistantQuestionInput",
401
612
  description: "Input for assistant calls with mandatory envelope.",
402
613
  fields: {
403
614
  envelope: { type: LLMCallEnvelopeModel, isOptional: false },
404
- question: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
615
+ question: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false }
405
616
  }
406
617
  });
407
- var AssistantConceptInput = defineSchemaModel3({
618
+ var AssistantConceptInput = defineSchemaModel4({
408
619
  name: "AssistantConceptInput",
409
620
  description: "Input for explaining a concept with mandatory envelope.",
410
621
  fields: {
411
622
  envelope: { type: LLMCallEnvelopeModel, isOptional: false },
412
- conceptKey: { type: ScalarTypeEnum3.String_unsecure(), isOptional: false }
623
+ conceptKey: { type: ScalarTypeEnum4.String_unsecure(), isOptional: false }
413
624
  }
414
625
  });
415
626
  var AssistantAnswerContract = defineCommand({
@@ -479,42 +690,148 @@ var AssistantExplainConceptContract = defineCommand({
479
690
  },
480
691
  policy: { auth: "user" }
481
692
  });
482
- // src/locale-jurisdiction-gate.feature.ts
483
- import { defineFeature } from "@contractspec/lib.contracts-spec";
484
- var LocaleJurisdictionGateFeature = defineFeature({
693
+ // src/translations/assistant-gate.en-GB.translation.ts
694
+ import {
695
+ OwnersEnum as OwnersEnum3,
696
+ StabilityEnum as StabilityEnum3,
697
+ TagsEnum as TagsEnum3
698
+ } from "@contractspec/lib.contracts-spec/ownership";
699
+ import { defineTranslation } from "@contractspec/lib.contracts-spec/translations/spec";
700
+ var AssistantGateMessagesEnGb = defineTranslation({
485
701
  meta: {
486
- key: "locale-jurisdiction-gate",
702
+ key: "locale-jurisdiction-gate.translation.assistant-gate.en-GB",
487
703
  version: "1.0.0",
488
- title: "Locale + Jurisdiction Gate",
489
- description: "Fail-closed gating for assistant calls requiring locale/jurisdiction/snapshot/scope and citations.",
490
- domain: "knowledge",
491
- owners: ["@examples"],
492
- tags: ["assistant", "policy", "locale", "jurisdiction", "knowledge"],
493
- stability: "experimental"
704
+ domain: "assistant",
705
+ description: "British English messages for the assistant locale and jurisdiction gate.",
706
+ owners: [OwnersEnum3.PlatformFinance],
707
+ stability: StabilityEnum3.Experimental,
708
+ tags: [TagsEnum3.I18n, "assistant", "policy"]
494
709
  },
495
- operations: [
496
- { key: "assistant.answer", version: "1.0.0" },
497
- { key: "assistant.explainConcept", version: "1.0.0" }
498
- ],
499
- events: [
500
- { key: "assistant.answer.requested", version: "1.0.0" },
501
- { key: "assistant.answer.blocked", version: "1.0.0" },
502
- { key: "assistant.answer.delivered", version: "1.0.0" }
503
- ],
504
- presentations: [],
505
- opToPresentation: [],
506
- presentationsTargets: [],
507
- capabilities: {
508
- requires: [{ key: "knowledge", version: "1.0.0" }]
710
+ locale: "en-GB",
711
+ fallback: "en-US",
712
+ messages: {
713
+ "assistantGate.locale.label": { value: "Locale" },
714
+ "assistantGate.locale.description": {
715
+ value: "Select the reviewed locale for the assistant response."
716
+ },
717
+ "assistantGate.jurisdiction.label": { value: "Jurisdiction" },
718
+ "assistantGate.jurisdiction.placeholder": { value: "UK-FCA" },
719
+ "assistantGate.kbSnapshotId.label": { value: "Knowledge snapshot ID" },
720
+ "assistantGate.kbSnapshotId.placeholder": {
721
+ value: "kb_2026_03_20_policy_reviewed"
722
+ },
723
+ "assistantGate.allowedScope.label": { value: "Permitted scope" },
724
+ "assistantGate.allowedScope.educationOnly": {
725
+ value: "Educational content only"
726
+ },
727
+ "assistantGate.allowedScope.genericInfo": { value: "General information" },
728
+ "assistantGate.allowedScope.escalationRequired": {
729
+ value: "Escalation required"
730
+ },
731
+ "assistantGate.question.label": { value: "Question" },
732
+ "assistantGate.question.placeholder": {
733
+ value: "What may I say about this product in the selected jurisdiction?"
734
+ },
735
+ "assistantGate.submit.label": { value: "Generate response" }
736
+ }
737
+ });
738
+
739
+ // src/translations/assistant-gate.en-US.translation.ts
740
+ import {
741
+ OwnersEnum as OwnersEnum4,
742
+ StabilityEnum as StabilityEnum4,
743
+ TagsEnum as TagsEnum4
744
+ } from "@contractspec/lib.contracts-spec/ownership";
745
+ import { defineTranslation as defineTranslation2 } from "@contractspec/lib.contracts-spec/translations/spec";
746
+ var AssistantGateMessagesEnUs = defineTranslation2({
747
+ meta: {
748
+ key: "locale-jurisdiction-gate.translation.assistant-gate.en-US",
749
+ version: "1.0.0",
750
+ domain: "assistant",
751
+ description: "US English messages for the assistant locale and jurisdiction gate.",
752
+ owners: [OwnersEnum4.PlatformFinance],
753
+ stability: StabilityEnum4.Experimental,
754
+ tags: [TagsEnum4.I18n, "assistant", "policy"]
509
755
  },
510
- policies: [{ key: "locale-jurisdiction-gate.policy.gate", version: "1.0.0" }],
511
- knowledge: [
512
- { key: "locale-jurisdiction-gate.knowledge.rules", version: "1.0.0" }
513
- ],
514
- docs: [
515
- "docs.examples.locale-jurisdiction-gate.goal",
516
- "docs.examples.locale-jurisdiction-gate.reference"
517
- ]
756
+ locale: "en-US",
757
+ messages: {
758
+ "assistantGate.locale.label": { value: "Locale" },
759
+ "assistantGate.locale.description": {
760
+ value: "Choose the reviewed locale for the assistant answer."
761
+ },
762
+ "assistantGate.locale.enUs": { value: "English (United States)" },
763
+ "assistantGate.locale.enGb": { value: "English (United Kingdom)" },
764
+ "assistantGate.locale.frFr": { value: "French (France)" },
765
+ "assistantGate.jurisdiction.label": { value: "Jurisdiction" },
766
+ "assistantGate.jurisdiction.placeholder": { value: "US-SEC" },
767
+ "assistantGate.kbSnapshotId.label": { value: "Knowledge snapshot ID" },
768
+ "assistantGate.kbSnapshotId.placeholder": {
769
+ value: "kb_2026_03_20_policy_reviewed"
770
+ },
771
+ "assistantGate.allowedScope.label": { value: "Allowed scope" },
772
+ "assistantGate.allowedScope.educationOnly": {
773
+ value: "Educational content only"
774
+ },
775
+ "assistantGate.allowedScope.genericInfo": { value: "Generic information" },
776
+ "assistantGate.allowedScope.escalationRequired": {
777
+ value: "Escalation required"
778
+ },
779
+ "assistantGate.question.label": { value: "Question" },
780
+ "assistantGate.question.placeholder": {
781
+ value: "What can I say about this product in the selected jurisdiction?"
782
+ },
783
+ "assistantGate.submit.label": { value: "Generate answer" }
784
+ }
785
+ });
786
+
787
+ // src/translations/assistant-gate.fr-FR.translation.ts
788
+ import {
789
+ OwnersEnum as OwnersEnum5,
790
+ StabilityEnum as StabilityEnum5,
791
+ TagsEnum as TagsEnum5
792
+ } from "@contractspec/lib.contracts-spec/ownership";
793
+ import { defineTranslation as defineTranslation3 } from "@contractspec/lib.contracts-spec/translations/spec";
794
+ var AssistantGateMessagesFrFr = defineTranslation3({
795
+ meta: {
796
+ key: "locale-jurisdiction-gate.translation.assistant-gate.fr-FR",
797
+ version: "1.0.0",
798
+ domain: "assistant",
799
+ description: "French messages for the assistant locale and jurisdiction gate.",
800
+ owners: [OwnersEnum5.PlatformFinance],
801
+ stability: StabilityEnum5.Experimental,
802
+ tags: [TagsEnum5.I18n, "assistant", "policy"]
803
+ },
804
+ locale: "fr-FR",
805
+ fallback: "en-US",
806
+ messages: {
807
+ "assistantGate.locale.label": { value: "Langue" },
808
+ "assistantGate.locale.description": {
809
+ value: "Sélectionnez la langue validée pour la réponse de l'assistant."
810
+ },
811
+ "assistantGate.jurisdiction.label": { value: "Juridiction" },
812
+ "assistantGate.jurisdiction.placeholder": { value: "FR-AMF" },
813
+ "assistantGate.kbSnapshotId.label": {
814
+ value: "Identifiant du snapshot documentaire"
815
+ },
816
+ "assistantGate.kbSnapshotId.placeholder": {
817
+ value: "kb_2026_03_20_policy_reviewed"
818
+ },
819
+ "assistantGate.allowedScope.label": { value: "Périmètre autorisé" },
820
+ "assistantGate.allowedScope.educationOnly": {
821
+ value: "Contenu éducatif uniquement"
822
+ },
823
+ "assistantGate.allowedScope.genericInfo": {
824
+ value: "Information générale"
825
+ },
826
+ "assistantGate.allowedScope.escalationRequired": {
827
+ value: "Escalade obligatoire"
828
+ },
829
+ "assistantGate.question.label": { value: "Question" },
830
+ "assistantGate.question.placeholder": {
831
+ value: "Que puis-je dire sur ce produit dans la juridiction sélectionnée ?"
832
+ },
833
+ "assistantGate.submit.label": { value: "Générer la réponse" }
834
+ }
518
835
  });
519
836
  export {
520
837
  validateEnvelope,
@@ -526,7 +843,12 @@ export {
526
843
  RegulatoryContextModel,
527
844
  LocaleJurisdictionGateFeature,
528
845
  LLMCallEnvelopeModel,
846
+ AssistantGatePolicy,
847
+ AssistantGateMessagesFrFr,
848
+ AssistantGateMessagesEnUs,
849
+ AssistantGateMessagesEnGb,
529
850
  AssistantExplainConceptContract,
851
+ AssistantContextForm,
530
852
  AssistantCitationModel,
531
853
  AssistantAnswerSectionModel,
532
854
  AssistantAnswerRequestedEvent,