@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,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
+ };
@@ -0,0 +1 @@
1
+ export * from './assistant-context.form';
@@ -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
@@ -5,10 +5,12 @@
5
5
  * allowedScope must be explicit, and answers must cite a KB snapshot.
6
6
  */
7
7
  export * from './entities';
8
- export * from './operations';
9
8
  export * from './events';
10
- export * from './policy';
9
+ export { default as example } from './example';
10
+ export * from './forms';
11
11
  export * from './handlers';
12
12
  export * from './locale-jurisdiction-gate.feature';
13
- export { default as example } from './example';
13
+ export * from './operations';
14
+ export * from './policy';
15
+ export * from './translations';
14
16
  import './docs';