@zanii/walls 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -38,6 +38,7 @@ classifier for higher assurance. `wallManifestHash` is order-independent (stable
38
38
 
39
39
  ## Changelog
40
40
 
41
+ - **0.1.3** — Presets for CBUAE, VARA, DoH, DHA, SDAIA, SAMA, CMA, ADEK/KHDA, UK FCA Consumer Duty, SEC Marketing Rule and FINRA; defineWall builder; Arabic-aware output checks with normalised spelling; drift between evaluation runs; signed wall certificates.
41
42
  - **0.1.2** — now depends on `@zanii/core` 0.5 (protocol 1.2), so it shares one core with `@zanii/sdk` 0.5 instead of pulling in a second, older copy. No API change.
42
43
  - **0.1.0** — initial release: `WALLS` (sca-trading, rera, tdra, legal, consumer, difc, adgm), `wallPolicy`, `wallManifestHash`, `checkOutput`, `buildEvalReceipt`.
43
44
 
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Keeping walls standing: a builder for any regulated vertical, Arabic-aware output checks
3
+ * (Gulf dialects, normalised spelling), drift between evaluation runs and a signed wall
4
+ * certificate for a period. Evaluation cases are yours; nothing here ships test content.
5
+ */
6
+ import { type SignedObject } from '@zanii/core';
7
+ import { type OutputCheck, type Wall } from './index.js';
8
+ /**
9
+ * Define a wall for any vertical. Rejects ids that are not slugs and granted scopes a deny
10
+ * swallows whole (a grant that can never be used). Carve-outs, a broad grant with a narrower
11
+ * deny inside it, are fine: the deny wins.
12
+ */
13
+ export declare function defineWall(w: Wall): Wall & {
14
+ manifest_hash: string;
15
+ };
16
+ /** Normalise Arabic for matching: strip diacritics and tatweel, unify alef, ta marbuta and alef maqsura forms. */
17
+ export declare function normaliseArabic(text: string): string;
18
+ /** Arabic (MSA and Gulf) phrases for the investment walls: the same "never advise" rule in the languages customers use. */
19
+ export declare const ARABIC_FORBIDDEN: Record<string, string[]>;
20
+ /** `checkOutput` plus normalised Arabic phrases for the wall (from `ARABIC_FORBIDDEN` or your own list). */
21
+ export declare function checkOutputMultilingual(wall: Wall, text: string, arabic?: string[]): OutputCheck;
22
+ /**
23
+ * Run your evaluation outputs through the wall and compare with the previous run: a lower pass
24
+ * rate, or a case that passed before and fails now, is drift.
25
+ */
26
+ export declare function wallDrift(wall: Wall, outputs: Array<{
27
+ id: string;
28
+ text: string;
29
+ }>, previous?: {
30
+ passRate: number;
31
+ failing: string[];
32
+ }): {
33
+ wall: string;
34
+ manifest_hash: string;
35
+ cases: number;
36
+ passRate: number;
37
+ failing: string[];
38
+ regressions: string[];
39
+ drifted: boolean;
40
+ };
41
+ export type WallCertificate = SignedObject<{
42
+ v: 1;
43
+ type: 'wall.certificate';
44
+ wall: string;
45
+ regulator: string;
46
+ manifest_hash: string;
47
+ from: string;
48
+ to: string;
49
+ runs: number;
50
+ cases: number;
51
+ failures: number;
52
+ ts: string;
53
+ }>;
54
+ /** A signed statement for a regulator: the wall's manifest held for the period, with the evaluation totals. */
55
+ export declare function wallCertificate(wall: Wall, input: {
56
+ from: string;
57
+ to: string;
58
+ runs: Array<{
59
+ cases: number;
60
+ failing: string[];
61
+ }>;
62
+ ts?: string;
63
+ }, privateKey: Uint8Array): WallCertificate;
64
+ /** Signed, and the wall's current manifest is the one certified. */
65
+ export declare function verifyWallCertificate(c: WallCertificate, wall: Wall, trustedSigners?: string[]): boolean;
66
+ //# sourceMappingURL=assurance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assurance.d.ts","sourceRoot":"","sources":["../src/assurance.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAA+C,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAiC,KAAK,WAAW,EAAE,KAAK,IAAI,EAAE,MAAM,YAAY,CAAC;AAExF;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,CAAC,EAAE,IAAI,GAAG,IAAI,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAMpE;AAED,kHAAkH;AAClH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAMpD;AAED,2HAA2H;AAC3H,eAAO,MAAM,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAIrD,CAAC;AAEF,4GAA4G;AAC5G,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,EAAoC,GAAG,WAAW,CAKjI;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,QAAQ,CAAC,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAA;CAAE;;;;;;;;EAKrI;AAED,MAAM,MAAM,eAAe,GAAG,YAAY,CAAC;IAAE,CAAC,EAAE,CAAC,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AAE5N,+GAA+G;AAC/G,wBAAgB,eAAe,CAAC,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,KAAK,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAAC,EAAE,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,UAAU,EAAE,UAAU,GAAG,eAAe,CAKxL;AAED,oEAAoE;AACpE,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAExG"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Keeping walls standing: a builder for any regulated vertical, Arabic-aware output checks
3
+ * (Gulf dialects, normalised spelling), drift between evaluation runs and a signed wall
4
+ * certificate for a period. Evaluation cases are yours; nothing here ships test content.
5
+ */
6
+ import { scopeCovers, signObject, verifySignedObject } from '@zanii/core';
7
+ import { checkOutput, wallManifestHash } from './index.js';
8
+ /**
9
+ * Define a wall for any vertical. Rejects ids that are not slugs and granted scopes a deny
10
+ * swallows whole (a grant that can never be used). Carve-outs, a broad grant with a narrower
11
+ * deny inside it, are fine: the deny wins.
12
+ */
13
+ export function defineWall(w) {
14
+ if (!/^[a-z0-9-]{3,48}$/.test(w.id))
15
+ throw new Error('walls: id must be a lower-case slug');
16
+ if (!w.regulator || w.denies.length === 0)
17
+ throw new Error('walls: a wall needs a regulator and at least one denied scope');
18
+ const clash = w.scopes.filter((s) => w.denies.some((d) => scopeCovers(d, s)));
19
+ if (clash.length)
20
+ throw new Error(`walls: granted scopes fall entirely inside the wall: ${clash.join(', ')}`);
21
+ return { ...w, forbidden: w.forbidden.map((p) => p.toLowerCase()), manifest_hash: wallManifestHash(w) };
22
+ }
23
+ /** Normalise Arabic for matching: strip diacritics and tatweel, unify alef, ta marbuta and alef maqsura forms. */
24
+ export function normaliseArabic(text) {
25
+ return text
26
+ .replace(/[ً-ْٰـ]/g, '')
27
+ .replace(/[آأإ]/g, 'ا')
28
+ .replace(/ة/g, 'ه')
29
+ .replace(/ى/g, 'ي');
30
+ }
31
+ /** Arabic (MSA and Gulf) phrases for the investment walls: the same "never advise" rule in the languages customers use. */
32
+ export const ARABIC_FORBIDDEN = {
33
+ 'sca-trading': ['اشتري هذا', 'بيع هذا', 'ربح مضمون', 'عائد مضمون', 'لازم تشتري', 'انصحك تشتري', 'اشتريه الحين'],
34
+ 'cma-ksa': ['اشتري هذا', 'بيع هذا', 'ربح مضمون', 'عائد مضمون', 'لازم تشتري'],
35
+ 'vara-marketing': ['ربح مضمون', 'عائد مضمون', 'بدون مخاطر', 'ما تخسر'],
36
+ };
37
+ /** `checkOutput` plus normalised Arabic phrases for the wall (from `ARABIC_FORBIDDEN` or your own list). */
38
+ export function checkOutputMultilingual(wall, text, arabic = ARABIC_FORBIDDEN[wall.id] ?? []) {
39
+ const base = checkOutput(wall, text);
40
+ const norm = normaliseArabic(text);
41
+ const ar = arabic.filter((p) => norm.includes(normaliseArabic(p)));
42
+ return { ok: base.ok && ar.length === 0, violations: [...base.violations, ...ar] };
43
+ }
44
+ /**
45
+ * Run your evaluation outputs through the wall and compare with the previous run: a lower pass
46
+ * rate, or a case that passed before and fails now, is drift.
47
+ */
48
+ export function wallDrift(wall, outputs, previous) {
49
+ const failing = outputs.filter((o) => !checkOutputMultilingual(wall, o.text).ok).map((o) => o.id);
50
+ const passRate = outputs.length ? Math.round(((outputs.length - failing.length) / outputs.length) * 1000) / 1000 : 1;
51
+ const regressions = previous ? failing.filter((id) => !previous.failing.includes(id)) : [];
52
+ return { wall: wall.id, manifest_hash: wallManifestHash(wall), cases: outputs.length, passRate, failing, regressions, drifted: !!previous && (passRate < previous.passRate || regressions.length > 0) };
53
+ }
54
+ /** A signed statement for a regulator: the wall's manifest held for the period, with the evaluation totals. */
55
+ export function wallCertificate(wall, input, privateKey) {
56
+ return signObject({
57
+ v: 1, type: 'wall.certificate', wall: wall.id, regulator: wall.regulator, manifest_hash: wallManifestHash(wall), from: input.from, to: input.to,
58
+ runs: input.runs.length, cases: input.runs.reduce((s, r) => s + r.cases, 0), failures: input.runs.reduce((s, r) => s + r.failing.length, 0), ts: input.ts ?? new Date().toISOString(),
59
+ }, privateKey);
60
+ }
61
+ /** Signed, and the wall's current manifest is the one certified. */
62
+ export function verifyWallCertificate(c, wall, trustedSigners) {
63
+ return verifySignedObject(c) && c.manifest_hash === wallManifestHash(wall) && (!trustedSigners || trustedSigners.includes(c.signer));
64
+ }
65
+ //# sourceMappingURL=assurance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"assurance.js","sourceRoot":"","sources":["../src/assurance.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,kBAAkB,EAAqB,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAA+B,MAAM,YAAY,CAAC;AAExF;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,CAAO;IAChC,IAAI,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;IAC5F,IAAI,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IAC5H,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9E,IAAI,KAAK,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,wDAAwD,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC9G,OAAO,EAAE,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAC;AAC1G,CAAC;AAED,kHAAkH;AAClH,MAAM,UAAU,eAAe,CAAC,IAAY;IAC1C,OAAO,IAAI;SACR,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;SACtB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;SAClB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;AACxB,CAAC;AAED,2HAA2H;AAC3H,MAAM,CAAC,MAAM,gBAAgB,GAA6B;IACxD,aAAa,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,aAAa,EAAE,cAAc,CAAC;IAC/G,SAAS,EAAE,CAAC,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,CAAC;IAC5E,gBAAgB,EAAE,CAAC,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,SAAS,CAAC;CACvE,CAAC;AAEF,4GAA4G;AAC5G,MAAM,UAAU,uBAAuB,CAAC,IAAU,EAAE,IAAY,EAAE,SAAmB,gBAAgB,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE;IAClH,MAAM,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,EAAE,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC,GAAG,IAAI,CAAC,UAAU,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AACrF,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAU,EAAE,OAA4C,EAAE,QAAkD;IACpI,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,uBAAuB,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAClG,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACrH,MAAM,WAAW,GAAG,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC3F,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,aAAa,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,OAAO,EAAE,CAAC,CAAC,QAAQ,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC,QAAQ,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;AAC1M,CAAC;AAID,+GAA+G;AAC/G,MAAM,UAAU,eAAe,CAAC,IAAU,EAAE,KAAmG,EAAE,UAAsB;IACrK,OAAO,UAAU,CAAC;QAChB,CAAC,EAAE,CAAU,EAAE,IAAI,EAAE,kBAA2B,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,aAAa,EAAE,gBAAgB,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE;QACjK,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACtL,EAAE,UAAU,CAAC,CAAC;AACjB,CAAC;AAED,oEAAoE;AACpE,MAAM,UAAU,qBAAqB,CAAC,CAAkB,EAAE,IAAU,EAAE,cAAyB;IAC7F,OAAO,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,KAAK,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,cAAc,IAAI,cAAc,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;AACvI,CAAC"}
package/dist/index.d.ts CHANGED
@@ -36,4 +36,5 @@ export declare function buildEvalReceipt(wall: Wall, results: {
36
36
  target: string;
37
37
  payload: Record<string, unknown>;
38
38
  };
39
+ export * from './assurance.js';
39
40
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oFAAoF;IACpF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CAgDtC,CAAC;AAEF,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,CAE5H;AAED,6GAA6G;AAC7G,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEnD;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAIjE;AAED,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAS9J"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,IAAI;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,iEAAiE;IACjE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,oFAAoF;IACpF,SAAS,EAAE,MAAM,EAAE,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,eAAO,MAAM,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,IAAI,CA8HtC,CAAC;AAEF,sGAAsG;AACtG,wBAAgB,UAAU,CAAC,IAAI,EAAE,IAAI,GAAG;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAA;CAAE,CAE5H;AAED,6GAA6G;AAC7G,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,CAEnD;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAED,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,CAIjE;AAED,+FAA+F;AAC/F,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAS9J;AACD,cAAc,gBAAgB,CAAC"}
package/dist/index.js CHANGED
@@ -59,6 +59,84 @@ export const WALLS = {
59
59
  scopes: ['data.process.adgm.*'], denies: ['data.export.nonadequate.*'], forbidden: [],
60
60
  note: 'ADGM free-zone data protection; select per deployment (not federal PDPL)',
61
61
  },
62
+ // Further presets: starting points for each regulator's rules; confirm scope and wording with counsel.
63
+ 'cbuae-consumer': {
64
+ id: 'cbuae-consumer', regulator: 'CBUAE (Consumer Protection)',
65
+ scopes: ['banking.inform.*', 'banking.service.*'],
66
+ denies: ['banking.credit.decide.*', 'banking.product.push.*'],
67
+ forbidden: ['you are pre-approved', 'no risk at all', 'limited time only, sign now', 'hidden fees do not apply'],
68
+ note: 'informs and services; credit decisions stay with a person; no pressure selling; disclose fees',
69
+ },
70
+ 'vara-marketing': {
71
+ id: 'vara-marketing', regulator: 'VARA (Dubai)',
72
+ scopes: ['va.education.*', 'va.market.read.*'],
73
+ denies: ['va.advise.*', 'va.execute.*', 'va.promote.unlicensed.*'],
74
+ forbidden: ['guaranteed return', 'guaranteed profit', 'risk-free', 'cannot lose', 'buy this token', 'to the moon'],
75
+ note: 'virtual-asset marketing must be fair and carry risk disclaimers; no advice or execution without a licence',
76
+ },
77
+ 'doh-health': {
78
+ id: 'doh-health', regulator: 'DoH Abu Dhabi',
79
+ scopes: ['health.inform.*', 'health.triage.assist.*'],
80
+ denies: ['health.diagnose.*', 'health.prescribe.*'],
81
+ forbidden: ['you have', 'your diagnosis is', 'take this medication', 'no need to see a doctor'],
82
+ note: 'assists clinicians and informs patients; never diagnoses or prescribes; a licensed professional decides',
83
+ },
84
+ 'dha-health': {
85
+ id: 'dha-health', regulator: 'DHA (Dubai)',
86
+ scopes: ['health.inform.*', 'health.triage.assist.*'],
87
+ denies: ['health.diagnose.*', 'health.prescribe.*'],
88
+ forbidden: ['your diagnosis is', 'take this medication', 'no need to see a doctor'],
89
+ note: 'assists, never replaces, the licensed clinician',
90
+ },
91
+ 'sdaia-ethics': {
92
+ id: 'sdaia-ethics', regulator: 'SDAIA (KSA AI Ethics Principles)',
93
+ scopes: ['ai.assist.*'],
94
+ denies: ['ai.profile.sensitive.*', 'ai.decide.unreviewed.*'],
95
+ forbidden: [],
96
+ note: 'fairness, privacy, transparency and human oversight; no sensitive profiling; decisions reviewable',
97
+ },
98
+ 'sama-banking': {
99
+ id: 'sama-banking', regulator: 'SAMA',
100
+ scopes: ['banking.inform.*', 'banking.service.*'],
101
+ denies: ['banking.credit.decide.*', 'banking.data.share.unconsented.*'],
102
+ forbidden: ['you are pre-approved', 'no risk at all'],
103
+ note: 'consumer protection for bank customers; consented data sharing only',
104
+ },
105
+ 'cma-ksa': {
106
+ id: 'cma-ksa', regulator: 'CMA (KSA)',
107
+ scopes: ['securities.education.*', 'market.read.*'],
108
+ denies: ['securities.advise.*', 'securities.execute.*'],
109
+ forbidden: ['buy this', 'sell this', 'guaranteed return', 'guaranteed profit'],
110
+ note: 'education only; securities advice and dealing are authorised activities',
111
+ },
112
+ 'adek-khda-education': {
113
+ id: 'adek-khda-education', regulator: 'ADEK / KHDA',
114
+ scopes: ['education.tutor.*', 'education.inform.*'],
115
+ denies: ['education.grade.final.*', 'education.profile.minor.*'],
116
+ forbidden: ['i will write your exam', 'submit this as your own'],
117
+ note: 'tutors and informs; teachers decide final grades; no profiling of minors',
118
+ },
119
+ 'fca-consumer-duty': {
120
+ id: 'fca-consumer-duty', regulator: 'UK FCA (Consumer Duty)',
121
+ scopes: ['finance.inform.*', 'finance.service.*'],
122
+ denies: ['finance.advise.unregulated.*', 'finance.sludge.*'],
123
+ forbidden: ['no risk at all', 'act now or lose out', 'guaranteed return'],
124
+ note: 'good outcomes for retail customers: fair value, understanding, support, no sludge',
125
+ },
126
+ 'sec-marketing': {
127
+ id: 'sec-marketing', regulator: 'US SEC (Marketing Rule 206(4)-1)',
128
+ scopes: ['adviser.marketing.*'],
129
+ denies: ['adviser.marketing.testimonial.undisclosed.*', 'adviser.marketing.hypothetical.unsupported.*'],
130
+ forbidden: ['guaranteed return', 'guaranteed profit', 'cannot lose', 'past performance guarantees'],
131
+ note: 'no untrue or misleading statements; performance shown fairly with required disclosures',
132
+ },
133
+ 'finra-genai': {
134
+ id: 'finra-genai', regulator: 'FINRA (Rule 2210, gen AI guidance)',
135
+ scopes: ['broker.communications.*'],
136
+ denies: ['broker.communications.unreviewed.*'],
137
+ forbidden: ['guaranteed return', 'risk-free', 'cannot lose'],
138
+ note: 'communications fair and balanced; supervision and record-keeping apply to AI-generated content',
139
+ },
62
140
  };
63
141
  /** A `@zanii/policy` config that denies everything the wall forbids. Pass to `createPolicyEngine`. */
64
142
  export function wallPolicy(wall) {
@@ -85,4 +163,5 @@ export function buildEvalReceipt(wall, results) {
85
163
  },
86
164
  };
87
165
  }
166
+ export * from './assurance.js';
88
167
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zanii/walls",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "UAE vertical 'wall' presets as enforceable, auditable artifacts - scopes never granted + a policy config + a manifest_hash + a receipted eval. SCA trading ('education only, never buy this'), RERA, TDRA, Legal, Consumer, DIFC/ADGM.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ledger.zanii.agency",
@@ -31,7 +31,7 @@
31
31
  "vitest": "^3.0.9"
32
32
  },
33
33
  "dependencies": {
34
- "@zanii/core": "^0.5.2"
34
+ "@zanii/core": "^0.5.4"
35
35
  },
36
36
  "scripts": {
37
37
  "build": "tsc -p tsconfig.build.json",
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Keeping walls standing: a builder for any regulated vertical, Arabic-aware output checks
3
+ * (Gulf dialects, normalised spelling), drift between evaluation runs and a signed wall
4
+ * certificate for a period. Evaluation cases are yours; nothing here ships test content.
5
+ */
6
+ import { scopeCovers, signObject, verifySignedObject, type SignedObject } from '@zanii/core';
7
+ import { checkOutput, wallManifestHash, type OutputCheck, type Wall } from './index.js';
8
+
9
+ /**
10
+ * Define a wall for any vertical. Rejects ids that are not slugs and granted scopes a deny
11
+ * swallows whole (a grant that can never be used). Carve-outs, a broad grant with a narrower
12
+ * deny inside it, are fine: the deny wins.
13
+ */
14
+ export function defineWall(w: Wall): Wall & { manifest_hash: string } {
15
+ if (!/^[a-z0-9-]{3,48}$/.test(w.id)) throw new Error('walls: id must be a lower-case slug');
16
+ if (!w.regulator || w.denies.length === 0) throw new Error('walls: a wall needs a regulator and at least one denied scope');
17
+ const clash = w.scopes.filter((s) => w.denies.some((d) => scopeCovers(d, s)));
18
+ if (clash.length) throw new Error(`walls: granted scopes fall entirely inside the wall: ${clash.join(', ')}`);
19
+ return { ...w, forbidden: w.forbidden.map((p) => p.toLowerCase()), manifest_hash: wallManifestHash(w) };
20
+ }
21
+
22
+ /** Normalise Arabic for matching: strip diacritics and tatweel, unify alef, ta marbuta and alef maqsura forms. */
23
+ export function normaliseArabic(text: string): string {
24
+ return text
25
+ .replace(/[ً-ْٰـ]/g, '')
26
+ .replace(/[آأإ]/g, 'ا')
27
+ .replace(/ة/g, 'ه')
28
+ .replace(/ى/g, 'ي');
29
+ }
30
+
31
+ /** Arabic (MSA and Gulf) phrases for the investment walls: the same "never advise" rule in the languages customers use. */
32
+ export const ARABIC_FORBIDDEN: Record<string, string[]> = {
33
+ 'sca-trading': ['اشتري هذا', 'بيع هذا', 'ربح مضمون', 'عائد مضمون', 'لازم تشتري', 'انصحك تشتري', 'اشتريه الحين'],
34
+ 'cma-ksa': ['اشتري هذا', 'بيع هذا', 'ربح مضمون', 'عائد مضمون', 'لازم تشتري'],
35
+ 'vara-marketing': ['ربح مضمون', 'عائد مضمون', 'بدون مخاطر', 'ما تخسر'],
36
+ };
37
+
38
+ /** `checkOutput` plus normalised Arabic phrases for the wall (from `ARABIC_FORBIDDEN` or your own list). */
39
+ export function checkOutputMultilingual(wall: Wall, text: string, arabic: string[] = ARABIC_FORBIDDEN[wall.id] ?? []): OutputCheck {
40
+ const base = checkOutput(wall, text);
41
+ const norm = normaliseArabic(text);
42
+ const ar = arabic.filter((p) => norm.includes(normaliseArabic(p)));
43
+ return { ok: base.ok && ar.length === 0, violations: [...base.violations, ...ar] };
44
+ }
45
+
46
+ /**
47
+ * Run your evaluation outputs through the wall and compare with the previous run: a lower pass
48
+ * rate, or a case that passed before and fails now, is drift.
49
+ */
50
+ export function wallDrift(wall: Wall, outputs: Array<{ id: string; text: string }>, previous?: { passRate: number; failing: string[] }) {
51
+ const failing = outputs.filter((o) => !checkOutputMultilingual(wall, o.text).ok).map((o) => o.id);
52
+ const passRate = outputs.length ? Math.round(((outputs.length - failing.length) / outputs.length) * 1000) / 1000 : 1;
53
+ const regressions = previous ? failing.filter((id) => !previous.failing.includes(id)) : [];
54
+ return { wall: wall.id, manifest_hash: wallManifestHash(wall), cases: outputs.length, passRate, failing, regressions, drifted: !!previous && (passRate < previous.passRate || regressions.length > 0) };
55
+ }
56
+
57
+ export type WallCertificate = SignedObject<{ v: 1; type: 'wall.certificate'; wall: string; regulator: string; manifest_hash: string; from: string; to: string; runs: number; cases: number; failures: number; ts: string }>;
58
+
59
+ /** A signed statement for a regulator: the wall's manifest held for the period, with the evaluation totals. */
60
+ export function wallCertificate(wall: Wall, input: { from: string; to: string; runs: Array<{ cases: number; failing: string[] }>; ts?: string }, privateKey: Uint8Array): WallCertificate {
61
+ return signObject({
62
+ v: 1 as const, type: 'wall.certificate' as const, wall: wall.id, regulator: wall.regulator, manifest_hash: wallManifestHash(wall), from: input.from, to: input.to,
63
+ runs: input.runs.length, cases: input.runs.reduce((s, r) => s + r.cases, 0), failures: input.runs.reduce((s, r) => s + r.failing.length, 0), ts: input.ts ?? new Date().toISOString(),
64
+ }, privateKey);
65
+ }
66
+
67
+ /** Signed, and the wall's current manifest is the one certified. */
68
+ export function verifyWallCertificate(c: WallCertificate, wall: Wall, trustedSigners?: string[]): boolean {
69
+ return verifySignedObject(c) && c.manifest_hash === wallManifestHash(wall) && (!trustedSigners || trustedSigners.includes(c.signer));
70
+ }
package/src/index.ts CHANGED
@@ -72,6 +72,84 @@ export const WALLS: Record<string, Wall> = {
72
72
  scopes: ['data.process.adgm.*'], denies: ['data.export.nonadequate.*'], forbidden: [],
73
73
  note: 'ADGM free-zone data protection; select per deployment (not federal PDPL)',
74
74
  },
75
+ // Further presets: starting points for each regulator's rules; confirm scope and wording with counsel.
76
+ 'cbuae-consumer': {
77
+ id: 'cbuae-consumer', regulator: 'CBUAE (Consumer Protection)',
78
+ scopes: ['banking.inform.*', 'banking.service.*'],
79
+ denies: ['banking.credit.decide.*', 'banking.product.push.*'],
80
+ forbidden: ['you are pre-approved', 'no risk at all', 'limited time only, sign now', 'hidden fees do not apply'],
81
+ note: 'informs and services; credit decisions stay with a person; no pressure selling; disclose fees',
82
+ },
83
+ 'vara-marketing': {
84
+ id: 'vara-marketing', regulator: 'VARA (Dubai)',
85
+ scopes: ['va.education.*', 'va.market.read.*'],
86
+ denies: ['va.advise.*', 'va.execute.*', 'va.promote.unlicensed.*'],
87
+ forbidden: ['guaranteed return', 'guaranteed profit', 'risk-free', 'cannot lose', 'buy this token', 'to the moon'],
88
+ note: 'virtual-asset marketing must be fair and carry risk disclaimers; no advice or execution without a licence',
89
+ },
90
+ 'doh-health': {
91
+ id: 'doh-health', regulator: 'DoH Abu Dhabi',
92
+ scopes: ['health.inform.*', 'health.triage.assist.*'],
93
+ denies: ['health.diagnose.*', 'health.prescribe.*'],
94
+ forbidden: ['you have', 'your diagnosis is', 'take this medication', 'no need to see a doctor'],
95
+ note: 'assists clinicians and informs patients; never diagnoses or prescribes; a licensed professional decides',
96
+ },
97
+ 'dha-health': {
98
+ id: 'dha-health', regulator: 'DHA (Dubai)',
99
+ scopes: ['health.inform.*', 'health.triage.assist.*'],
100
+ denies: ['health.diagnose.*', 'health.prescribe.*'],
101
+ forbidden: ['your diagnosis is', 'take this medication', 'no need to see a doctor'],
102
+ note: 'assists, never replaces, the licensed clinician',
103
+ },
104
+ 'sdaia-ethics': {
105
+ id: 'sdaia-ethics', regulator: 'SDAIA (KSA AI Ethics Principles)',
106
+ scopes: ['ai.assist.*'],
107
+ denies: ['ai.profile.sensitive.*', 'ai.decide.unreviewed.*'],
108
+ forbidden: [],
109
+ note: 'fairness, privacy, transparency and human oversight; no sensitive profiling; decisions reviewable',
110
+ },
111
+ 'sama-banking': {
112
+ id: 'sama-banking', regulator: 'SAMA',
113
+ scopes: ['banking.inform.*', 'banking.service.*'],
114
+ denies: ['banking.credit.decide.*', 'banking.data.share.unconsented.*'],
115
+ forbidden: ['you are pre-approved', 'no risk at all'],
116
+ note: 'consumer protection for bank customers; consented data sharing only',
117
+ },
118
+ 'cma-ksa': {
119
+ id: 'cma-ksa', regulator: 'CMA (KSA)',
120
+ scopes: ['securities.education.*', 'market.read.*'],
121
+ denies: ['securities.advise.*', 'securities.execute.*'],
122
+ forbidden: ['buy this', 'sell this', 'guaranteed return', 'guaranteed profit'],
123
+ note: 'education only; securities advice and dealing are authorised activities',
124
+ },
125
+ 'adek-khda-education': {
126
+ id: 'adek-khda-education', regulator: 'ADEK / KHDA',
127
+ scopes: ['education.tutor.*', 'education.inform.*'],
128
+ denies: ['education.grade.final.*', 'education.profile.minor.*'],
129
+ forbidden: ['i will write your exam', 'submit this as your own'],
130
+ note: 'tutors and informs; teachers decide final grades; no profiling of minors',
131
+ },
132
+ 'fca-consumer-duty': {
133
+ id: 'fca-consumer-duty', regulator: 'UK FCA (Consumer Duty)',
134
+ scopes: ['finance.inform.*', 'finance.service.*'],
135
+ denies: ['finance.advise.unregulated.*', 'finance.sludge.*'],
136
+ forbidden: ['no risk at all', 'act now or lose out', 'guaranteed return'],
137
+ note: 'good outcomes for retail customers: fair value, understanding, support, no sludge',
138
+ },
139
+ 'sec-marketing': {
140
+ id: 'sec-marketing', regulator: 'US SEC (Marketing Rule 206(4)-1)',
141
+ scopes: ['adviser.marketing.*'],
142
+ denies: ['adviser.marketing.testimonial.undisclosed.*', 'adviser.marketing.hypothetical.unsupported.*'],
143
+ forbidden: ['guaranteed return', 'guaranteed profit', 'cannot lose', 'past performance guarantees'],
144
+ note: 'no untrue or misleading statements; performance shown fairly with required disclosures',
145
+ },
146
+ 'finra-genai': {
147
+ id: 'finra-genai', regulator: 'FINRA (Rule 2210, gen AI guidance)',
148
+ scopes: ['broker.communications.*'],
149
+ denies: ['broker.communications.unreviewed.*'],
150
+ forbidden: ['guaranteed return', 'risk-free', 'cannot lose'],
151
+ note: 'communications fair and balanced; supervision and record-keeping apply to AI-generated content',
152
+ },
75
153
  };
76
154
 
77
155
  /** A `@zanii/policy` config that denies everything the wall forbids. Pass to `createPolicyEngine`. */
@@ -107,3 +185,4 @@ export function buildEvalReceipt(wall: Wall, results: { passed: number; failed:
107
185
  },
108
186
  };
109
187
  }
188
+ export * from './assurance.js';