@lssm/example.locale-jurisdiction-gate 0.0.0-canary-20251220002821 → 0.0.0-canary-20251220021406

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.
@@ -9,7 +9,7 @@ $ tsdown
9
9
  ℹ dist/entities/models.js  3.55 kB │ gzip: 0.82 kB
10
10
  ℹ dist/contracts/assistant.js  3.18 kB │ gzip: 1.05 kB
11
11
  ℹ dist/events.js  2.57 kB │ gzip: 0.58 kB
12
- ℹ dist/handlers/demo.handlers.js  2.41 kB │ gzip: 0.90 kB
12
+ ℹ dist/handlers/demo.handlers.js  2.46 kB │ gzip: 0.90 kB
13
13
  ℹ dist/policy/guard.js  1.90 kB │ gzip: 0.76 kB
14
14
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js  1.69 kB │ gzip: 0.76 kB
15
15
  ℹ dist/index.js  1.27 kB │ gzip: 0.40 kB
@@ -46,9 +46,9 @@ $ tsdown
46
46
  ℹ dist/libs/contracts/dist/knowledge/contracts.js  6.68 kB │ gzip: 1.33 kB
47
47
  ℹ dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js.map  6.33 kB │ gzip: 2.84 kB
48
48
  ℹ dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js.map  6.17 kB │ gzip: 2.52 kB
49
+ ℹ dist/handlers/demo.handlers.js.map  5.97 kB │ gzip: 1.81 kB
49
50
  ℹ dist/entities/models.js.map  5.92 kB │ gzip: 1.22 kB
50
51
  ℹ dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js  5.90 kB │ gzip: 2.68 kB
51
- ℹ dist/handlers/demo.handlers.js.map  5.78 kB │ gzip: 1.76 kB
52
52
  ℹ dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js  5.71 kB │ gzip: 2.36 kB
53
53
  ℹ dist/libs/contracts/dist/integrations/openbanking/contracts/accounts.js  5.63 kB │ gzip: 1.50 kB
54
54
  ℹ dist/libs/contracts/dist/docs/tech/telemetry-ingest.docblock.js.map  5.10 kB │ gzip: 1.98 kB
@@ -127,7 +127,7 @@ $ tsdown
127
127
  ℹ dist/libs/contracts/dist/integrations/providers/twilio-sms.js  1.56 kB │ gzip: 0.73 kB
128
128
  ℹ dist/libs/contracts/dist/docs/tech/mcp-endpoints.docblock.js  1.51 kB │ gzip: 0.79 kB
129
129
  ℹ dist/libs/contracts/dist/integrations/providers/elevenlabs.js  1.47 kB │ gzip: 0.72 kB
130
- ℹ dist/libs/contracts/dist/ownership.js.map  1.41 kB │ gzip: 0.61 kB
130
+ ℹ dist/libs/contracts/dist/ownership.js.map  1.47 kB │ gzip: 0.63 kB
131
131
  ℹ dist/libs/contracts/dist/docs/meta.docs.js.map  1.38 kB │ gzip: 0.78 kB
132
132
  ℹ dist/libs/contracts/dist/docs/index.js  1.38 kB │ gzip: 0.43 kB
133
133
  ℹ dist/example.js.map  1.33 kB │ gzip: 0.68 kB
@@ -145,8 +145,8 @@ $ tsdown
145
145
  ℹ dist/libs/contracts/dist/integrations/index.js  0.78 kB │ gzip: 0.27 kB
146
146
  ℹ dist/policy/guard.d.ts.map  0.76 kB │ gzip: 0.39 kB
147
147
  ℹ dist/libs/contracts/dist/spec.js  0.68 kB │ gzip: 0.33 kB
148
+ ℹ dist/libs/contracts/dist/ownership.js  0.68 kB │ gzip: 0.34 kB
148
149
  ℹ dist/contracts/assistant.d.ts.map  0.67 kB │ gzip: 0.28 kB
149
- ℹ dist/libs/contracts/dist/ownership.js  0.64 kB │ gzip: 0.33 kB
150
150
  ℹ dist/libs/contracts/dist/integrations/openbanking/telemetry.js  0.60 kB │ gzip: 0.28 kB
151
151
  ℹ dist/events.d.ts.map  0.57 kB │ gzip: 0.25 kB
152
152
  ℹ dist/libs/contracts/dist/events.js.map  0.53 kB │ gzip: 0.35 kB
@@ -214,33 +214,13 @@ $ tsdown
214
214
  ℹ dist/handlers/index.d.ts  0.15 kB │ gzip: 0.09 kB
215
215
  ℹ dist/docs/index.d.ts  0.01 kB │ gzip: 0.03 kB
216
216
  ℹ dist/docs/locale-jurisdiction-gate.docblock.d.ts  0.01 kB │ gzip: 0.03 kB
217
- ℹ 208 files, total: 1262.82 kB
218
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/workflow/runner.js
219
- ╭─[ ../../libs/contracts/dist/workflow/runner.js:2:28 ]
220
- │
221
- 2 │ import { randomUUID } from "node:crypto";
222
-  │ ──────┬──────
223
-  │ ╰──────── Module not found, treating it as an external dependency
224
-  │
225
-  │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
226
- ───╯
227
-
228
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/experiments/evaluator.js
229
- ╭─[ ../../libs/contracts/dist/experiments/evaluator.js:1:28 ]
230
- │
231
- 1 │ import { createHash } from "node:crypto";
232
-  │ ──────┬──────
233
-  │ ╰──────── Module not found, treating it as an external dependency
234
-  │
235
-  │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
236
- ───╯
237
-
238
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:timers/promises' in ../../libs/contracts/dist/regenerator/service.js
239
- ╭─[ ../../libs/contracts/dist/regenerator/service.js:2:28 ]
217
+ ℹ 208 files, total: 1263.15 kB
218
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'turndown' in ../../libs/contracts/dist/presentations.v2.js
219
+ ╭─[ ../../libs/contracts/dist/presentations.v2.js:3:29 ]
240
220
  │
241
- 2 │ import { setTimeout } from "node:timers/promises";
242
-  │ ───────────┬──────────
243
-  │ ╰──────────── Module not found, treating it as an external dependency
221
+ 3 │ import TurndownService from "turndown";
222
+  │ ─────┬────
223
+  │ ╰────── Module not found, treating it as an external dependency
244
224
   │
245
225
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
246
226
  ───╯
@@ -265,12 +245,32 @@ $ tsdown
265
245
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
266
246
  ───╯
267
247
 
268
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'turndown' in ../../libs/contracts/dist/presentations.v2.js
269
- ╭─[ ../../libs/contracts/dist/presentations.v2.js:3:29 ]
248
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/experiments/evaluator.js
249
+ ╭─[ ../../libs/contracts/dist/experiments/evaluator.js:1:28 ]
270
250
  │
271
- 3 │ import TurndownService from "turndown";
272
-  │ ─────┬────
273
-  │ ╰────── Module not found, treating it as an external dependency
251
+ 1 │ import { createHash } from "node:crypto";
252
+  │ ──────┬──────
253
+  │ ╰──────── Module not found, treating it as an external dependency
254
+  │
255
+  │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
256
+ ───╯
257
+
258
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/workflow/runner.js
259
+ ╭─[ ../../libs/contracts/dist/workflow/runner.js:2:28 ]
260
+ │
261
+ 2 │ import { randomUUID } from "node:crypto";
262
+  │ ──────┬──────
263
+  │ ╰──────── Module not found, treating it as an external dependency
264
+  │
265
+  │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
266
+ ───╯
267
+
268
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:timers/promises' in ../../libs/contracts/dist/regenerator/service.js
269
+ ╭─[ ../../libs/contracts/dist/regenerator/service.js:2:28 ]
270
+ │
271
+ 2 │ import { setTimeout } from "node:timers/promises";
272
+  │ ───────────┬──────────
273
+  │ ╰──────────── Module not found, treating it as an external dependency
274
274
   │
275
275
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
276
276
  ───╯
@@ -285,4 +285,4 @@ $ tsdown
285
285
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
286
286
  ───╯
287
287
 
288
- ✔ Build complete in 46932ms
288
+ ✔ Build complete in 49555ms
@@ -9,7 +9,7 @@ $ tsdown
9
9
  ℹ dist/entities/models.js  3.55 kB │ gzip: 0.82 kB
10
10
  ℹ dist/contracts/assistant.js  3.18 kB │ gzip: 1.05 kB
11
11
  ℹ dist/events.js  2.57 kB │ gzip: 0.58 kB
12
- ℹ dist/handlers/demo.handlers.js  2.41 kB │ gzip: 0.90 kB
12
+ ℹ dist/handlers/demo.handlers.js  2.46 kB │ gzip: 0.90 kB
13
13
  ℹ dist/policy/guard.js  1.90 kB │ gzip: 0.76 kB
14
14
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js  1.69 kB │ gzip: 0.76 kB
15
15
  ℹ dist/index.js  1.27 kB │ gzip: 0.40 kB
@@ -46,9 +46,9 @@ $ tsdown
46
46
  ℹ dist/libs/contracts/dist/knowledge/contracts.js  6.68 kB │ gzip: 1.33 kB
47
47
  ℹ dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js.map  6.33 kB │ gzip: 2.84 kB
48
48
  ℹ dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js.map  6.17 kB │ gzip: 2.52 kB
49
+ ℹ dist/handlers/demo.handlers.js.map  5.97 kB │ gzip: 1.81 kB
49
50
  ℹ dist/entities/models.js.map  5.92 kB │ gzip: 1.22 kB
50
51
  ℹ dist/libs/contracts/dist/docs/tech/templates/runtime.docblock.js  5.90 kB │ gzip: 2.68 kB
51
- ℹ dist/handlers/demo.handlers.js.map  5.78 kB │ gzip: 1.76 kB
52
52
  ℹ dist/libs/contracts/dist/docs/tech/workflows/overview.docblock.js  5.71 kB │ gzip: 2.36 kB
53
53
  ℹ dist/libs/contracts/dist/integrations/openbanking/contracts/accounts.js  5.63 kB │ gzip: 1.50 kB
54
54
  ℹ dist/libs/contracts/dist/docs/tech/telemetry-ingest.docblock.js.map  5.10 kB │ gzip: 1.98 kB
@@ -127,7 +127,7 @@ $ tsdown
127
127
  ℹ dist/libs/contracts/dist/integrations/providers/twilio-sms.js  1.56 kB │ gzip: 0.73 kB
128
128
  ℹ dist/libs/contracts/dist/docs/tech/mcp-endpoints.docblock.js  1.51 kB │ gzip: 0.79 kB
129
129
  ℹ dist/libs/contracts/dist/integrations/providers/elevenlabs.js  1.47 kB │ gzip: 0.72 kB
130
- ℹ dist/libs/contracts/dist/ownership.js.map  1.41 kB │ gzip: 0.61 kB
130
+ ℹ dist/libs/contracts/dist/ownership.js.map  1.47 kB │ gzip: 0.63 kB
131
131
  ℹ dist/libs/contracts/dist/docs/meta.docs.js.map  1.38 kB │ gzip: 0.78 kB
132
132
  ℹ dist/libs/contracts/dist/docs/index.js  1.38 kB │ gzip: 0.43 kB
133
133
  ℹ dist/example.js.map  1.33 kB │ gzip: 0.68 kB
@@ -145,10 +145,10 @@ $ tsdown
145
145
  ℹ dist/libs/contracts/dist/integrations/index.js  0.78 kB │ gzip: 0.27 kB
146
146
  ℹ dist/policy/guard.d.ts.map  0.76 kB │ gzip: 0.39 kB
147
147
  ℹ dist/libs/contracts/dist/spec.js  0.68 kB │ gzip: 0.33 kB
148
+ ℹ dist/libs/contracts/dist/ownership.js  0.68 kB │ gzip: 0.34 kB
148
149
  ℹ dist/contracts/assistant.d.ts.map  0.67 kB │ gzip: 0.28 kB
149
- ℹ dist/libs/contracts/dist/ownership.js  0.64 kB │ gzip: 0.33 kB
150
150
  ℹ dist/libs/contracts/dist/integrations/openbanking/telemetry.js  0.60 kB │ gzip: 0.28 kB
151
- ℹ dist/events.d.ts.map  0.57 kB │ gzip: 0.25 kB
151
+ ℹ dist/events.d.ts.map  0.57 kB │ gzip: 0.26 kB
152
152
  ℹ dist/libs/contracts/dist/events.js.map  0.53 kB │ gzip: 0.35 kB
153
153
  ℹ dist/libs/contracts/dist/llm/exporters.js  0.46 kB │ gzip: 0.26 kB
154
154
  ℹ dist/handlers/demo.handlers.d.ts.map  0.45 kB │ gzip: 0.26 kB
@@ -201,7 +201,7 @@ $ tsdown
201
201
  ℹ dist/libs/contracts/dist/resources.js  0.01 kB │ gzip: 0.03 kB
202
202
  ℹ dist/contracts/assistant.d.ts  6.77 kB │ gzip: 0.62 kB
203
203
  ℹ dist/entities/models.d.ts  5.04 kB │ gzip: 0.67 kB
204
- ℹ dist/events.d.ts  2.03 kB │ gzip: 0.38 kB
204
+ ℹ dist/events.d.ts  2.05 kB │ gzip: 0.38 kB
205
205
  ℹ dist/handlers/demo.handlers.d.ts  1.48 kB │ gzip: 0.55 kB
206
206
  ℹ dist/index.d.ts  1.31 kB │ gzip: 0.40 kB
207
207
  ℹ dist/example.d.ts  1.19 kB │ gzip: 0.49 kB
@@ -214,7 +214,7 @@ $ tsdown
214
214
  ℹ dist/handlers/index.d.ts  0.15 kB │ gzip: 0.09 kB
215
215
  ℹ dist/docs/index.d.ts  0.01 kB │ gzip: 0.03 kB
216
216
  ℹ dist/docs/locale-jurisdiction-gate.docblock.d.ts  0.01 kB │ gzip: 0.03 kB
217
- ℹ 208 files, total: 1262.79 kB
217
+ ℹ 208 files, total: 1263.14 kB
218
218
  [UNRESOLVED_IMPORT] Warning: Could not resolve 'turndown' in ../../libs/contracts/dist/presentations.v2.js
219
219
  â•­─[ ../../libs/contracts/dist/presentations.v2.js:3:29 ]
220
220
  │
@@ -225,20 +225,20 @@ $ tsdown
225
225
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
226
226
  ───╯
227
227
 
228
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:assert' in ../../libs/contracts/dist/tests/runner.js
229
- ╭─[ ../../libs/contracts/dist/tests/runner.js:2:33 ]
228
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:timers/promises' in ../../libs/contracts/dist/regenerator/service.js
229
+ ╭─[ ../../libs/contracts/dist/regenerator/service.js:2:28 ]
230
230
  │
231
- 2 │ import { deepStrictEqual } from "node:assert";
232
-  │ ──────┬──────
233
-  │ ╰──────── Module not found, treating it as an external dependency
231
+ 2 │ import { setTimeout } from "node:timers/promises";
232
+  │ ───────────┬──────────
233
+  │ ╰──────────── Module not found, treating it as an external dependency
234
234
   │
235
235
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
236
236
  ───╯
237
237
 
238
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/experiments/evaluator.js
239
- ╭─[ ../../libs/contracts/dist/experiments/evaluator.js:1:28 ]
238
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/workflow/runner.js
239
+ ╭─[ ../../libs/contracts/dist/workflow/runner.js:2:28 ]
240
240
  │
241
- 1 │ import { createHash } from "node:crypto";
241
+ 2 │ import { randomUUID } from "node:crypto";
242
242
   │ ──────┬──────
243
243
   │ ╰──────── Module not found, treating it as an external dependency
244
244
   │
@@ -255,20 +255,20 @@ $ tsdown
255
255
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
256
256
  ───╯
257
257
 
258
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:timers/promises' in ../../libs/contracts/dist/regenerator/service.js
259
- ╭─[ ../../libs/contracts/dist/regenerator/service.js:2:28 ]
258
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:assert' in ../../libs/contracts/dist/tests/runner.js
259
+ ╭─[ ../../libs/contracts/dist/tests/runner.js:2:33 ]
260
260
  │
261
- 2 │ import { setTimeout } from "node:timers/promises";
262
-  │ ───────────┬──────────
263
-  │ ╰──────────── Module not found, treating it as an external dependency
261
+ 2 │ import { deepStrictEqual } from "node:assert";
262
+  │ ──────┬──────
263
+  │ ╰──────── Module not found, treating it as an external dependency
264
264
   │
265
265
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
266
266
  ───╯
267
267
 
268
- [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/workflow/runner.js
269
- ╭─[ ../../libs/contracts/dist/workflow/runner.js:2:28 ]
268
+ [UNRESOLVED_IMPORT] Warning: Could not resolve 'node:crypto' in ../../libs/contracts/dist/experiments/evaluator.js
269
+ ╭─[ ../../libs/contracts/dist/experiments/evaluator.js:1:28 ]
270
270
  │
271
- 2 │ import { randomUUID } from "node:crypto";
271
+ 1 │ import { createHash } from "node:crypto";
272
272
   │ ──────┬──────
273
273
   │ ╰──────── Module not found, treating it as an external dependency
274
274
   │
@@ -285,5 +285,5 @@ $ tsdown
285
285
   │ Help: The "main" field here was ignored. Main fields must be configured explicitly when using the "neutral" platform.
286
286
  ───╯
287
287
 
288
- ✔ Build complete in 88268ms
288
+ ✔ Build complete in 49862ms
289
289
  $ tsc --noEmit
package/CHANGELOG.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @lssm/example.locale-jurisdiction-gate
2
2
 
3
- ## 0.0.0-canary-20251220002821
3
+ ## 0.0.0-canary-20251220021406
4
4
 
5
5
  ### Minor Changes
6
6
 
@@ -9,5 +9,5 @@
9
9
  ### Patch Changes
10
10
 
11
11
  - Updated dependencies [66a5dfd]
12
- - @lssm/lib.contracts@0.0.0-canary-20251220002821
13
- - @lssm/lib.schema@0.0.0-canary-20251220002821
12
+ - @lssm/lib.contracts@0.0.0-canary-20251220021406
13
+ - @lssm/lib.schema@0.0.0-canary-20251220021406
@@ -27,14 +27,14 @@ function createDemoAssistantHandlers() {
27
27
  };
28
28
  const draft = {
29
29
  locale: env.value.locale,
30
- jurisdiction: env.value.regulatoryContext.jurisdiction,
31
- allowedScope: env.value.allowedScope,
30
+ jurisdiction: env.value.regulatoryContext?.jurisdiction ?? "UNKNOWN",
31
+ allowedScope: env.value.allowedScope ?? "education_only",
32
32
  sections: [{
33
33
  heading: "Answer (demo)",
34
34
  body: `You asked: "${input.question}". This demo answer is derived from the KB snapshot only.`
35
35
  }],
36
36
  citations: [{
37
- kbSnapshotId: env.value.kbSnapshotId,
37
+ kbSnapshotId: env.value.kbSnapshotId ?? "unknown",
38
38
  sourceType: "ruleVersion",
39
39
  sourceId: "rv_demo",
40
40
  title: "Demo rule version",
@@ -1 +1 @@
1
- {"version":3,"file":"demo.handlers.js","names":["draft: AssistantAnswerIR"],"sources":["../../src/handlers/demo.handlers.ts"],"sourcesContent":["import {\n enforceAllowedScope,\n enforceCitations,\n validateEnvelope,\n} from '../policy/guard';\n\ntype AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';\n\ninterface AssistantAnswerIR {\n locale: string;\n jurisdiction: string;\n allowedScope: AllowedScope;\n sections: { heading: string; body: string }[];\n citations: {\n kbSnapshotId: string;\n sourceType: string;\n sourceId: string;\n title?: string;\n excerpt?: string;\n }[];\n disclaimers?: string[];\n riskFlags?: string[];\n refused?: boolean;\n refusalReason?: string;\n}\n\nexport interface DemoAssistantHandlers {\n answer(input: {\n envelope: {\n traceId: string;\n locale: string;\n kbSnapshotId: string;\n allowedScope: AllowedScope;\n regulatoryContext: { jurisdiction: string };\n };\n question: string;\n }): Promise<AssistantAnswerIR>;\n\n explainConcept(input: {\n envelope: {\n traceId: string;\n locale: string;\n kbSnapshotId: string;\n allowedScope: AllowedScope;\n regulatoryContext: { jurisdiction: string };\n };\n conceptKey: string;\n }): Promise<AssistantAnswerIR>;\n}\n\n/**\n * Deterministic demo assistant handlers (no LLM).\n *\n * - Validates envelope\n * - Requires citations\n * - Enforces allowedScope (education_only blocks actionable language)\n */\nexport function createDemoAssistantHandlers(): DemoAssistantHandlers {\n async function answer(input: {\n envelope: DemoAssistantHandlers['answer'] extends (a: infer A) => any\n ? A extends { envelope: infer E }\n ? E\n : never\n : never;\n question: string;\n }): Promise<AssistantAnswerIR> {\n const env = validateEnvelope(input.envelope);\n if (!env.ok) {\n return {\n locale: input.envelope.locale ?? 'en-US',\n jurisdiction:\n input.envelope.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n allowedScope: input.envelope.allowedScope ?? 'education_only',\n sections: [\n {\n heading: 'Request blocked',\n body: env.error.message,\n },\n ],\n citations: [],\n disclaimers: [\n 'This system refuses to answer without a valid envelope.',\n ],\n riskFlags: [env.error.code],\n refused: true,\n refusalReason: env.error.code,\n };\n }\n\n const draft: AssistantAnswerIR = {\n locale: env.value.locale,\n jurisdiction: env.value.regulatoryContext!.jurisdiction!,\n allowedScope: env.value.allowedScope!,\n sections: [\n {\n heading: 'Answer (demo)',\n body: `You asked: \"${input.question}\". This demo answer is derived from the KB snapshot only.`,\n },\n ],\n citations: [\n {\n kbSnapshotId: env.value.kbSnapshotId!,\n sourceType: 'ruleVersion',\n sourceId: 'rv_demo',\n title: 'Demo rule version',\n excerpt: 'Demo excerpt',\n },\n ],\n disclaimers: ['Educational demo only.'],\n riskFlags: [],\n };\n\n const scope = enforceAllowedScope(env.value.allowedScope, draft);\n if (!scope.ok) {\n return {\n ...draft,\n sections: [\n { heading: 'Escalation required', body: scope.error.message },\n ],\n citations: draft.citations,\n refused: true,\n refusalReason: scope.error.code,\n riskFlags: [...(draft.riskFlags ?? []), scope.error.code],\n };\n }\n\n const cited = enforceCitations(draft);\n if (!cited.ok) {\n return {\n ...draft,\n sections: [{ heading: 'Request blocked', body: cited.error.message }],\n citations: [],\n refused: true,\n refusalReason: cited.error.code,\n riskFlags: [...(draft.riskFlags ?? []), cited.error.code],\n };\n }\n\n return draft;\n }\n\n async function explainConcept(input: {\n envelope: DemoAssistantHandlers['explainConcept'] extends (\n a: infer A\n ) => any\n ? A extends { envelope: infer E }\n ? E\n : never\n : never;\n conceptKey: string;\n }): Promise<AssistantAnswerIR> {\n return await answer({\n envelope: input.envelope,\n question: `Explain concept: ${input.conceptKey}`,\n });\n }\n\n return { answer, explainConcept };\n}\n"],"mappings":";;;;;;;;;;AAyDA,SAAgB,8BAAqD;CACnE,eAAe,OAAO,OAOS;EAC7B,MAAM,MAAM,iBAAiB,MAAM,SAAS;AAC5C,MAAI,CAAC,IAAI,GACP,QAAO;GACL,QAAQ,MAAM,SAAS,UAAU;GACjC,cACE,MAAM,SAAS,mBAAmB,gBAAgB;GACpD,cAAc,MAAM,SAAS,gBAAgB;GAC7C,UAAU,CACR;IACE,SAAS;IACT,MAAM,IAAI,MAAM;IACjB,CACF;GACD,WAAW,EAAE;GACb,aAAa,CACX,0DACD;GACD,WAAW,CAAC,IAAI,MAAM,KAAK;GAC3B,SAAS;GACT,eAAe,IAAI,MAAM;GAC1B;EAGH,MAAMA,QAA2B;GAC/B,QAAQ,IAAI,MAAM;GAClB,cAAc,IAAI,MAAM,kBAAmB;GAC3C,cAAc,IAAI,MAAM;GACxB,UAAU,CACR;IACE,SAAS;IACT,MAAM,eAAe,MAAM,SAAS;IACrC,CACF;GACD,WAAW,CACT;IACE,cAAc,IAAI,MAAM;IACxB,YAAY;IACZ,UAAU;IACV,OAAO;IACP,SAAS;IACV,CACF;GACD,aAAa,CAAC,yBAAyB;GACvC,WAAW,EAAE;GACd;EAED,MAAM,QAAQ,oBAAoB,IAAI,MAAM,cAAc,MAAM;AAChE,MAAI,CAAC,MAAM,GACT,QAAO;GACL,GAAG;GACH,UAAU,CACR;IAAE,SAAS;IAAuB,MAAM,MAAM,MAAM;IAAS,CAC9D;GACD,WAAW,MAAM;GACjB,SAAS;GACT,eAAe,MAAM,MAAM;GAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;GAC1D;EAGH,MAAM,QAAQ,iBAAiB,MAAM;AACrC,MAAI,CAAC,MAAM,GACT,QAAO;GACL,GAAG;GACH,UAAU,CAAC;IAAE,SAAS;IAAmB,MAAM,MAAM,MAAM;IAAS,CAAC;GACrE,WAAW,EAAE;GACb,SAAS;GACT,eAAe,MAAM,MAAM;GAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;GAC1D;AAGH,SAAO;;CAGT,eAAe,eAAe,OASC;AAC7B,SAAO,MAAM,OAAO;GAClB,UAAU,MAAM;GAChB,UAAU,oBAAoB,MAAM;GACrC,CAAC;;AAGJ,QAAO;EAAE;EAAQ;EAAgB"}
1
+ {"version":3,"file":"demo.handlers.js","names":["draft: AssistantAnswerIR"],"sources":["../../src/handlers/demo.handlers.ts"],"sourcesContent":["import {\n enforceAllowedScope,\n enforceCitations,\n validateEnvelope,\n} from '../policy/guard';\n\ntype AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';\n\ninterface AssistantAnswerIR {\n locale: string;\n jurisdiction: string;\n allowedScope: AllowedScope;\n sections: { heading: string; body: string }[];\n citations: {\n kbSnapshotId: string;\n sourceType: string;\n sourceId: string;\n title?: string;\n excerpt?: string;\n }[];\n disclaimers?: string[];\n riskFlags?: string[];\n refused?: boolean;\n refusalReason?: string;\n}\n\nexport interface DemoAssistantHandlers {\n answer(input: {\n envelope: {\n traceId: string;\n locale: string;\n kbSnapshotId: string;\n allowedScope: AllowedScope;\n regulatoryContext: { jurisdiction: string };\n };\n question: string;\n }): Promise<AssistantAnswerIR>;\n\n explainConcept(input: {\n envelope: {\n traceId: string;\n locale: string;\n kbSnapshotId: string;\n allowedScope: AllowedScope;\n regulatoryContext: { jurisdiction: string };\n };\n conceptKey: string;\n }): Promise<AssistantAnswerIR>;\n}\n\n/**\n * Deterministic demo assistant handlers (no LLM).\n *\n * - Validates envelope\n * - Requires citations\n * - Enforces allowedScope (education_only blocks actionable language)\n */\nexport function createDemoAssistantHandlers(): DemoAssistantHandlers {\n async function answer(input: {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n envelope: DemoAssistantHandlers['answer'] extends (a: infer A) => any\n ? A extends { envelope: infer E }\n ? E\n : never\n : never;\n question: string;\n }): Promise<AssistantAnswerIR> {\n const env = validateEnvelope(input.envelope);\n if (!env.ok) {\n return {\n locale: input.envelope.locale ?? 'en-US',\n jurisdiction:\n input.envelope.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n allowedScope: input.envelope.allowedScope ?? 'education_only',\n sections: [\n {\n heading: 'Request blocked',\n body: env.error.message,\n },\n ],\n citations: [],\n disclaimers: [\n 'This system refuses to answer without a valid envelope.',\n ],\n riskFlags: [env.error.code],\n refused: true,\n refusalReason: env.error.code,\n };\n }\n\n const draft: AssistantAnswerIR = {\n locale: env.value.locale,\n jurisdiction: env.value.regulatoryContext?.jurisdiction ?? 'UNKNOWN',\n allowedScope: env.value.allowedScope ?? 'education_only',\n sections: [\n {\n heading: 'Answer (demo)',\n body: `You asked: \"${input.question}\". This demo answer is derived from the KB snapshot only.`,\n },\n ],\n citations: [\n {\n kbSnapshotId: env.value.kbSnapshotId ?? 'unknown',\n sourceType: 'ruleVersion',\n sourceId: 'rv_demo',\n title: 'Demo rule version',\n excerpt: 'Demo excerpt',\n },\n ],\n disclaimers: ['Educational demo only.'],\n riskFlags: [],\n };\n\n const scope = enforceAllowedScope(env.value.allowedScope, draft);\n if (!scope.ok) {\n return {\n ...draft,\n sections: [\n { heading: 'Escalation required', body: scope.error.message },\n ],\n citations: draft.citations,\n refused: true,\n refusalReason: scope.error.code,\n riskFlags: [...(draft.riskFlags ?? []), scope.error.code],\n };\n }\n\n const cited = enforceCitations(draft);\n if (!cited.ok) {\n return {\n ...draft,\n sections: [{ heading: 'Request blocked', body: cited.error.message }],\n citations: [],\n refused: true,\n refusalReason: cited.error.code,\n riskFlags: [...(draft.riskFlags ?? []), cited.error.code],\n };\n }\n\n return draft;\n }\n\n async function explainConcept(input: {\n envelope: DemoAssistantHandlers['explainConcept'] extends (\n a: infer A\n ) => any // eslint-disable-line @typescript-eslint/no-explicit-any\n ? A extends { envelope: infer E }\n ? E\n : never\n : never;\n conceptKey: string;\n }): Promise<AssistantAnswerIR> {\n return await answer({\n envelope: input.envelope,\n question: `Explain concept: ${input.conceptKey}`,\n });\n }\n\n return { answer, explainConcept };\n}\n"],"mappings":";;;;;;;;;;AAyDA,SAAgB,8BAAqD;CACnE,eAAe,OAAO,OAQS;EAC7B,MAAM,MAAM,iBAAiB,MAAM,SAAS;AAC5C,MAAI,CAAC,IAAI,GACP,QAAO;GACL,QAAQ,MAAM,SAAS,UAAU;GACjC,cACE,MAAM,SAAS,mBAAmB,gBAAgB;GACpD,cAAc,MAAM,SAAS,gBAAgB;GAC7C,UAAU,CACR;IACE,SAAS;IACT,MAAM,IAAI,MAAM;IACjB,CACF;GACD,WAAW,EAAE;GACb,aAAa,CACX,0DACD;GACD,WAAW,CAAC,IAAI,MAAM,KAAK;GAC3B,SAAS;GACT,eAAe,IAAI,MAAM;GAC1B;EAGH,MAAMA,QAA2B;GAC/B,QAAQ,IAAI,MAAM;GAClB,cAAc,IAAI,MAAM,mBAAmB,gBAAgB;GAC3D,cAAc,IAAI,MAAM,gBAAgB;GACxC,UAAU,CACR;IACE,SAAS;IACT,MAAM,eAAe,MAAM,SAAS;IACrC,CACF;GACD,WAAW,CACT;IACE,cAAc,IAAI,MAAM,gBAAgB;IACxC,YAAY;IACZ,UAAU;IACV,OAAO;IACP,SAAS;IACV,CACF;GACD,aAAa,CAAC,yBAAyB;GACvC,WAAW,EAAE;GACd;EAED,MAAM,QAAQ,oBAAoB,IAAI,MAAM,cAAc,MAAM;AAChE,MAAI,CAAC,MAAM,GACT,QAAO;GACL,GAAG;GACH,UAAU,CACR;IAAE,SAAS;IAAuB,MAAM,MAAM,MAAM;IAAS,CAC9D;GACD,WAAW,MAAM;GACjB,SAAS;GACT,eAAe,MAAM,MAAM;GAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;GAC1D;EAGH,MAAM,QAAQ,iBAAiB,MAAM;AACrC,MAAI,CAAC,MAAM,GACT,QAAO;GACL,GAAG;GACH,UAAU,CAAC;IAAE,SAAS;IAAmB,MAAM,MAAM,MAAM;IAAS,CAAC;GACrE,WAAW,EAAE;GACb,SAAS;GACT,eAAe,MAAM,MAAM;GAC3B,WAAW,CAAC,GAAI,MAAM,aAAa,EAAE,EAAG,MAAM,MAAM,KAAK;GAC1D;AAGH,SAAO;;CAGT,eAAe,eAAe,OASC;AAC7B,SAAO,MAAM,OAAO;GAClB,UAAU,MAAM;GAChB,UAAU,oBAAoB,MAAM;GACrC,CAAC;;AAGJ,QAAO;EAAE;EAAQ;EAAgB"}
@@ -13,6 +13,7 @@ const OwnersEnum = {
13
13
  ProductArtisanos: "product.artisanos",
14
14
  PlatformSigil: "platform.sigil",
15
15
  PlatformMarketplace: "platform.marketplace",
16
+ PlatformMessaging: "platform.messaging",
16
17
  PlatformContent: "platform.content",
17
18
  PlatformFeatureFlags: "platform.featureflags",
18
19
  PlatformFinance: "platform.finance"
@@ -1 +1 @@
1
- {"version":3,"file":"ownership.js","names":[],"sources":["../../../../../../libs/contracts/dist/ownership.js"],"sourcesContent":["//#region src/ownership.ts\nconst StabilityEnum = {\n\tIdea: \"idea\",\n\tInCreation: \"in_creation\",\n\tExperimental: \"experimental\",\n\tBeta: \"beta\",\n\tStable: \"stable\",\n\tDeprecated: \"deprecated\"\n};\nconst OwnersEnum = {\n\tProductColiving: \"product.coliving\",\n\tProductStrit: \"product.strit\",\n\tProductArtisanos: \"product.artisanos\",\n\tPlatformSigil: \"platform.sigil\",\n\tPlatformMarketplace: \"platform.marketplace\",\n\tPlatformContent: \"platform.content\",\n\tPlatformFeatureFlags: \"platform.featureflags\",\n\tPlatformFinance: \"platform.finance\"\n};\nconst Owners = OwnersEnum;\nconst TagsEnum = {\n\tSpots: \"spots\",\n\tCollectivity: \"collectivity\",\n\tMarketplace: \"marketplace\",\n\tSellers: \"sellers\",\n\tAuth: \"auth\",\n\tLogin: \"login\",\n\tSignup: \"signup\",\n\tGuide: \"guide\",\n\tDocs: \"docs\",\n\tI18n: \"i18n\",\n\tIncident: \"incident\",\n\tAutomation: \"automation\",\n\tHygiene: \"hygiene\"\n};\nconst Tags = TagsEnum;\n\n//#endregion\nexport { Owners, OwnersEnum, StabilityEnum, Tags, TagsEnum };"],"mappings":";AACA,MAAM,gBAAgB;CACrB,MAAM;CACN,YAAY;CACZ,cAAc;CACd,MAAM;CACN,QAAQ;CACR,YAAY;CACZ;AACD,MAAM,aAAa;CAClB,iBAAiB;CACjB,cAAc;CACd,kBAAkB;CAClB,eAAe;CACf,qBAAqB;CACrB,iBAAiB;CACjB,sBAAsB;CACtB,iBAAiB;CACjB"}
1
+ {"version":3,"file":"ownership.js","names":[],"sources":["../../../../../../libs/contracts/dist/ownership.js"],"sourcesContent":["//#region src/ownership.ts\nconst StabilityEnum = {\n\tIdea: \"idea\",\n\tInCreation: \"in_creation\",\n\tExperimental: \"experimental\",\n\tBeta: \"beta\",\n\tStable: \"stable\",\n\tDeprecated: \"deprecated\"\n};\nconst OwnersEnum = {\n\tProductColiving: \"product.coliving\",\n\tProductStrit: \"product.strit\",\n\tProductArtisanos: \"product.artisanos\",\n\tPlatformSigil: \"platform.sigil\",\n\tPlatformMarketplace: \"platform.marketplace\",\n\tPlatformMessaging: \"platform.messaging\",\n\tPlatformContent: \"platform.content\",\n\tPlatformFeatureFlags: \"platform.featureflags\",\n\tPlatformFinance: \"platform.finance\"\n};\nconst Owners = OwnersEnum;\nconst TagsEnum = {\n\tSpots: \"spots\",\n\tCollectivity: \"collectivity\",\n\tMarketplace: \"marketplace\",\n\tSellers: \"sellers\",\n\tAuth: \"auth\",\n\tLogin: \"login\",\n\tSignup: \"signup\",\n\tGuide: \"guide\",\n\tDocs: \"docs\",\n\tI18n: \"i18n\",\n\tIncident: \"incident\",\n\tAutomation: \"automation\",\n\tHygiene: \"hygiene\"\n};\nconst Tags = TagsEnum;\n\n//#endregion\nexport { Owners, OwnersEnum, StabilityEnum, Tags, TagsEnum };"],"mappings":";AACA,MAAM,gBAAgB;CACrB,MAAM;CACN,YAAY;CACZ,cAAc;CACd,MAAM;CACN,QAAQ;CACR,YAAY;CACZ;AACD,MAAM,aAAa;CAClB,iBAAiB;CACjB,cAAc;CACd,kBAAkB;CAClB,eAAe;CACf,qBAAqB;CACrB,mBAAmB;CACnB,iBAAiB;CACjB,sBAAsB;CACtB,iBAAiB;CACjB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/example.locale-jurisdiction-gate",
3
- "version": "0.0.0-canary-20251220002821",
3
+ "version": "0.0.0-canary-20251220021406",
4
4
  "description": "Example: enforce locale + jurisdiction + kbSnapshotId + allowed scope for assistant calls (fail-closed).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -38,13 +38,13 @@
38
38
  "test": "bun test"
39
39
  },
40
40
  "dependencies": {
41
- "@lssm/lib.contracts": "0.0.0-canary-20251220002821",
42
- "@lssm/lib.schema": "0.0.0-canary-20251220002821",
41
+ "@lssm/lib.contracts": "0.0.0-canary-20251220021406",
42
+ "@lssm/lib.schema": "0.0.0-canary-20251220021406",
43
43
  "zod": "^4.1.13"
44
44
  },
45
45
  "devDependencies": {
46
- "@lssm/tool.tsdown": "0.0.0-canary-20251220002821",
47
- "@lssm/tool.typescript": "0.0.0-canary-20251220002821",
46
+ "@lssm/tool.tsdown": "0.0.0-canary-20251220021406",
47
+ "@lssm/tool.typescript": "0.0.0-canary-20251220021406",
48
48
  "tsdown": "^0.18.1",
49
49
  "typescript": "^5.9.3"
50
50
  },
@@ -57,6 +57,7 @@ export interface DemoAssistantHandlers {
57
57
  */
58
58
  export function createDemoAssistantHandlers(): DemoAssistantHandlers {
59
59
  async function answer(input: {
60
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
60
61
  envelope: DemoAssistantHandlers['answer'] extends (a: infer A) => any
61
62
  ? A extends { envelope: infer E }
62
63
  ? E
@@ -89,8 +90,8 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
89
90
 
90
91
  const draft: AssistantAnswerIR = {
91
92
  locale: env.value.locale,
92
- jurisdiction: env.value.regulatoryContext!.jurisdiction!,
93
- allowedScope: env.value.allowedScope!,
93
+ jurisdiction: env.value.regulatoryContext?.jurisdiction ?? 'UNKNOWN',
94
+ allowedScope: env.value.allowedScope ?? 'education_only',
94
95
  sections: [
95
96
  {
96
97
  heading: 'Answer (demo)',
@@ -99,7 +100,7 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
99
100
  ],
100
101
  citations: [
101
102
  {
102
- kbSnapshotId: env.value.kbSnapshotId!,
103
+ kbSnapshotId: env.value.kbSnapshotId ?? 'unknown',
103
104
  sourceType: 'ruleVersion',
104
105
  sourceId: 'rv_demo',
105
106
  title: 'Demo rule version',
@@ -142,7 +143,7 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
142
143
  async function explainConcept(input: {
143
144
  envelope: DemoAssistantHandlers['explainConcept'] extends (
144
145
  a: infer A
145
- ) => any
146
+ ) => any // eslint-disable-line @typescript-eslint/no-explicit-any
146
147
  ? A extends { envelope: infer E }
147
148
  ? E
148
149
  : never