@contractspec/example.locale-jurisdiction-gate 1.46.2 → 1.47.0

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,5 +1,5 @@
1
1
  $ tsdown
2
- ℹ tsdown v0.18.4 powered by rolldown v1.0.0-beta.57
2
+ ℹ tsdown v0.19.0 powered by rolldown v1.0.0-beta.59
3
3
  ℹ config file: /home/runner/work/contractspec/contractspec/packages/examples/locale-jurisdiction-gate/tsdown.config.js
4
4
  ℹ entry: src/events.ts, src/example.ts, src/index.ts, src/locale-jurisdiction-gate.feature.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/operations/assistant.ts, src/operations/index.ts, src/policy/guard.ts, src/policy/index.ts, src/policy/types.ts
5
5
  ℹ target: esnext
@@ -13,30 +13,30 @@ $ tsdown
13
13
  ℹ dist/policy/guard.js 1.90 kB │ gzip: 0.76 kB
14
14
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js 1.64 kB │ gzip: 0.74 kB
15
15
  ℹ dist/index.js 1.27 kB │ gzip: 0.40 kB
16
- ℹ dist/locale-jurisdiction-gate.feature.js 1.08 kB │ gzip: 0.46 kB
17
- ℹ dist/example.js 1.05 kB │ gzip: 0.55 kB
16
+ ℹ dist/locale-jurisdiction-gate.feature.js 1.16 kB │ gzip: 0.50 kB
17
+ ℹ dist/example.js 1.13 kB │ gzip: 0.58 kB
18
18
  ℹ dist/entities/index.js 0.36 kB │ gzip: 0.16 kB
19
19
  ℹ dist/operations/index.js 0.16 kB │ gzip: 0.10 kB
20
20
  ℹ dist/policy/index.js 0.15 kB │ gzip: 0.11 kB
21
21
  ℹ dist/handlers/index.js 0.11 kB │ gzip: 0.09 kB
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
- ℹ dist/handlers/demo.handlers.js.map 5.97 kB │ gzip: 1.81 kB
24
+ ℹ dist/handlers/demo.handlers.js.map 5.94 kB │ gzip: 1.81 kB
25
25
  ℹ dist/entities/models.js.map 5.85 kB │ gzip: 1.20 kB
26
26
  ℹ dist/operations/assistant.js.map 4.60 kB │ gzip: 1.41 kB
27
27
  ℹ dist/events.js.map 4.40 kB │ gzip: 0.93 kB
28
- ℹ dist/policy/guard.js.map 4.12 kB │ gzip: 1.44 kB
28
+ ℹ dist/policy/guard.js.map 4.08 kB │ gzip: 1.44 kB
29
29
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js.map 2.16 kB │ gzip: 0.93 kB
30
- ℹ dist/locale-jurisdiction-gate.feature.js.map 1.73 kB │ gzip: 0.73 kB
31
- ℹ dist/example.js.map 1.61 kB │ gzip: 0.78 kB
30
+ ℹ dist/locale-jurisdiction-gate.feature.js.map 1.67 kB │ gzip: 0.72 kB
31
+ ℹ dist/example.js.map 1.60 kB │ gzip: 0.79 kB
32
32
  ℹ dist/entities/models.d.ts.map 0.91 kB │ gzip: 0.39 kB
33
33
  ℹ dist/policy/guard.d.ts.map 0.76 kB │ gzip: 0.39 kB
34
34
  ℹ dist/operations/assistant.d.ts.map 0.65 kB │ gzip: 0.28 kB
35
35
  ℹ dist/events.d.ts.map 0.57 kB │ gzip: 0.26 kB
36
36
  ℹ dist/handlers/demo.handlers.d.ts.map 0.45 kB │ gzip: 0.26 kB
37
37
  ℹ dist/policy/types.d.ts.map 0.25 kB │ gzip: 0.19 kB
38
- ℹ dist/locale-jurisdiction-gate.feature.d.ts.map 0.18 kB │ gzip: 0.14 kB
39
- ℹ dist/example.d.ts.map 0.12 kB │ gzip: 0.12 kB
38
+ ℹ dist/locale-jurisdiction-gate.feature.d.ts.map 0.19 kB │ gzip: 0.15 kB
39
+ ℹ dist/example.d.ts.map 0.14 kB │ gzip: 0.13 kB
40
40
  ℹ dist/operations/assistant.d.ts 7.28 kB │ gzip: 0.64 kB
41
41
  ℹ dist/entities/models.d.ts 5.48 kB │ gzip: 0.68 kB
42
42
  ℹ dist/events.d.ts 2.20 kB │ gzip: 0.38 kB
@@ -45,12 +45,12 @@ $ tsdown
45
45
  ℹ dist/policy/guard.d.ts 0.93 kB │ gzip: 0.42 kB
46
46
  ℹ dist/policy/types.d.ts 0.46 kB │ gzip: 0.31 kB
47
47
  ℹ dist/entities/index.d.ts 0.36 kB │ gzip: 0.16 kB
48
- ℹ dist/locale-jurisdiction-gate.feature.d.ts 0.30 kB │ gzip: 0.18 kB
48
+ ℹ dist/locale-jurisdiction-gate.feature.d.ts 0.34 kB │ gzip: 0.20 kB
49
49
  ℹ dist/policy/index.d.ts 0.26 kB │ gzip: 0.14 kB
50
- ℹ dist/example.d.ts 0.20 kB │ gzip: 0.16 kB
50
+ ℹ dist/example.d.ts 0.25 kB │ gzip: 0.17 kB
51
51
  ℹ dist/operations/index.d.ts 0.16 kB │ gzip: 0.10 kB
52
52
  ℹ dist/handlers/index.d.ts 0.15 kB │ gzip: 0.09 kB
53
53
  ℹ dist/docs/index.d.ts 0.01 kB │ gzip: 0.03 kB
54
54
  ℹ dist/docs/locale-jurisdiction-gate.docblock.d.ts 0.01 kB │ gzip: 0.03 kB
55
- ℹ 46 files, total: 75.52 kB
56
- ✔ Build complete in 25267ms
55
+ ℹ 46 files, total: 75.65 kB
56
+ ✔ Build complete in 25973ms
@@ -1,7 +1,7 @@
1
1
  $ bun build:types && bun build:bundle
2
2
  $ tsc --noEmit
3
3
  $ tsdown
4
- ℹ tsdown v0.18.4 powered by rolldown v1.0.0-beta.57
4
+ ℹ tsdown v0.19.0 powered by rolldown v1.0.0-beta.59
5
5
  ℹ config file: /home/runner/work/contractspec/contractspec/packages/examples/locale-jurisdiction-gate/tsdown.config.js
6
6
  ℹ entry: src/events.ts, src/example.ts, src/index.ts, src/locale-jurisdiction-gate.feature.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/operations/assistant.ts, src/operations/index.ts, src/policy/guard.ts, src/policy/index.ts, src/policy/types.ts
7
7
  ℹ target: esnext
@@ -14,30 +14,30 @@ $ tsdown
14
14
  ℹ dist/policy/guard.js 1.90 kB │ gzip: 0.76 kB
15
15
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js 1.64 kB │ gzip: 0.74 kB
16
16
  ℹ dist/index.js 1.27 kB │ gzip: 0.40 kB
17
- ℹ dist/locale-jurisdiction-gate.feature.js 1.08 kB │ gzip: 0.46 kB
18
- ℹ dist/example.js 1.05 kB │ gzip: 0.55 kB
17
+ ℹ dist/locale-jurisdiction-gate.feature.js 1.16 kB │ gzip: 0.50 kB
18
+ ℹ dist/example.js 1.13 kB │ gzip: 0.58 kB
19
19
  ℹ dist/entities/index.js 0.36 kB │ gzip: 0.16 kB
20
20
  ℹ dist/operations/index.js 0.16 kB │ gzip: 0.10 kB
21
21
  ℹ dist/policy/index.js 0.15 kB │ gzip: 0.11 kB
22
22
  ℹ dist/handlers/index.js 0.11 kB │ gzip: 0.09 kB
23
23
  ℹ dist/docs/index.js 0.05 kB │ gzip: 0.07 kB
24
24
  ℹ dist/policy/types.js 0.00 kB │ gzip: 0.02 kB
25
- ℹ dist/handlers/demo.handlers.js.map 5.97 kB │ gzip: 1.81 kB
25
+ ℹ dist/handlers/demo.handlers.js.map 5.94 kB │ gzip: 1.81 kB
26
26
  ℹ dist/entities/models.js.map 5.85 kB │ gzip: 1.20 kB
27
27
  ℹ dist/operations/assistant.js.map 4.60 kB │ gzip: 1.41 kB
28
28
  ℹ dist/events.js.map 4.40 kB │ gzip: 0.93 kB
29
- ℹ dist/policy/guard.js.map 4.12 kB │ gzip: 1.44 kB
29
+ ℹ dist/policy/guard.js.map 4.08 kB │ gzip: 1.44 kB
30
30
  ℹ dist/docs/locale-jurisdiction-gate.docblock.js.map 2.16 kB │ gzip: 0.93 kB
31
- ℹ dist/locale-jurisdiction-gate.feature.js.map 1.73 kB │ gzip: 0.73 kB
32
- ℹ dist/example.js.map 1.61 kB │ gzip: 0.78 kB
31
+ ℹ dist/locale-jurisdiction-gate.feature.js.map 1.67 kB │ gzip: 0.72 kB
32
+ ℹ dist/example.js.map 1.60 kB │ gzip: 0.79 kB
33
33
  ℹ dist/entities/models.d.ts.map 0.91 kB │ gzip: 0.39 kB
34
34
  ℹ dist/policy/guard.d.ts.map 0.76 kB │ gzip: 0.39 kB
35
35
  ℹ dist/operations/assistant.d.ts.map 0.65 kB │ gzip: 0.28 kB
36
36
  ℹ dist/events.d.ts.map 0.57 kB │ gzip: 0.26 kB
37
37
  ℹ dist/handlers/demo.handlers.d.ts.map 0.45 kB │ gzip: 0.26 kB
38
38
  ℹ dist/policy/types.d.ts.map 0.25 kB │ gzip: 0.19 kB
39
- ℹ dist/locale-jurisdiction-gate.feature.d.ts.map 0.18 kB │ gzip: 0.14 kB
40
- ℹ dist/example.d.ts.map 0.12 kB │ gzip: 0.12 kB
39
+ ℹ dist/locale-jurisdiction-gate.feature.d.ts.map 0.19 kB │ gzip: 0.15 kB
40
+ ℹ dist/example.d.ts.map 0.14 kB │ gzip: 0.13 kB
41
41
  ℹ dist/operations/assistant.d.ts 7.28 kB │ gzip: 0.64 kB
42
42
  ℹ dist/entities/models.d.ts 5.48 kB │ gzip: 0.68 kB
43
43
  ℹ dist/events.d.ts 2.20 kB │ gzip: 0.38 kB
@@ -46,12 +46,12 @@ $ tsdown
46
46
  ℹ dist/policy/guard.d.ts 0.93 kB │ gzip: 0.42 kB
47
47
  ℹ dist/policy/types.d.ts 0.46 kB │ gzip: 0.31 kB
48
48
  ℹ dist/entities/index.d.ts 0.36 kB │ gzip: 0.16 kB
49
- ℹ dist/locale-jurisdiction-gate.feature.d.ts 0.30 kB │ gzip: 0.18 kB
49
+ ℹ dist/locale-jurisdiction-gate.feature.d.ts 0.34 kB │ gzip: 0.20 kB
50
50
  ℹ dist/policy/index.d.ts 0.26 kB │ gzip: 0.14 kB
51
- ℹ dist/example.d.ts 0.20 kB │ gzip: 0.16 kB
51
+ ℹ dist/example.d.ts 0.25 kB │ gzip: 0.17 kB
52
52
  ℹ dist/operations/index.d.ts 0.16 kB │ gzip: 0.10 kB
53
53
  ℹ dist/handlers/index.d.ts 0.15 kB │ gzip: 0.09 kB
54
54
  ℹ dist/docs/index.d.ts 0.01 kB │ gzip: 0.03 kB
55
55
  ℹ dist/docs/locale-jurisdiction-gate.docblock.d.ts 0.01 kB │ gzip: 0.03 kB
56
- ℹ 46 files, total: 75.52 kB
57
- ✔ Build complete in 26076ms
56
+ ℹ 46 files, total: 75.65 kB
57
+ ✔ Build complete in 26073ms
package/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # @contractspec/example.locale-jurisdiction-gate
2
2
 
3
+ ## 1.47.0
4
+
5
+ ### Minor Changes
6
+
7
+ - caf8701: feat: add cli vibe command to run workflow
8
+ - c69b849: feat: add api web services (mcp & website)
9
+ - 42b8d78: feat: add cli `contractspec vibe` workflow to simplify usage
10
+ - fd38e85: feat: auto-fix contractspec issues
11
+
12
+ ### Patch Changes
13
+
14
+ - e7ded36: feat: improve stability (adding ts-morph)
15
+ - c231a8b: test: improve workspace stability
16
+ - Updated dependencies [e7ded36]
17
+ - Updated dependencies [caf8701]
18
+ - Updated dependencies [c69b849]
19
+ - Updated dependencies [c231a8b]
20
+ - Updated dependencies [42b8d78]
21
+ - Updated dependencies [fd38e85]
22
+ - @contractspec/lib.contracts@1.47.0
23
+ - @contractspec/lib.schema@1.47.0
24
+
3
25
  ## 1.46.2
4
26
 
5
27
  ### Patch Changes
package/dist/example.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- import { ExampleSpec } from "@contractspec/lib.contracts";
1
+ import * as _contractspec_lib_contracts2 from "@contractspec/lib.contracts";
2
2
 
3
3
  //#region src/example.d.ts
4
- declare const example: ExampleSpec;
4
+ declare const example: _contractspec_lib_contracts2.ExampleSpec;
5
5
  //#endregion
6
6
  export { example as default };
7
7
  //# sourceMappingURL=example.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"example.d.ts","names":[],"sources":["../src/example.ts"],"sourcesContent":[],"mappings":";;;cAEM,SAAS"}
1
+ {"version":3,"file":"example.d.ts","names":[],"sources":["../src/example.ts"],"sourcesContent":[],"mappings":";;;cAEM,SA6BJ,4BAAA,CA7BW"}
package/dist/example.js CHANGED
@@ -1,5 +1,7 @@
1
+ import { defineExample } from "@contractspec/lib.contracts";
2
+
1
3
  //#region src/example.ts
2
- const example = {
4
+ const example = defineExample({
3
5
  meta: {
4
6
  key: "locale-jurisdiction-gate",
5
7
  version: "1.0.0",
@@ -37,7 +39,7 @@ const example = {
37
39
  },
38
40
  mcp: { enabled: true }
39
41
  }
40
- };
42
+ });
41
43
  var example_default = example;
42
44
 
43
45
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"example.js","names":["example: ExampleSpec"],"sources":["../src/example.ts"],"sourcesContent":["import type { ExampleSpec } from '@contractspec/lib.contracts';\n\nconst example: ExampleSpec = {\n meta: {\n key: 'locale-jurisdiction-gate',\n version: '1.0.0',\n title: 'Locale / Jurisdiction Gate',\n description:\n 'Fail-closed gating for assistant calls: locale + jurisdiction + kbSnapshotId + allowedScope must be explicit, answers must cite a snapshot.',\n kind: 'knowledge',\n visibility: 'public',\n stability: 'experimental',\n owners: ['@platform.core'],\n tags: ['policy', 'locale', 'jurisdiction', 'assistant', 'gating'],\n },\n docs: {\n rootDocId: 'docs.examples.locale-jurisdiction-gate',\n },\n entrypoints: {\n packageName: '@contractspec/example.locale-jurisdiction-gate',\n feature: './feature',\n contracts: './contracts',\n handlers: './handlers',\n docs: './docs',\n },\n surfaces: {\n templates: true,\n sandbox: { enabled: true, modes: ['markdown', 'specs'] },\n studio: { enabled: true, installable: true },\n mcp: { enabled: true },\n },\n};\n\nexport default example;\n"],"mappings":";AAEA,MAAMA,UAAuB;CAC3B,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,MAAM;EACN,YAAY;EACZ,WAAW;EACX,QAAQ,CAAC,iBAAiB;EAC1B,MAAM;GAAC;GAAU;GAAU;GAAgB;GAAa;GAAS;EAClE;CACD,MAAM,EACJ,WAAW,0CACZ;CACD,aAAa;EACX,aAAa;EACb,SAAS;EACT,WAAW;EACX,UAAU;EACV,MAAM;EACP;CACD,UAAU;EACR,WAAW;EACX,SAAS;GAAE,SAAS;GAAM,OAAO,CAAC,YAAY,QAAQ;GAAE;EACxD,QAAQ;GAAE,SAAS;GAAM,aAAa;GAAM;EAC5C,KAAK,EAAE,SAAS,MAAM;EACvB;CACF;AAED,sBAAe"}
1
+ {"version":3,"file":"example.js","names":[],"sources":["../src/example.ts"],"sourcesContent":["import { defineExample } from '@contractspec/lib.contracts';\n\nconst example = defineExample({\n meta: {\n key: 'locale-jurisdiction-gate',\n version: '1.0.0',\n title: 'Locale / Jurisdiction Gate',\n description:\n 'Fail-closed gating for assistant calls: locale + jurisdiction + kbSnapshotId + allowedScope must be explicit, answers must cite a snapshot.',\n kind: 'knowledge',\n visibility: 'public',\n stability: 'experimental',\n owners: ['@platform.core'],\n tags: ['policy', 'locale', 'jurisdiction', 'assistant', 'gating'],\n },\n docs: {\n rootDocId: 'docs.examples.locale-jurisdiction-gate',\n },\n entrypoints: {\n packageName: '@contractspec/example.locale-jurisdiction-gate',\n feature: './feature',\n contracts: './contracts',\n handlers: './handlers',\n docs: './docs',\n },\n surfaces: {\n templates: true,\n sandbox: { enabled: true, modes: ['markdown', 'specs'] },\n studio: { enabled: true, installable: true },\n mcp: { enabled: true },\n },\n});\n\nexport default example;\n"],"mappings":";;;AAEA,MAAM,UAAU,cAAc;CAC5B,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,MAAM;EACN,YAAY;EACZ,WAAW;EACX,QAAQ,CAAC,iBAAiB;EAC1B,MAAM;GAAC;GAAU;GAAU;GAAgB;GAAa;GAAS;EAClE;CACD,MAAM,EACJ,WAAW,0CACZ;CACD,aAAa;EACX,aAAa;EACb,SAAS;EACT,WAAW;EACX,UAAU;EACV,MAAM;EACP;CACD,UAAU;EACR,WAAW;EACX,SAAS;GAAE,SAAS;GAAM,OAAO,CAAC,YAAY,QAAQ;GAAE;EACxD,QAAQ;GAAE,SAAS;GAAM,aAAa;GAAM;EAC5C,KAAK,EAAE,SAAS,MAAM;EACvB;CACF,CAAC;AAEF,sBAAe"}
@@ -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 // 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"}
1
+ {"version":3,"file":"demo.handlers.js","names":[],"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,MAAM,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"}
@@ -1,7 +1,7 @@
1
- import { FeatureModuleSpec } from "@contractspec/lib.contracts";
1
+ import * as _contractspec_lib_contracts3 from "@contractspec/lib.contracts";
2
2
 
3
3
  //#region src/locale-jurisdiction-gate.feature.d.ts
4
- declare const LocaleJurisdictionGateFeature: FeatureModuleSpec;
4
+ declare const LocaleJurisdictionGateFeature: _contractspec_lib_contracts3.FeatureModuleSpec;
5
5
  //#endregion
6
6
  export { LocaleJurisdictionGateFeature };
7
7
  //# sourceMappingURL=locale-jurisdiction-gate.feature.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"locale-jurisdiction-gate.feature.d.ts","names":[],"sources":["../src/locale-jurisdiction-gate.feature.ts"],"sourcesContent":[],"mappings":";;;cAEa,+BAA+B"}
1
+ {"version":3,"file":"locale-jurisdiction-gate.feature.d.ts","names":[],"sources":["../src/locale-jurisdiction-gate.feature.ts"],"sourcesContent":[],"mappings":";;;cAEa,+BA2BX,4BAAA,CA3BwC"}
@@ -1,5 +1,7 @@
1
+ import { defineFeature } from "@contractspec/lib.contracts";
2
+
1
3
  //#region src/locale-jurisdiction-gate.feature.ts
2
- const LocaleJurisdictionGateFeature = {
4
+ const LocaleJurisdictionGateFeature = defineFeature({
3
5
  meta: {
4
6
  key: "locale-jurisdiction-gate",
5
7
  version: "1.0.0",
@@ -44,7 +46,7 @@ const LocaleJurisdictionGateFeature = {
44
46
  key: "knowledge",
45
47
  version: "1.0.0"
46
48
  }] }
47
- };
49
+ });
48
50
 
49
51
  //#endregion
50
52
  export { LocaleJurisdictionGateFeature };
@@ -1 +1 @@
1
- {"version":3,"file":"locale-jurisdiction-gate.feature.js","names":["LocaleJurisdictionGateFeature: FeatureModuleSpec"],"sources":["../src/locale-jurisdiction-gate.feature.ts"],"sourcesContent":["import type { FeatureModuleSpec } from '@contractspec/lib.contracts';\n\nexport const LocaleJurisdictionGateFeature: FeatureModuleSpec = {\n meta: {\n key: 'locale-jurisdiction-gate',\n version: '1.0.0',\n title: 'Locale + Jurisdiction Gate',\n description:\n 'Fail-closed gating for assistant calls requiring locale/jurisdiction/snapshot/scope and citations.',\n domain: 'knowledge',\n owners: ['@examples'],\n tags: ['assistant', 'policy', 'locale', 'jurisdiction', 'knowledge'],\n stability: 'experimental',\n },\n operations: [\n { key: 'assistant.answer', version: '1.0.0' },\n { key: 'assistant.explainConcept', version: '1.0.0' },\n ],\n events: [\n { key: 'assistant.answer.requested', version: '1.0.0' },\n { key: 'assistant.answer.blocked', version: '1.0.0' },\n { key: 'assistant.answer.delivered', version: '1.0.0' },\n ],\n presentations: [],\n opToPresentation: [],\n presentationsTargets: [],\n capabilities: {\n requires: [{ key: 'knowledge', version: '1.0.0' }],\n },\n};\n"],"mappings":";AAEA,MAAaA,gCAAmD;CAC9D,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,YAAY;EACrB,MAAM;GAAC;GAAa;GAAU;GAAU;GAAgB;GAAY;EACpE,WAAW;EACZ;CACD,YAAY,CACV;EAAE,KAAK;EAAoB,SAAS;EAAS,EAC7C;EAAE,KAAK;EAA4B,SAAS;EAAS,CACtD;CACD,QAAQ;EACN;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAA4B,SAAS;GAAS;EACrD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACxD;CACD,eAAe,EAAE;CACjB,kBAAkB,EAAE;CACpB,sBAAsB,EAAE;CACxB,cAAc,EACZ,UAAU,CAAC;EAAE,KAAK;EAAa,SAAS;EAAS,CAAC,EACnD;CACF"}
1
+ {"version":3,"file":"locale-jurisdiction-gate.feature.js","names":[],"sources":["../src/locale-jurisdiction-gate.feature.ts"],"sourcesContent":["import { defineFeature } from '@contractspec/lib.contracts';\n\nexport const LocaleJurisdictionGateFeature = defineFeature({\n meta: {\n key: 'locale-jurisdiction-gate',\n version: '1.0.0',\n title: 'Locale + Jurisdiction Gate',\n description:\n 'Fail-closed gating for assistant calls requiring locale/jurisdiction/snapshot/scope and citations.',\n domain: 'knowledge',\n owners: ['@examples'],\n tags: ['assistant', 'policy', 'locale', 'jurisdiction', 'knowledge'],\n stability: 'experimental',\n },\n operations: [\n { key: 'assistant.answer', version: '1.0.0' },\n { key: 'assistant.explainConcept', version: '1.0.0' },\n ],\n events: [\n { key: 'assistant.answer.requested', version: '1.0.0' },\n { key: 'assistant.answer.blocked', version: '1.0.0' },\n { key: 'assistant.answer.delivered', version: '1.0.0' },\n ],\n presentations: [],\n opToPresentation: [],\n presentationsTargets: [],\n capabilities: {\n requires: [{ key: 'knowledge', version: '1.0.0' }],\n },\n});\n"],"mappings":";;;AAEA,MAAa,gCAAgC,cAAc;CACzD,MAAM;EACJ,KAAK;EACL,SAAS;EACT,OAAO;EACP,aACE;EACF,QAAQ;EACR,QAAQ,CAAC,YAAY;EACrB,MAAM;GAAC;GAAa;GAAU;GAAU;GAAgB;GAAY;EACpE,WAAW;EACZ;CACD,YAAY,CACV;EAAE,KAAK;EAAoB,SAAS;EAAS,EAC7C;EAAE,KAAK;EAA4B,SAAS;EAAS,CACtD;CACD,QAAQ;EACN;GAAE,KAAK;GAA8B,SAAS;GAAS;EACvD;GAAE,KAAK;GAA4B,SAAS;GAAS;EACrD;GAAE,KAAK;GAA8B,SAAS;GAAS;EACxD;CACD,eAAe,EAAE;CACjB,kBAAkB,EAAE;CACpB,sBAAsB,EAAE;CACxB,cAAc,EACZ,UAAU,CAAC;EAAE,KAAK;EAAa,SAAS;EAAS,CAAC,EACnD;CACF,CAAC"}
@@ -1,8 +1,8 @@
1
- import * as _contractspec_lib_contracts2 from "@contractspec/lib.contracts";
1
+ import * as _contractspec_lib_contracts4 from "@contractspec/lib.contracts";
2
2
  import * as _contractspec_lib_schema63 from "@contractspec/lib.schema";
3
3
 
4
4
  //#region src/operations/assistant.d.ts
5
- declare const AssistantAnswerContract: _contractspec_lib_contracts2.OperationSpec<_contractspec_lib_schema63.SchemaModel<{
5
+ declare const AssistantAnswerContract: _contractspec_lib_contracts4.OperationSpec<_contractspec_lib_schema63.SchemaModel<{
6
6
  envelope: {
7
7
  type: _contractspec_lib_schema63.SchemaModel<{
8
8
  traceId: {
@@ -121,7 +121,7 @@ declare const AssistantAnswerContract: _contractspec_lib_contracts2.OperationSpe
121
121
  isOptional: true;
122
122
  };
123
123
  }>, undefined>;
124
- declare const AssistantExplainConceptContract: _contractspec_lib_contracts2.OperationSpec<_contractspec_lib_schema63.SchemaModel<{
124
+ declare const AssistantExplainConceptContract: _contractspec_lib_contracts4.OperationSpec<_contractspec_lib_schema63.SchemaModel<{
125
125
  envelope: {
126
126
  type: _contractspec_lib_schema63.SchemaModel<{
127
127
  traceId: {
@@ -1 +1 @@
1
- {"version":3,"file":"guard.js","names":["EDUCATION_ONLY_FORBIDDEN_PATTERNS: RegExp[]"],"sources":["../../src/policy/guard.ts"],"sourcesContent":["import type { GateError, GateResult } from './types';\n\ninterface EnvelopeLike {\n locale?: string;\n kbSnapshotId?: string;\n allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';\n regulatoryContext?: { jurisdiction?: string };\n}\n\ninterface AnswerLike {\n citations?: unknown[];\n sections?: { heading: string; body: string }[];\n refused?: boolean;\n refusalReason?: string;\n allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';\n}\n\nconst SUPPORTED_LOCALES = new Set<string>(['en-US', 'en-GB', 'fr-FR']);\n\nfunction err(code: GateError['code'], message: string): GateError {\n return { code, message };\n}\n\nexport function validateEnvelope(\n envelope: EnvelopeLike\n): GateResult<Required<EnvelopeLike>> {\n if (!envelope.locale || !SUPPORTED_LOCALES.has(envelope.locale)) {\n return {\n ok: false,\n error: err('LOCALE_REQUIRED', 'locale is required and must be supported'),\n };\n }\n if (!envelope.regulatoryContext?.jurisdiction) {\n return {\n ok: false,\n error: err('JURISDICTION_REQUIRED', 'jurisdiction is required'),\n };\n }\n if (!envelope.kbSnapshotId) {\n return {\n ok: false,\n error: err('KB_SNAPSHOT_REQUIRED', 'kbSnapshotId is required'),\n };\n }\n if (!envelope.allowedScope) {\n return {\n ok: false,\n error: err('SCOPE_VIOLATION', 'allowedScope is required'),\n };\n }\n return { ok: true, value: envelope as Required<EnvelopeLike> };\n}\n\nexport function enforceCitations(answer: AnswerLike): GateResult<AnswerLike> {\n const citations = answer.citations ?? [];\n if (!Array.isArray(citations) || citations.length === 0) {\n return {\n ok: false,\n error: err(\n 'CITATIONS_REQUIRED',\n 'answers must include at least one citation'\n ),\n };\n }\n return { ok: true, value: answer };\n}\n\nconst EDUCATION_ONLY_FORBIDDEN_PATTERNS: RegExp[] = [\n /\\b(buy|sell)\\b/i,\n /\\b(should\\s+buy|should\\s+sell)\\b/i,\n /\\b(guarantee(d)?|promise(d)?)\\b/i,\n];\n\nexport function enforceAllowedScope(\n allowedScope: EnvelopeLike['allowedScope'],\n answer: AnswerLike\n): GateResult<AnswerLike> {\n if (!allowedScope) {\n return {\n ok: false,\n error: err('SCOPE_VIOLATION', 'allowedScope is required'),\n };\n }\n if (allowedScope !== 'education_only') {\n return { ok: true, value: answer };\n }\n\n const bodies = (answer.sections ?? []).map((s) => s.body).join('\\n');\n const violations = EDUCATION_ONLY_FORBIDDEN_PATTERNS.some((re) =>\n re.test(bodies)\n );\n if (violations) {\n return {\n ok: false,\n error: err(\n 'SCOPE_VIOLATION',\n 'answer violates education_only scope (contains actionable or promotional language)'\n ),\n };\n }\n return { ok: true, value: answer };\n}\n"],"mappings":";AAiBA,MAAM,oBAAoB,IAAI,IAAY;CAAC;CAAS;CAAS;CAAQ,CAAC;AAEtE,SAAS,IAAI,MAAyB,SAA4B;AAChE,QAAO;EAAE;EAAM;EAAS;;AAG1B,SAAgB,iBACd,UACoC;AACpC,KAAI,CAAC,SAAS,UAAU,CAAC,kBAAkB,IAAI,SAAS,OAAO,CAC7D,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2CAA2C;EAC1E;AAEH,KAAI,CAAC,SAAS,mBAAmB,aAC/B,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,yBAAyB,2BAA2B;EAChE;AAEH,KAAI,CAAC,SAAS,aACZ,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,wBAAwB,2BAA2B;EAC/D;AAEH,KAAI,CAAC,SAAS,aACZ,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2BAA2B;EAC1D;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAoC;;AAGhE,SAAgB,iBAAiB,QAA4C;CAC3E,MAAM,YAAY,OAAO,aAAa,EAAE;AACxC,KAAI,CAAC,MAAM,QAAQ,UAAU,IAAI,UAAU,WAAW,EACpD,QAAO;EACL,IAAI;EACJ,OAAO,IACL,sBACA,6CACD;EACF;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ;;AAGpC,MAAMA,oCAA8C;CAClD;CACA;CACA;CACD;AAED,SAAgB,oBACd,cACA,QACwB;AACxB,KAAI,CAAC,aACH,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2BAA2B;EAC1D;AAEH,KAAI,iBAAiB,iBACnB,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ;CAGpC,MAAM,UAAU,OAAO,YAAY,EAAE,EAAE,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK;AAIpE,KAHmB,kCAAkC,MAAM,OACzD,GAAG,KAAK,OAAO,CAChB,CAEC,QAAO;EACL,IAAI;EACJ,OAAO,IACL,mBACA,qFACD;EACF;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ"}
1
+ {"version":3,"file":"guard.js","names":[],"sources":["../../src/policy/guard.ts"],"sourcesContent":["import type { GateError, GateResult } from './types';\n\ninterface EnvelopeLike {\n locale?: string;\n kbSnapshotId?: string;\n allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';\n regulatoryContext?: { jurisdiction?: string };\n}\n\ninterface AnswerLike {\n citations?: unknown[];\n sections?: { heading: string; body: string }[];\n refused?: boolean;\n refusalReason?: string;\n allowedScope?: 'education_only' | 'generic_info' | 'escalation_required';\n}\n\nconst SUPPORTED_LOCALES = new Set<string>(['en-US', 'en-GB', 'fr-FR']);\n\nfunction err(code: GateError['code'], message: string): GateError {\n return { code, message };\n}\n\nexport function validateEnvelope(\n envelope: EnvelopeLike\n): GateResult<Required<EnvelopeLike>> {\n if (!envelope.locale || !SUPPORTED_LOCALES.has(envelope.locale)) {\n return {\n ok: false,\n error: err('LOCALE_REQUIRED', 'locale is required and must be supported'),\n };\n }\n if (!envelope.regulatoryContext?.jurisdiction) {\n return {\n ok: false,\n error: err('JURISDICTION_REQUIRED', 'jurisdiction is required'),\n };\n }\n if (!envelope.kbSnapshotId) {\n return {\n ok: false,\n error: err('KB_SNAPSHOT_REQUIRED', 'kbSnapshotId is required'),\n };\n }\n if (!envelope.allowedScope) {\n return {\n ok: false,\n error: err('SCOPE_VIOLATION', 'allowedScope is required'),\n };\n }\n return { ok: true, value: envelope as Required<EnvelopeLike> };\n}\n\nexport function enforceCitations(answer: AnswerLike): GateResult<AnswerLike> {\n const citations = answer.citations ?? [];\n if (!Array.isArray(citations) || citations.length === 0) {\n return {\n ok: false,\n error: err(\n 'CITATIONS_REQUIRED',\n 'answers must include at least one citation'\n ),\n };\n }\n return { ok: true, value: answer };\n}\n\nconst EDUCATION_ONLY_FORBIDDEN_PATTERNS: RegExp[] = [\n /\\b(buy|sell)\\b/i,\n /\\b(should\\s+buy|should\\s+sell)\\b/i,\n /\\b(guarantee(d)?|promise(d)?)\\b/i,\n];\n\nexport function enforceAllowedScope(\n allowedScope: EnvelopeLike['allowedScope'],\n answer: AnswerLike\n): GateResult<AnswerLike> {\n if (!allowedScope) {\n return {\n ok: false,\n error: err('SCOPE_VIOLATION', 'allowedScope is required'),\n };\n }\n if (allowedScope !== 'education_only') {\n return { ok: true, value: answer };\n }\n\n const bodies = (answer.sections ?? []).map((s) => s.body).join('\\n');\n const violations = EDUCATION_ONLY_FORBIDDEN_PATTERNS.some((re) =>\n re.test(bodies)\n );\n if (violations) {\n return {\n ok: false,\n error: err(\n 'SCOPE_VIOLATION',\n 'answer violates education_only scope (contains actionable or promotional language)'\n ),\n };\n }\n return { ok: true, value: answer };\n}\n"],"mappings":";AAiBA,MAAM,oBAAoB,IAAI,IAAY;CAAC;CAAS;CAAS;CAAQ,CAAC;AAEtE,SAAS,IAAI,MAAyB,SAA4B;AAChE,QAAO;EAAE;EAAM;EAAS;;AAG1B,SAAgB,iBACd,UACoC;AACpC,KAAI,CAAC,SAAS,UAAU,CAAC,kBAAkB,IAAI,SAAS,OAAO,CAC7D,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2CAA2C;EAC1E;AAEH,KAAI,CAAC,SAAS,mBAAmB,aAC/B,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,yBAAyB,2BAA2B;EAChE;AAEH,KAAI,CAAC,SAAS,aACZ,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,wBAAwB,2BAA2B;EAC/D;AAEH,KAAI,CAAC,SAAS,aACZ,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2BAA2B;EAC1D;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAoC;;AAGhE,SAAgB,iBAAiB,QAA4C;CAC3E,MAAM,YAAY,OAAO,aAAa,EAAE;AACxC,KAAI,CAAC,MAAM,QAAQ,UAAU,IAAI,UAAU,WAAW,EACpD,QAAO;EACL,IAAI;EACJ,OAAO,IACL,sBACA,6CACD;EACF;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ;;AAGpC,MAAM,oCAA8C;CAClD;CACA;CACA;CACD;AAED,SAAgB,oBACd,cACA,QACwB;AACxB,KAAI,CAAC,aACH,QAAO;EACL,IAAI;EACJ,OAAO,IAAI,mBAAmB,2BAA2B;EAC1D;AAEH,KAAI,iBAAiB,iBACnB,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ;CAGpC,MAAM,UAAU,OAAO,YAAY,EAAE,EAAE,KAAK,MAAM,EAAE,KAAK,CAAC,KAAK,KAAK;AAIpE,KAHmB,kCAAkC,MAAM,OACzD,GAAG,KAAK,OAAO,CAChB,CAEC,QAAO;EACL,IAAI;EACJ,OAAO,IACL,mBACA,qFACD;EACF;AAEH,QAAO;EAAE,IAAI;EAAM,OAAO;EAAQ"}
package/package.json CHANGED
@@ -1,10 +1,8 @@
1
1
  {
2
2
  "name": "@contractspec/example.locale-jurisdiction-gate",
3
- "version": "1.46.2",
3
+ "version": "1.47.0",
4
4
  "description": "Example: enforce locale + jurisdiction + kbSnapshotId + allowed scope for assistant calls (fail-closed).",
5
5
  "type": "module",
6
- "main": "./dist/index.js",
7
- "module": "./dist/index.js",
8
6
  "types": "./dist/index.d.ts",
9
7
  "exports": {
10
8
  ".": "./dist/index.js",
@@ -38,13 +36,13 @@
38
36
  "test": "bun test"
39
37
  },
40
38
  "dependencies": {
41
- "@contractspec/lib.contracts": "1.46.2",
42
- "@contractspec/lib.schema": "1.46.2"
39
+ "@contractspec/lib.contracts": "1.47.0",
40
+ "@contractspec/lib.schema": "1.47.0"
43
41
  },
44
42
  "devDependencies": {
45
- "@contractspec/tool.tsdown": "1.46.2",
46
- "@contractspec/tool.typescript": "1.46.2",
47
- "tsdown": "^0.18.3",
43
+ "@contractspec/tool.tsdown": "1.47.0",
44
+ "@contractspec/tool.typescript": "1.47.0",
45
+ "tsdown": "^0.19.0",
48
46
  "typescript": "^5.9.3"
49
47
  },
50
48
  "publishConfig": {
package/src/example.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { ExampleSpec } from '@contractspec/lib.contracts';
1
+ import { defineExample } from '@contractspec/lib.contracts';
2
2
 
3
- const example: ExampleSpec = {
3
+ const example = defineExample({
4
4
  meta: {
5
5
  key: 'locale-jurisdiction-gate',
6
6
  version: '1.0.0',
@@ -29,6 +29,6 @@ const example: ExampleSpec = {
29
29
  studio: { enabled: true, installable: true },
30
30
  mcp: { enabled: true },
31
31
  },
32
- };
32
+ });
33
33
 
34
34
  export default example;
@@ -1,6 +1,6 @@
1
- import type { FeatureModuleSpec } from '@contractspec/lib.contracts';
1
+ import { defineFeature } from '@contractspec/lib.contracts';
2
2
 
3
- export const LocaleJurisdictionGateFeature: FeatureModuleSpec = {
3
+ export const LocaleJurisdictionGateFeature = defineFeature({
4
4
  meta: {
5
5
  key: 'locale-jurisdiction-gate',
6
6
  version: '1.0.0',
@@ -27,4 +27,4 @@ export const LocaleJurisdictionGateFeature: FeatureModuleSpec = {
27
27
  capabilities: {
28
28
  requires: [{ key: 'knowledge', version: '1.0.0' }],
29
29
  },
30
- };
30
+ });