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