@zanii/minimization 0.1.0 → 0.1.2

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 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAyBA,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAIzF;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,qBAAqB,CAAC;IAC5B,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAgBzG;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjD;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oEAAoE;IACpE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAYlG"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAoCA,yGAAyG;AACzG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,EAAE,CAAA;CAAE,CAIzF;AAED,iGAAiG;AACjG,wBAAgB,cAAc,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAE5E;AAED,MAAM,WAAW,WAAW;IAC1B,CAAC,EAAE,CAAC,CAAC;IACL,IAAI,EAAE,qBAAqB,CAAC;IAC5B,wDAAwD;IACxD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,SAAS,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,WAAW,WAAW;IAC1B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,yFAAyF;AACzF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAAE,CAgBzG;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,WAAW,GAAG,MAAM,CAEjD;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,OAAO,CAAC;IACZ,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,oEAAoE;IACpE,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,WAAW,EAAE,cAAc,EAAE,MAAM,EAAE,GAAG,iBAAiB,CAelG"}
package/dist/index.js CHANGED
@@ -22,9 +22,20 @@
22
22
  import { bytesToHex } from '@noble/hashes/utils';
23
23
  import { sha256 } from '@noble/hashes/sha256';
24
24
  import { jcsHash } from '@zanii/core';
25
+ // Code-point order (what Python's sorted() uses) — JS default sort is UTF-16 code-unit
26
+ // order, which diverges on astral-plane characters and would break cross-language parity.
27
+ const byCodePoint = (a, b) => {
28
+ const A = [...a], B = [...b];
29
+ for (let i = 0; i < Math.min(A.length, B.length); i++) {
30
+ const d = A[i].codePointAt(0) - B[i].codePointAt(0);
31
+ if (d !== 0)
32
+ return d;
33
+ }
34
+ return A.length - B.length;
35
+ };
25
36
  /** Commit to a declared minimum field set. Order-independent; `commitment` references it on receipts. */
26
37
  export function commitFieldSet(fields) {
27
- const sorted = [...new Set(fields)].sort();
38
+ const sorted = [...new Set(fields)].sort(byCodePoint);
28
39
  const h = sha256(new TextEncoder().encode(JSON.stringify(sorted)));
29
40
  return { commitment: `minfields:v1:${bytesToHex(h)}`, fields: sorted };
30
41
  }
@@ -68,6 +79,9 @@ export function verifyMinimization(proof, declaredFields) {
68
79
  if (proof?.v !== 1 || proof.type !== 'minimization.access') {
69
80
  return { ok: false, reasons: ['not a minimization access proof (v1)'], excess: [] };
70
81
  }
82
+ if (typeof proof.field_set !== 'string' || !Array.isArray(proof.accessed)) {
83
+ return { ok: false, reasons: ['malformed access proof: field_set/accessed missing'], excess: [] };
84
+ }
71
85
  if (!verifyFieldSet(declaredFields, proof.field_set)) {
72
86
  reasons.push('declared field set does not match the receipt commitment (was the minimum widened after the fact?)');
73
87
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAEtC,yGAAyG;AACzG,MAAM,UAAU,cAAc,CAAC,MAAgB;IAC7C,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;IACnE,OAAO,EAAE,UAAU,EAAE,gBAAgB,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;AACzE,CAAC;AAED,iGAAiG;AACjG,MAAM,UAAU,cAAc,CAAC,MAAgB,EAAE,UAAkB;IACjE,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC;AAC1D,CAAC;AAuBD,yFAAyF;AACzF,MAAM,UAAU,gBAAgB,CAAC,KAAkB;IACjD,IAAI,OAAO,KAAK,CAAC,kBAAkB,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,kBAAkB,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACvG,MAAM,IAAI,KAAK,CAAC,wDAAwD,CAAC,CAAC;IAC5E,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IACtF,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IACvF,MAAM,CAAC,GAAgB;QACrB,CAAC,EAAE,CAAC;QACJ,IAAI,EAAE,qBAAqB;QAC3B,SAAS,EAAE,KAAK,CAAC,kBAAkB;QACnC,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE;QAC7C,EAAE,EAAE,KAAK,CAAC,EAAE;KACb,CAAC;IACF,IAAI,KAAK,CAAC,GAAG,KAAK,SAAS;QAAE,CAAC,CAAC,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC;IAC/C,IAAI,KAAK,CAAC,OAAO,KAAK,SAAS;QAAE,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAC3D,OAAO,EAAE,MAAM,EAAE,qBAAqB,EAAE,OAAO,EAAE,CAAuC,EAAE,CAAC;AAC7F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAc;IACvC,OAAO,OAAO,CAAC,CAAuC,CAAC,CAAC;AAC1D,CAAC;AASD;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAkB,EAAE,cAAwB;IAC7E,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,IAAI,KAAK,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,qBAAqB,EAAE,CAAC;QAC3D,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,sCAAsC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACtF,CAAC;IACD,IAAI,CAAC,cAAc,CAAC,cAAc,EAAE,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;QACrD,OAAO,CAAC,IAAI,CAAC,oGAAoG,CAAC,CAAC;IACrH,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,cAAc,CAAC,CAAC;IACzC,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,KAAK,MAAM,CAAC,IAAI,MAAM;QAAE,OAAO,CAAC,IAAI,CAAC,aAAa,CAAC,0CAA0C,CAAC,CAAC;IAC/F,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;AACvD,CAAC"}
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/minimization",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Prove data minimization (GDPR Art. 5(1)(c)) - unprovable today, only assertable. Commit the declared MINIMUM field set, then prove every field an agent accessed was inside it; any access outside the declared minimum is a flagged violation. Composes @zanii/redact field commitments and purpose-bound delegation into a proof a regulator accepts. Proves declared-vs-accessed, not that the minimum itself was well-chosen.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://ledger.zanii.agency",
@@ -32,7 +32,7 @@
32
32
  },
33
33
  "dependencies": {
34
34
  "@noble/hashes": "^1.7.1",
35
- "@zanii/core": "0.4.0"
35
+ "@zanii/core": "^0.5.2"
36
36
  },
37
37
  "scripts": {
38
38
  "build": "tsc -p tsconfig.build.json",
package/src/index.ts CHANGED
@@ -23,9 +23,20 @@ import { bytesToHex } from '@noble/hashes/utils';
23
23
  import { sha256 } from '@noble/hashes/sha256';
24
24
  import { jcsHash } from '@zanii/core';
25
25
 
26
+ // Code-point order (what Python's sorted() uses) — JS default sort is UTF-16 code-unit
27
+ // order, which diverges on astral-plane characters and would break cross-language parity.
28
+ const byCodePoint = (a: string, b: string): number => {
29
+ const A = [...a], B = [...b];
30
+ for (let i = 0; i < Math.min(A.length, B.length); i++) {
31
+ const d = A[i]!.codePointAt(0)! - B[i]!.codePointAt(0)!;
32
+ if (d !== 0) return d;
33
+ }
34
+ return A.length - B.length;
35
+ };
36
+
26
37
  /** Commit to a declared minimum field set. Order-independent; `commitment` references it on receipts. */
27
38
  export function commitFieldSet(fields: string[]): { commitment: string; fields: string[] } {
28
- const sorted = [...new Set(fields)].sort();
39
+ const sorted = [...new Set(fields)].sort(byCodePoint);
29
40
  const h = sha256(new TextEncoder().encode(JSON.stringify(sorted)));
30
41
  return { commitment: `minfields:v1:${bytesToHex(h)}`, fields: sorted };
31
42
  }
@@ -97,6 +108,9 @@ export function verifyMinimization(proof: AccessProof, declaredFields: string[])
97
108
  if (proof?.v !== 1 || proof.type !== 'minimization.access') {
98
109
  return { ok: false, reasons: ['not a minimization access proof (v1)'], excess: [] };
99
110
  }
111
+ if (typeof proof.field_set !== 'string' || !Array.isArray(proof.accessed)) {
112
+ return { ok: false, reasons: ['malformed access proof: field_set/accessed missing'], excess: [] };
113
+ }
100
114
  if (!verifyFieldSet(declaredFields, proof.field_set)) {
101
115
  reasons.push('declared field set does not match the receipt commitment (was the minimum widened after the fact?)');
102
116
  }