@lssm/example.locale-jurisdiction-gate 0.0.0-canary-20251213172311 → 0.0.0-canary-20251215220103

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.
@@ -1,8 +1,8 @@
1
1
  $ bun build:bundle && bun build:types
2
2
  $ tsdown
3
- ℹ tsdown v0.17.0 powered by rolldown v1.0.0-beta.53
3
+ ℹ tsdown v0.17.4 powered by rolldown v1.0.0-beta.53
4
4
  ℹ config file: /home/runner/work/contractspec/contractspec/packages/examples/locale-jurisdiction-gate/tsdown.config.js
5
- ℹ entry: src/events.ts, src/example.ts, src/feature.ts, src/index.ts, src/docs/index.ts, src/docs/locale-jurisdiction-gate.docblock.ts, src/entities/index.ts, src/entities/models.ts, src/contracts/assistant.ts, src/contracts/index.ts, src/handlers/demo.handlers.ts, src/handlers/index.ts, src/policy/guard.ts, src/policy/index.ts, src/policy/types.ts
5
+ ℹ entry: src/events.ts, src/example.ts, src/feature.ts, src/index.ts, src/contracts/assistant.ts, src/contracts/index.ts, src/docs/index.ts, src/docs/locale-jurisdiction-gate.docblock.ts, src/entities/index.ts, src/entities/models.ts, src/handlers/demo.handlers.ts, src/handlers/index.ts, src/policy/guard.ts, src/policy/index.ts, src/policy/types.ts
6
6
  ℹ target: esnext
7
7
  ℹ tsconfig: tsconfig.json
8
8
  ℹ Build start
@@ -22,5 +22,5 @@ $ tsdown
22
22
  ℹ dist/docs/index.js 0.05 kB │ gzip: 0.07 kB
23
23
  ℹ dist/policy/types.js 0.00 kB │ gzip: 0.02 kB
24
24
  ℹ 15 files, total: 14.27 kB
25
- ✔ Build complete in 64ms
25
+ ✔ Build complete in 65ms
26
26
  $ tsc --noEmit
package/CHANGELOG.md CHANGED
@@ -1,9 +1,9 @@
1
1
  # @lssm/example.locale-jurisdiction-gate
2
2
 
3
- ## 0.0.0-canary-20251213172311
3
+ ## 0.0.0-canary-20251215220103
4
4
 
5
5
  ### Patch Changes
6
6
 
7
7
  - Updated dependencies [3086383]
8
- - @lssm/lib.contracts@0.0.0-canary-20251213172311
9
- - @lssm/lib.schema@0.0.0-canary-20251213172311
8
+ - @lssm/lib.contracts@0.0.0-canary-20251215220103
9
+ - @lssm/lib.schema@0.0.0-canary-20251215220103
package/README.md CHANGED
@@ -29,3 +29,4 @@ bun test
29
29
  ```
30
30
 
31
31
 
32
+
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lssm/example.locale-jurisdiction-gate",
3
- "version": "0.0.0-canary-20251213172311",
3
+ "version": "0.0.0-canary-20251215220103",
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",
@@ -43,7 +43,7 @@
43
43
  "devDependencies": {
44
44
  "@lssm/tool.tsdown": "workspace:*",
45
45
  "@lssm/tool.typescript": "workspace:*",
46
- "tsdown": "^0.17.0",
46
+ "tsdown": "^0.17.4",
47
47
  "typescript": "^5.9.3"
48
48
  },
49
49
  "publishConfig": {
@@ -1,7 +1,10 @@
1
1
  import { defineCommand } from '@lssm/lib.contracts';
2
2
  import { ScalarTypeEnum, defineSchemaModel } from '@lssm/lib.schema';
3
3
 
4
- import { AssistantAnswerIRModel, LLMCallEnvelopeModel } from '../entities/models';
4
+ import {
5
+ AssistantAnswerIRModel,
6
+ LLMCallEnvelopeModel,
7
+ } from '../entities/models';
5
8
 
6
9
  const AssistantQuestionInput = defineSchemaModel({
7
10
  name: 'AssistantQuestionInput',
@@ -63,7 +66,8 @@ export const AssistantAnswerContract = defineCommand({
63
66
  when: 'answer has no citations',
64
67
  },
65
68
  SCOPE_VIOLATION: {
66
- description: 'Answer violates allowed scope and must be refused/escalated',
69
+ description:
70
+ 'Answer violates allowed scope and must be refused/escalated',
67
71
  http: 403,
68
72
  gqlCode: 'SCOPE_VIOLATION',
69
73
  when: 'output includes forbidden content under the given allowedScope',
@@ -92,5 +96,3 @@ export const AssistantExplainConceptContract = defineCommand({
92
96
  },
93
97
  policy: { auth: 'user' },
94
98
  });
95
-
96
-
@@ -1,3 +1 @@
1
1
  export * from './assistant';
2
-
3
-
package/src/docs/index.ts CHANGED
@@ -1,3 +1 @@
1
1
  import './locale-jurisdiction-gate.docblock';
2
-
3
-
@@ -44,5 +44,3 @@ const docBlocks: DocBlock[] = [
44
44
  ];
45
45
 
46
46
  registerDocBlocks(docBlocks);
47
-
48
-
@@ -1,3 +1 @@
1
1
  export * from './models';
2
-
3
-
@@ -1,4 +1,8 @@
1
- import { ScalarTypeEnum, defineEnum, defineSchemaModel } from '@lssm/lib.schema';
1
+ import {
2
+ ScalarTypeEnum,
3
+ defineEnum,
4
+ defineSchemaModel,
5
+ } from '@lssm/lib.schema';
2
6
 
3
7
  export const AllowedScopeEnum = defineEnum('AllowedScope', [
4
8
  'education_only',
@@ -10,8 +14,14 @@ export const UserProfileModel = defineSchemaModel({
10
14
  name: 'UserProfile',
11
15
  description: 'User profile inputs used to derive regulatory context.',
12
16
  fields: {
13
- preferredLocale: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
14
- residencyCountry: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
17
+ preferredLocale: {
18
+ type: ScalarTypeEnum.String_unsecure(),
19
+ isOptional: true,
20
+ },
21
+ residencyCountry: {
22
+ type: ScalarTypeEnum.String_unsecure(),
23
+ isOptional: true,
24
+ },
15
25
  taxResidenceCountry: {
16
26
  type: ScalarTypeEnum.String_unsecure(),
17
27
  isOptional: true,
@@ -46,7 +56,8 @@ export const LLMCallEnvelopeModel = defineSchemaModel({
46
56
 
47
57
  export const AssistantCitationModel = defineSchemaModel({
48
58
  name: 'AssistantCitation',
49
- description: 'Citation referencing a KB snapshot + a specific item within it.',
59
+ description:
60
+ 'Citation referencing a KB snapshot + a specific item within it.',
50
61
  fields: {
51
62
  kbSnapshotId: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
52
63
  sourceType: { type: ScalarTypeEnum.String_unsecure(), isOptional: false },
@@ -97,5 +108,3 @@ export const AssistantAnswerIRModel = defineSchemaModel({
97
108
  refusalReason: { type: ScalarTypeEnum.String_unsecure(), isOptional: true },
98
109
  },
99
110
  });
100
-
101
-
package/src/events.ts CHANGED
@@ -57,5 +57,3 @@ export const AssistantAnswerDeliveredEvent = defineEvent({
57
57
  'Assistant answer delivered (must include KB snapshot citations).',
58
58
  payload: AssistantAnswerDeliveredPayload,
59
59
  });
60
-
61
-
package/src/example.ts CHANGED
@@ -25,5 +25,3 @@ const example = {
25
25
  } as const;
26
26
 
27
27
  export default example;
28
-
29
-
package/src/feature.ts CHANGED
@@ -27,5 +27,3 @@ export const LocaleJurisdictionGateFeature: FeatureModuleSpec = {
27
27
  requires: [{ key: 'knowledge', version: 1 }],
28
28
  },
29
29
  };
30
-
31
-
@@ -1,24 +1,28 @@
1
- import { enforceAllowedScope, enforceCitations, validateEnvelope } from '../policy/guard';
1
+ import {
2
+ enforceAllowedScope,
3
+ enforceCitations,
4
+ validateEnvelope,
5
+ } from '../policy/guard';
2
6
 
3
7
  type AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';
4
8
 
5
- type AssistantAnswerIR = {
9
+ interface AssistantAnswerIR {
6
10
  locale: string;
7
11
  jurisdiction: string;
8
12
  allowedScope: AllowedScope;
9
- sections: Array<{ heading: string; body: string }>;
10
- citations: Array<{
13
+ sections: { heading: string; body: string }[];
14
+ citations: {
11
15
  kbSnapshotId: string;
12
16
  sourceType: string;
13
17
  sourceId: string;
14
18
  title?: string;
15
19
  excerpt?: string;
16
- }>;
20
+ }[];
17
21
  disclaimers?: string[];
18
22
  riskFlags?: string[];
19
23
  refused?: boolean;
20
24
  refusalReason?: string;
21
- };
25
+ }
22
26
 
23
27
  export interface DemoAssistantHandlers {
24
28
  answer(input: {
@@ -64,7 +68,8 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
64
68
  if (!env.ok) {
65
69
  return {
66
70
  locale: input.envelope.locale ?? 'en-US',
67
- jurisdiction: input.envelope.regulatoryContext?.jurisdiction ?? 'UNKNOWN',
71
+ jurisdiction:
72
+ input.envelope.regulatoryContext?.jurisdiction ?? 'UNKNOWN',
68
73
  allowedScope: input.envelope.allowedScope ?? 'education_only',
69
74
  sections: [
70
75
  {
@@ -73,7 +78,9 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
73
78
  },
74
79
  ],
75
80
  citations: [],
76
- disclaimers: ['This system refuses to answer without a valid envelope.'],
81
+ disclaimers: [
82
+ 'This system refuses to answer without a valid envelope.',
83
+ ],
77
84
  riskFlags: [env.error.code],
78
85
  refused: true,
79
86
  refusalReason: env.error.code,
@@ -121,9 +128,7 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
121
128
  if (!cited.ok) {
122
129
  return {
123
130
  ...draft,
124
- sections: [
125
- { heading: 'Request blocked', body: cited.error.message },
126
- ],
131
+ sections: [{ heading: 'Request blocked', body: cited.error.message }],
127
132
  citations: [],
128
133
  refused: true,
129
134
  refusalReason: cited.error.code,
@@ -135,7 +140,9 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
135
140
  }
136
141
 
137
142
  async function explainConcept(input: {
138
- envelope: DemoAssistantHandlers['explainConcept'] extends (a: infer A) => any
143
+ envelope: DemoAssistantHandlers['explainConcept'] extends (
144
+ a: infer A
145
+ ) => any
139
146
  ? A extends { envelope: infer E }
140
147
  ? E
141
148
  : never
@@ -150,5 +157,3 @@ export function createDemoAssistantHandlers(): DemoAssistantHandlers {
150
157
 
151
158
  return { answer, explainConcept };
152
159
  }
153
-
154
-
@@ -1,3 +1 @@
1
1
  export * from './demo.handlers';
2
-
3
-
package/src/index.ts CHANGED
@@ -13,5 +13,3 @@ export * from './feature';
13
13
  export { default as example } from './example';
14
14
 
15
15
  import './docs';
16
-
17
-
@@ -23,5 +23,3 @@ describe('locale/jurisdiction gate policy', () => {
23
23
  if (!result.ok) expect(result.error.code).toBe('CITATIONS_REQUIRED');
24
24
  });
25
25
  });
26
-
27
-
@@ -1,19 +1,19 @@
1
1
  import type { GateError, GateResult } from './types';
2
2
 
3
- type EnvelopeLike = {
3
+ interface EnvelopeLike {
4
4
  locale?: string;
5
5
  kbSnapshotId?: string;
6
6
  allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';
7
7
  regulatoryContext?: { jurisdiction?: string };
8
- };
8
+ }
9
9
 
10
- type AnswerLike = {
10
+ interface AnswerLike {
11
11
  citations?: unknown[];
12
- sections?: Array<{ heading: string; body: string }>;
12
+ sections?: { heading: string; body: string }[];
13
13
  refused?: boolean;
14
14
  refusalReason?: string;
15
15
  allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';
16
- };
16
+ }
17
17
 
18
18
  const SUPPORTED_LOCALES = new Set<string>(['en-US', 'en-GB', 'fr-FR']);
19
19
 
@@ -31,7 +31,10 @@ export function validateEnvelope(
31
31
  };
32
32
  }
33
33
  if (!envelope.regulatoryContext?.jurisdiction) {
34
- return { ok: false, error: err('JURISDICTION_REQUIRED', 'jurisdiction is required') };
34
+ return {
35
+ ok: false,
36
+ error: err('JURISDICTION_REQUIRED', 'jurisdiction is required'),
37
+ };
35
38
  }
36
39
  if (!envelope.kbSnapshotId) {
37
40
  return {
@@ -53,7 +56,10 @@ export function enforceCitations(answer: AnswerLike): GateResult<AnswerLike> {
53
56
  if (!Array.isArray(citations) || citations.length === 0) {
54
57
  return {
55
58
  ok: false,
56
- error: err('CITATIONS_REQUIRED', 'answers must include at least one citation'),
59
+ error: err(
60
+ 'CITATIONS_REQUIRED',
61
+ 'answers must include at least one citation'
62
+ ),
57
63
  };
58
64
  }
59
65
  return { ok: true, value: answer };
@@ -80,7 +86,9 @@ export function enforceAllowedScope(
80
86
  }
81
87
 
82
88
  const bodies = (answer.sections ?? []).map((s) => s.body).join('\n');
83
- const violations = EDUCATION_ONLY_FORBIDDEN_PATTERNS.some((re) => re.test(bodies));
89
+ const violations = EDUCATION_ONLY_FORBIDDEN_PATTERNS.some((re) =>
90
+ re.test(bodies)
91
+ );
84
92
  if (violations) {
85
93
  return {
86
94
  ok: false,
@@ -92,5 +100,3 @@ export function enforceAllowedScope(
92
100
  }
93
101
  return { ok: true, value: answer };
94
102
  }
95
-
96
-
@@ -1,4 +1,2 @@
1
1
  export * from './types';
2
2
  export * from './guard';
3
-
4
-
@@ -1,4 +1,7 @@
1
- export type AllowedScope = 'education_only' | 'generic_info' | 'escalation_required';
1
+ export type AllowedScope =
2
+ | 'education_only'
3
+ | 'generic_info'
4
+ | 'escalation_required';
2
5
 
3
6
  export interface GateError {
4
7
  code:
@@ -13,5 +16,3 @@ export interface GateError {
13
16
  export type GateResult<T> =
14
17
  | { ok: true; value: T }
15
18
  | { ok: false; error: GateError };
16
-
17
-
package/tsconfig.json CHANGED
@@ -7,3 +7,4 @@
7
7
  "include": ["src/**/*"],
8
8
  "exclude": ["node_modules", "dist"]
9
9
  }
10
+