@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.
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +15 -1
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
- package/src/index.ts +15 -1
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
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,
|
|
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.
|
|
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.
|
|
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
|
}
|