nz-privacy-auditor 0.8.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.
Files changed (67) hide show
  1. package/README.md +152 -0
  2. package/data/llm_cache/cache.json +1 -0
  3. package/dist/cli.d.ts +16 -0
  4. package/dist/cli.d.ts.map +1 -0
  5. package/dist/cli.js +233 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/detectors/address.d.ts +48 -0
  8. package/dist/detectors/address.d.ts.map +1 -0
  9. package/dist/detectors/address.js +262 -0
  10. package/dist/detectors/address.js.map +1 -0
  11. package/dist/detectors/base.d.ts +43 -0
  12. package/dist/detectors/base.d.ts.map +1 -0
  13. package/dist/detectors/base.js +6 -0
  14. package/dist/detectors/base.js.map +1 -0
  15. package/dist/detectors/driver_licence.d.ts +38 -0
  16. package/dist/detectors/driver_licence.d.ts.map +1 -0
  17. package/dist/detectors/driver_licence.js +80 -0
  18. package/dist/detectors/driver_licence.js.map +1 -0
  19. package/dist/detectors/ird.d.ts +37 -0
  20. package/dist/detectors/ird.d.ts.map +1 -0
  21. package/dist/detectors/ird.js +103 -0
  22. package/dist/detectors/ird.js.map +1 -0
  23. package/dist/detectors/maori_name.d.ts +36 -0
  24. package/dist/detectors/maori_name.d.ts.map +1 -0
  25. package/dist/detectors/maori_name.js +251 -0
  26. package/dist/detectors/maori_name.js.map +1 -0
  27. package/dist/detectors/nhi.d.ts +44 -0
  28. package/dist/detectors/nhi.d.ts.map +1 -0
  29. package/dist/detectors/nhi.js +147 -0
  30. package/dist/detectors/nhi.js.map +1 -0
  31. package/dist/detectors/phone.d.ts +49 -0
  32. package/dist/detectors/phone.d.ts.map +1 -0
  33. package/dist/detectors/phone.js +126 -0
  34. package/dist/detectors/phone.js.map +1 -0
  35. package/dist/index.d.ts +25 -0
  36. package/dist/index.d.ts.map +1 -0
  37. package/dist/index.js +52 -0
  38. package/dist/index.js.map +1 -0
  39. package/dist/report.d.ts +14 -0
  40. package/dist/report.d.ts.map +1 -0
  41. package/dist/report.js +90 -0
  42. package/dist/report.js.map +1 -0
  43. package/dist/scanner.d.ts +51 -0
  44. package/dist/scanner.d.ts.map +1 -0
  45. package/dist/scanner.js +114 -0
  46. package/dist/scanner.js.map +1 -0
  47. package/dist/verification.d.ts +25 -0
  48. package/dist/verification.d.ts.map +1 -0
  49. package/dist/verification.js +89 -0
  50. package/dist/verification.js.map +1 -0
  51. package/dist/verifiers/base.d.ts +27 -0
  52. package/dist/verifiers/base.d.ts.map +1 -0
  53. package/dist/verifiers/base.js +24 -0
  54. package/dist/verifiers/base.js.map +1 -0
  55. package/dist/verifiers/cache.d.ts +23 -0
  56. package/dist/verifiers/cache.d.ts.map +1 -0
  57. package/dist/verifiers/cache.js +103 -0
  58. package/dist/verifiers/cache.js.map +1 -0
  59. package/dist/verifiers/gemini.d.ts +38 -0
  60. package/dist/verifiers/gemini.d.ts.map +1 -0
  61. package/dist/verifiers/gemini.js +121 -0
  62. package/dist/verifiers/gemini.js.map +1 -0
  63. package/dist/verifiers/index.d.ts +8 -0
  64. package/dist/verifiers/index.d.ts.map +1 -0
  65. package/dist/verifiers/index.js +16 -0
  66. package/dist/verifiers/index.js.map +1 -0
  67. package/package.json +96 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,YAAY,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,EAAE,WAAW,EAAE,UAAU,IAAI,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC1D,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,IAAI,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACpE,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAExE,YAAY,EAAE,WAAW,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,iBAAiB,EAAE,KAAK,wBAAwB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,EACL,kBAAkB,IAAI,sBAAsB,EAC5C,aAAa,IAAI,iBAAiB,EAClC,cAAc,EACd,kBAAkB,EAClB,iBAAiB,EACjB,qBAAqB,EACrB,KAAK,WAAW,EAChB,KAAK,kBAAkB,EACvB,KAAK,OAAO,EACZ,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,OAAO,UAAU,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ /**
3
+ * nz-privacy-auditor
4
+ *
5
+ * Privacy Act 2020 compliance auditor for ML datasets. Scans text for
6
+ * NZ-specific personal information: IRD, NHI, driver licence, phone,
7
+ * address, te reo Māori names.
8
+ *
9
+ * TypeScript port of the Python package
10
+ * (https://github.com/ShahnawazKakarh/nz-privacy-auditor).
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.VERSION = exports.DETECTOR_DESCRIPTIONS = exports.VerificationCache = exports.QuotaExceededError = exports.GeminiVerifier = exports.LLM_DEFAULT_MODEL = exports.LLM_DEFAULT_CACHE_PATH = exports.applyVerification = exports.parseCsv = exports.renderConsole = exports.toJson = exports.toDict = exports.defaultDetectors = exports.Scanner = exports.foldMacrons = exports.MaoriNameDetector = exports.NZ_LOCATIONS = exports.AddressDetector = exports.classifyNzPhone = exports.toNsn = exports.toE164 = exports.PhoneDetector = exports.DriverLicenceDetector = exports.isValidNhi = exports.NHIDetector = exports.irdChecksumOk = exports.IRDDetector = void 0;
14
+ var ird_1 = require("./detectors/ird");
15
+ Object.defineProperty(exports, "IRDDetector", { enumerable: true, get: function () { return ird_1.IRDDetector; } });
16
+ Object.defineProperty(exports, "irdChecksumOk", { enumerable: true, get: function () { return ird_1.checksumOk; } });
17
+ var nhi_1 = require("./detectors/nhi");
18
+ Object.defineProperty(exports, "NHIDetector", { enumerable: true, get: function () { return nhi_1.NHIDetector; } });
19
+ Object.defineProperty(exports, "isValidNhi", { enumerable: true, get: function () { return nhi_1.isValidNhi; } });
20
+ var driver_licence_1 = require("./detectors/driver_licence");
21
+ Object.defineProperty(exports, "DriverLicenceDetector", { enumerable: true, get: function () { return driver_licence_1.DriverLicenceDetector; } });
22
+ var phone_1 = require("./detectors/phone");
23
+ Object.defineProperty(exports, "PhoneDetector", { enumerable: true, get: function () { return phone_1.PhoneDetector; } });
24
+ Object.defineProperty(exports, "toE164", { enumerable: true, get: function () { return phone_1.toE164; } });
25
+ Object.defineProperty(exports, "toNsn", { enumerable: true, get: function () { return phone_1.toNsn; } });
26
+ Object.defineProperty(exports, "classifyNzPhone", { enumerable: true, get: function () { return phone_1.classify; } });
27
+ var address_1 = require("./detectors/address");
28
+ Object.defineProperty(exports, "AddressDetector", { enumerable: true, get: function () { return address_1.AddressDetector; } });
29
+ Object.defineProperty(exports, "NZ_LOCATIONS", { enumerable: true, get: function () { return address_1.NZ_LOCATIONS; } });
30
+ var maori_name_1 = require("./detectors/maori_name");
31
+ Object.defineProperty(exports, "MaoriNameDetector", { enumerable: true, get: function () { return maori_name_1.MaoriNameDetector; } });
32
+ Object.defineProperty(exports, "foldMacrons", { enumerable: true, get: function () { return maori_name_1.foldMacrons; } });
33
+ var scanner_1 = require("./scanner");
34
+ Object.defineProperty(exports, "Scanner", { enumerable: true, get: function () { return scanner_1.Scanner; } });
35
+ Object.defineProperty(exports, "defaultDetectors", { enumerable: true, get: function () { return scanner_1.defaultDetectors; } });
36
+ var report_1 = require("./report");
37
+ Object.defineProperty(exports, "toDict", { enumerable: true, get: function () { return report_1.toDict; } });
38
+ Object.defineProperty(exports, "toJson", { enumerable: true, get: function () { return report_1.toJson; } });
39
+ Object.defineProperty(exports, "renderConsole", { enumerable: true, get: function () { return report_1.renderConsole; } });
40
+ var cli_1 = require("./cli");
41
+ Object.defineProperty(exports, "parseCsv", { enumerable: true, get: function () { return cli_1.parseCsv; } });
42
+ var verification_1 = require("./verification");
43
+ Object.defineProperty(exports, "applyVerification", { enumerable: true, get: function () { return verification_1.applyVerification; } });
44
+ var verifiers_1 = require("./verifiers");
45
+ Object.defineProperty(exports, "LLM_DEFAULT_CACHE_PATH", { enumerable: true, get: function () { return verifiers_1.DEFAULT_CACHE_PATH; } });
46
+ Object.defineProperty(exports, "LLM_DEFAULT_MODEL", { enumerable: true, get: function () { return verifiers_1.DEFAULT_MODEL; } });
47
+ Object.defineProperty(exports, "GeminiVerifier", { enumerable: true, get: function () { return verifiers_1.GeminiVerifier; } });
48
+ Object.defineProperty(exports, "QuotaExceededError", { enumerable: true, get: function () { return verifiers_1.QuotaExceededError; } });
49
+ Object.defineProperty(exports, "VerificationCache", { enumerable: true, get: function () { return verifiers_1.VerificationCache; } });
50
+ Object.defineProperty(exports, "DETECTOR_DESCRIPTIONS", { enumerable: true, get: function () { return verifiers_1.DETECTOR_DESCRIPTIONS; } });
51
+ exports.VERSION = "0.8.0";
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAGH,uCAA2E;AAAlE,kGAAA,WAAW,OAAA;AAAE,oGAAA,UAAU,OAAiB;AACjD,uCAA0D;AAAjD,kGAAA,WAAW,OAAA;AAAE,iGAAA,UAAU,OAAA;AAChC,6DAAmE;AAA1D,uHAAA,qBAAqB,OAAA;AAC9B,2CAA8F;AAArF,sGAAA,aAAa,OAAA;AAAE,+FAAA,MAAM,OAAA;AAAE,8FAAA,KAAK,OAAA;AAAE,wGAAA,QAAQ,OAAmB;AAClE,+CAAoE;AAA3D,0GAAA,eAAe,OAAA;AAAE,uGAAA,YAAY,OAAA;AACtC,qDAAwE;AAA/D,+GAAA,iBAAiB,OAAA;AAAE,yGAAA,WAAW,OAAA;AAGvC,qCAAsD;AAA7C,kGAAA,OAAO,OAAA;AAAE,2GAAA,gBAAgB,OAAA;AAClC,mCAAyD;AAAhD,gGAAA,MAAM,OAAA;AAAE,gGAAA,MAAM,OAAA;AAAE,uGAAA,aAAa,OAAA;AACtC,6BAAiC;AAAxB,+FAAA,QAAQ,OAAA;AACjB,+CAAkF;AAAzE,iHAAA,iBAAiB,OAAA;AAC1B,yCAWqB;AAVnB,mHAAA,kBAAkB,OAA0B;AAC5C,8GAAA,aAAa,OAAqB;AAClC,2GAAA,cAAc,OAAA;AACd,+GAAA,kBAAkB,OAAA;AAClB,8GAAA,iBAAiB,OAAA;AACjB,kHAAA,qBAAqB,OAAA;AAOV,QAAA,OAAO,GAAG,OAAO,CAAC"}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Report rendering for ScanResult instances.
3
+ *
4
+ * Provides a JSON serialiser and a plain-text console renderer. HTML
5
+ * reports are planned for a later release.
6
+ */
7
+ import type { ScanResult } from "./scanner";
8
+ /** Convert a ScanResult to a JSON-serialisable plain object. */
9
+ export declare function toDict(result: ScanResult): Record<string, unknown>;
10
+ /** Render the ScanResult as a JSON string. */
11
+ export declare function toJson(result: ScanResult, indent?: number | null): string;
12
+ /** Render a human-readable summary + findings table as plain text. */
13
+ export declare function renderConsole(result: ScanResult): string;
14
+ //# sourceMappingURL=report.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAE5C,gEAAgE;AAChE,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuBlE;AAED,8CAA8C;AAC9C,wBAAgB,MAAM,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,GAAE,MAAM,GAAG,IAAQ,GAAG,MAAM,CAE5E;AAED,sEAAsE;AACtE,wBAAgB,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAwDxD"}
package/dist/report.js ADDED
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ /**
3
+ * Report rendering for ScanResult instances.
4
+ *
5
+ * Provides a JSON serialiser and a plain-text console renderer. HTML
6
+ * reports are planned for a later release.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.toDict = toDict;
10
+ exports.toJson = toJson;
11
+ exports.renderConsole = renderConsole;
12
+ /** Convert a ScanResult to a JSON-serialisable plain object. */
13
+ function toDict(result) {
14
+ return {
15
+ summary: {
16
+ rows_scanned: result.rowsScanned,
17
+ columns_scanned: result.columnsScanned,
18
+ detectors_used: result.detectorsUsed,
19
+ total_findings: result.totalFindings,
20
+ by_detector: result.countByDetector,
21
+ by_severity: result.countBySeverity,
22
+ by_column: result.countByColumn,
23
+ },
24
+ findings: result.findings.map((cf) => ({
25
+ row: cf.row,
26
+ column: cf.column,
27
+ detector: cf.finding.detector,
28
+ severity: cf.finding.severity,
29
+ value: cf.finding.value,
30
+ start: cf.finding.start,
31
+ end: cf.finding.end,
32
+ confidence: cf.finding.confidence,
33
+ context: cf.finding.context,
34
+ })),
35
+ };
36
+ }
37
+ /** Render the ScanResult as a JSON string. */
38
+ function toJson(result, indent = 2) {
39
+ return JSON.stringify(toDict(result), null, indent ?? 0);
40
+ }
41
+ /** Render a human-readable summary + findings table as plain text. */
42
+ function renderConsole(result) {
43
+ const lines = [];
44
+ lines.push(`nz-privacy-auditor scanned ${result.rowsScanned} rows across ` +
45
+ `${result.columnsScanned.length} string columns`);
46
+ lines.push(`Total findings: ${result.totalFindings} • ` +
47
+ `Detectors: ${result.detectorsUsed.join(", ")}`);
48
+ if (result.totalFindings === 0) {
49
+ lines.push("No PII findings.");
50
+ return lines.join("\n");
51
+ }
52
+ const sev = Object.entries(result.countBySeverity)
53
+ .sort()
54
+ .map(([k, v]) => `${k} ${v}`)
55
+ .join(", ");
56
+ const det = Object.entries(result.countByDetector)
57
+ .sort()
58
+ .map(([k, v]) => `${k} ${v}`)
59
+ .join(", ");
60
+ lines.push(`By severity: ${sev}`);
61
+ lines.push(`By detector: ${det}`);
62
+ // Simple monospace table
63
+ const header = ["row", "column", "detector", "severity", "confidence", "value"];
64
+ const rows = result.findings.slice(0, 200).map((cf) => {
65
+ let value = cf.finding.value;
66
+ if (value.length > 40)
67
+ value = value.slice(0, 37) + "...";
68
+ return [
69
+ String(cf.row),
70
+ cf.column,
71
+ cf.finding.detector,
72
+ cf.finding.severity,
73
+ cf.finding.confidence.toFixed(2),
74
+ value,
75
+ ];
76
+ });
77
+ const widths = header.map((h, i) => Math.max(h.length, ...rows.map((r) => r[i].length)));
78
+ const pad = (s, w) => s.padEnd(w, " ");
79
+ lines.push("");
80
+ lines.push(header.map((h, i) => pad(h, widths[i])).join(" "));
81
+ lines.push(widths.map((w) => "-".repeat(w)).join(" "));
82
+ for (const row of rows) {
83
+ lines.push(row.map((c, i) => pad(c, widths[i])).join(" "));
84
+ }
85
+ if (result.totalFindings > 200) {
86
+ lines.push(`… ${result.totalFindings - 200} more findings not shown.`);
87
+ }
88
+ return lines.join("\n");
89
+ }
90
+ //# sourceMappingURL=report.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Dataset-level scanner that orchestrates the detector pipeline.
3
+ *
4
+ * `Scanner` walks each string-typed value across a set of rows and applies
5
+ * every configured detector to each cell. Results are collected into a
6
+ * `ScanResult` with per-cell findings and aggregate summary counts.
7
+ */
8
+ import type { Detector, Finding } from "./detectors/base";
9
+ /** Return the default detector set (all six built-in detectors). */
10
+ export declare function defaultDetectors(): Detector[];
11
+ /** A `Finding` enriched with its row index, column name, and cell value. */
12
+ export interface CellFinding {
13
+ row: number;
14
+ column: string;
15
+ finding: Finding;
16
+ /** The full cell value that produced this finding. */
17
+ cellValue: string;
18
+ }
19
+ /** Aggregate result of scanning a set of rows. */
20
+ export interface ScanResult {
21
+ rowsScanned: number;
22
+ columnsScanned: string[];
23
+ detectorsUsed: string[];
24
+ findings: CellFinding[];
25
+ totalFindings: number;
26
+ countByDetector: Record<string, number>;
27
+ countBySeverity: Record<string, number>;
28
+ countByColumn: Record<string, number>;
29
+ }
30
+ export interface ScannerOptions {
31
+ detectors?: Detector[];
32
+ /** Drop findings with confidence below this threshold. Default 0.0. */
33
+ minConfidence?: number;
34
+ }
35
+ /** Orchestrates detection across a set of rows or a single value. */
36
+ export declare class Scanner {
37
+ readonly detectors: Detector[];
38
+ readonly minConfidence: number;
39
+ constructor(options?: ScannerOptions);
40
+ /** Scan a single string with all configured detectors. */
41
+ scanValue(value: string): Finding[];
42
+ /**
43
+ * Scan every string-typed column of `rows` and return a ScanResult.
44
+ *
45
+ * Each row is a plain object; non-string values are ignored (numeric
46
+ * columns are not scanned). Columns are derived from the union of keys
47
+ * across all rows.
48
+ */
49
+ scanRows(rows: Record<string, unknown>[]): ScanResult;
50
+ }
51
+ //# sourceMappingURL=scanner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.d.ts","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAQ1D,oEAAoE;AACpE,wBAAgB,gBAAgB,IAAI,QAAQ,EAAE,CAS7C;AAED,4EAA4E;AAC5E,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB,sDAAsD;IACtD,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,kDAAkD;AAClD,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,EAAE,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,QAAQ,EAAE,WAAW,EAAE,CAAC;IACxB,aAAa,EAAE,MAAM,CAAC;IACtB,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;IACvB,uEAAuE;IACvE,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAwBD,qEAAqE;AACrE,qBAAa,OAAO;IAClB,QAAQ,CAAC,SAAS,EAAE,QAAQ,EAAE,CAAC;IAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;gBAEnB,OAAO,GAAE,cAAmB;IAKxC,0DAA0D;IAC1D,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,EAAE;IAWnC;;;;;;OAMG;IACH,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,GAAG,UAAU;CA0CtD"}
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+ /**
3
+ * Dataset-level scanner that orchestrates the detector pipeline.
4
+ *
5
+ * `Scanner` walks each string-typed value across a set of rows and applies
6
+ * every configured detector to each cell. Results are collected into a
7
+ * `ScanResult` with per-cell findings and aggregate summary counts.
8
+ */
9
+ Object.defineProperty(exports, "__esModule", { value: true });
10
+ exports.Scanner = void 0;
11
+ exports.defaultDetectors = defaultDetectors;
12
+ const address_1 = require("./detectors/address");
13
+ const driver_licence_1 = require("./detectors/driver_licence");
14
+ const ird_1 = require("./detectors/ird");
15
+ const maori_name_1 = require("./detectors/maori_name");
16
+ const nhi_1 = require("./detectors/nhi");
17
+ const phone_1 = require("./detectors/phone");
18
+ /** Return the default detector set (all six built-in detectors). */
19
+ function defaultDetectors() {
20
+ return [
21
+ new ird_1.IRDDetector(),
22
+ new nhi_1.NHIDetector(),
23
+ new driver_licence_1.DriverLicenceDetector(),
24
+ new phone_1.PhoneDetector(),
25
+ new address_1.AddressDetector(),
26
+ new maori_name_1.MaoriNameDetector(),
27
+ ];
28
+ }
29
+ function buildSummary(findings) {
30
+ const byDetector = {};
31
+ const bySeverity = {};
32
+ const byColumn = {};
33
+ for (const cf of findings) {
34
+ byDetector[cf.finding.detector] = (byDetector[cf.finding.detector] ?? 0) + 1;
35
+ bySeverity[cf.finding.severity] = (bySeverity[cf.finding.severity] ?? 0) + 1;
36
+ byColumn[cf.column] = (byColumn[cf.column] ?? 0) + 1;
37
+ }
38
+ return {
39
+ totalFindings: findings.length,
40
+ countByDetector: byDetector,
41
+ countBySeverity: bySeverity,
42
+ countByColumn: byColumn,
43
+ };
44
+ }
45
+ /** Orchestrates detection across a set of rows or a single value. */
46
+ class Scanner {
47
+ constructor(options = {}) {
48
+ this.detectors = options.detectors ?? defaultDetectors();
49
+ this.minConfidence = options.minConfidence ?? 0.0;
50
+ }
51
+ /** Scan a single string with all configured detectors. */
52
+ scanValue(value) {
53
+ const out = [];
54
+ for (const detector of this.detectors) {
55
+ for (const f of detector.scan(value)) {
56
+ if (f.confidence < this.minConfidence)
57
+ continue;
58
+ out.push(f);
59
+ }
60
+ }
61
+ return out;
62
+ }
63
+ /**
64
+ * Scan every string-typed column of `rows` and return a ScanResult.
65
+ *
66
+ * Each row is a plain object; non-string values are ignored (numeric
67
+ * columns are not scanned). Columns are derived from the union of keys
68
+ * across all rows.
69
+ */
70
+ scanRows(rows) {
71
+ const columnSet = new Set();
72
+ for (const row of rows) {
73
+ for (const key of Object.keys(row))
74
+ columnSet.add(key);
75
+ }
76
+ // A column is "string" if at least one non-empty string appears in it.
77
+ const stringCols = [];
78
+ for (const col of columnSet) {
79
+ const hasString = rows.some((r) => typeof r[col] === "string" && r[col].length > 0);
80
+ if (hasString)
81
+ stringCols.push(col);
82
+ }
83
+ const findings = [];
84
+ for (let rowIdx = 0; rowIdx < rows.length; rowIdx++) {
85
+ const row = rows[rowIdx];
86
+ for (const col of stringCols) {
87
+ const raw = row[col];
88
+ if (typeof raw !== "string" || raw.length === 0)
89
+ continue;
90
+ for (const detector of this.detectors) {
91
+ for (const f of detector.scan(raw)) {
92
+ if (f.confidence < this.minConfidence)
93
+ continue;
94
+ findings.push({
95
+ row: rowIdx,
96
+ column: col,
97
+ finding: f,
98
+ cellValue: raw,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ }
104
+ return {
105
+ rowsScanned: rows.length,
106
+ columnsScanned: stringCols,
107
+ detectorsUsed: this.detectors.map((d) => d.name),
108
+ findings,
109
+ ...buildSummary(findings),
110
+ };
111
+ }
112
+ }
113
+ exports.Scanner = Scanner;
114
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Apply an LLM verification pass to an existing ScanResult.
3
+ *
4
+ * The verifier re-scores findings whose initial confidence is below a
5
+ * configurable threshold. A `confirmed` verdict promotes confidence to at
6
+ * least 0.95; a `rejected` verdict drops the finding entirely; `uncertain`
7
+ * leaves the original score in place.
8
+ */
9
+ import type { ScanResult } from "./scanner";
10
+ import { type LLMVerifier } from "./verifiers/base";
11
+ export interface ApplyVerificationOptions {
12
+ /** Only findings with confidence below this threshold are verified. */
13
+ threshold?: number;
14
+ /** 'stop' returns partial result on quota-exceeded; 'raise' rethrows. */
15
+ onQuotaExceeded?: "stop" | "raise";
16
+ }
17
+ /**
18
+ * Run a second-pass LLM verification over the findings of a ScanResult.
19
+ *
20
+ * Confirmed → confidence promoted to max(orig, 0.95), finding annotated.
21
+ * Rejected → finding dropped from the result.
22
+ * Uncertain → confidence unchanged, finding annotated.
23
+ */
24
+ export declare function applyVerification(result: ScanResult, verifier: LLMVerifier, options?: ApplyVerificationOptions): Promise<ScanResult>;
25
+ //# sourceMappingURL=verification.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.d.ts","sourceRoot":"","sources":["../src/verification.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAe,UAAU,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAExE,MAAM,WAAW,wBAAwB;IACvC,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,eAAe,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CACpC;AAsBD;;;;;;GAMG;AACH,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,UAAU,EAClB,QAAQ,EAAE,WAAW,EACrB,OAAO,GAAE,wBAA6B,GACrC,OAAO,CAAC,UAAU,CAAC,CA6DrB"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ /**
3
+ * Apply an LLM verification pass to an existing ScanResult.
4
+ *
5
+ * The verifier re-scores findings whose initial confidence is below a
6
+ * configurable threshold. A `confirmed` verdict promotes confidence to at
7
+ * least 0.95; a `rejected` verdict drops the finding entirely; `uncertain`
8
+ * leaves the original score in place.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.applyVerification = applyVerification;
12
+ const base_1 = require("./verifiers/base");
13
+ function rebuildSummary(findings) {
14
+ const byDetector = {};
15
+ const bySeverity = {};
16
+ const byColumn = {};
17
+ for (const cf of findings) {
18
+ byDetector[cf.finding.detector] = (byDetector[cf.finding.detector] ?? 0) + 1;
19
+ bySeverity[cf.finding.severity] = (bySeverity[cf.finding.severity] ?? 0) + 1;
20
+ byColumn[cf.column] = (byColumn[cf.column] ?? 0) + 1;
21
+ }
22
+ return {
23
+ totalFindings: findings.length,
24
+ countByDetector: byDetector,
25
+ countBySeverity: bySeverity,
26
+ countByColumn: byColumn,
27
+ };
28
+ }
29
+ /**
30
+ * Run a second-pass LLM verification over the findings of a ScanResult.
31
+ *
32
+ * Confirmed → confidence promoted to max(orig, 0.95), finding annotated.
33
+ * Rejected → finding dropped from the result.
34
+ * Uncertain → confidence unchanged, finding annotated.
35
+ */
36
+ async function applyVerification(result, verifier, options = {}) {
37
+ const threshold = options.threshold ?? 0.8;
38
+ const onQuota = options.onQuotaExceeded ?? "stop";
39
+ const newFindings = [];
40
+ let quotaHit = false;
41
+ for (const cf of result.findings) {
42
+ if (cf.finding.confidence >= threshold || quotaHit) {
43
+ newFindings.push(cf);
44
+ continue;
45
+ }
46
+ let v;
47
+ try {
48
+ v = await verifier.verify(cf.finding.detector, cf.finding.value, cf.cellValue || cf.finding.value);
49
+ }
50
+ catch (exc) {
51
+ if (exc instanceof base_1.QuotaExceededError) {
52
+ if (onQuota === "raise")
53
+ throw exc;
54
+ quotaHit = true;
55
+ newFindings.push(cf);
56
+ continue;
57
+ }
58
+ throw exc;
59
+ }
60
+ if (v.verdict === "rejected")
61
+ continue; // drop
62
+ const newConfidence = v.verdict === "confirmed" ? Math.max(cf.finding.confidence, 0.95) : cf.finding.confidence;
63
+ newFindings.push({
64
+ row: cf.row,
65
+ column: cf.column,
66
+ cellValue: cf.cellValue,
67
+ finding: {
68
+ ...cf.finding,
69
+ confidence: newConfidence,
70
+ context: {
71
+ ...cf.finding.context,
72
+ verified: true,
73
+ llm_verdict: v.verdict,
74
+ llm_confidence: v.confidence,
75
+ llm_reason: v.reason,
76
+ llm_cached: v.cached,
77
+ },
78
+ },
79
+ });
80
+ }
81
+ return {
82
+ rowsScanned: result.rowsScanned,
83
+ columnsScanned: result.columnsScanned,
84
+ detectorsUsed: result.detectorsUsed,
85
+ findings: newFindings,
86
+ ...rebuildSummary(newFindings),
87
+ };
88
+ }
89
+ //# sourceMappingURL=verification.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verification.js","sourceRoot":"","sources":["../src/verification.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * LLM verification interface and shared types.
3
+ */
4
+ /** Outcome of an LLM second-pass review. */
5
+ export type Verdict = "confirmed" | "rejected" | "uncertain";
6
+ /** Outcome of verifying one finding. */
7
+ export interface VerificationResult {
8
+ verdict: Verdict;
9
+ /** LLM's own confidence in the verdict, 0..1. */
10
+ confidence: number;
11
+ /** One-sentence rationale. */
12
+ reason: string;
13
+ /** True when the verdict was served from disk cache. */
14
+ cached: boolean;
15
+ }
16
+ /** Short, human-readable description of each detector's claim. */
17
+ export declare const DETECTOR_DESCRIPTIONS: Record<string, string>;
18
+ /** Abstract base for second-pass LLM verifiers. */
19
+ export interface LLMVerifier {
20
+ verify(detector: string, value: string, context: string): Promise<VerificationResult>;
21
+ close(): void;
22
+ }
23
+ /** Thrown when Gemini returns 429 (quota / rate limit exceeded). */
24
+ export declare class QuotaExceededError extends Error {
25
+ constructor(message: string);
26
+ }
27
+ //# sourceMappingURL=base.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/verifiers/base.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,4CAA4C;AAC5C,MAAM,MAAM,OAAO,GAAG,WAAW,GAAG,UAAU,GAAG,WAAW,CAAC;AAE7D,wCAAwC;AACxC,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,iDAAiD;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,wDAAwD;IACxD,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,kEAAkE;AAClE,eAAO,MAAM,qBAAqB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAOxD,CAAC;AAEF,mDAAmD;AACnD,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAAC;IACtF,KAAK,IAAI,IAAI,CAAC;CACf;AAED,oEAAoE;AACpE,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,EAAE,MAAM;CAI5B"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ /**
3
+ * LLM verification interface and shared types.
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.QuotaExceededError = exports.DETECTOR_DESCRIPTIONS = void 0;
7
+ /** Short, human-readable description of each detector's claim. */
8
+ exports.DETECTOR_DESCRIPTIONS = {
9
+ ird: "an NZ Inland Revenue (IRD) tax identification number",
10
+ nhi: "an NZ National Health Index (NHI) patient identifier",
11
+ driver_licence: "an NZ driver licence number issued by Waka Kotahi",
12
+ phone: "an NZ phone number",
13
+ address: "an NZ street address",
14
+ maori_name: "a te reo Māori personal name",
15
+ };
16
+ /** Thrown when Gemini returns 429 (quota / rate limit exceeded). */
17
+ class QuotaExceededError extends Error {
18
+ constructor(message) {
19
+ super(message);
20
+ this.name = "QuotaExceededError";
21
+ }
22
+ }
23
+ exports.QuotaExceededError = QuotaExceededError;
24
+ //# sourceMappingURL=base.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/verifiers/base.ts"],"names":[],"mappings":";AAAA;;GAEG;;;AAgBH,kEAAkE;AACrD,QAAA,qBAAqB,GAA2B;IAC3D,GAAG,EAAE,sDAAsD;IAC3D,GAAG,EAAE,sDAAsD;IAC3D,cAAc,EAAE,mDAAmD;IACnE,KAAK,EAAE,oBAAoB;IAC3B,OAAO,EAAE,sBAAsB;IAC/B,UAAU,EAAE,8BAA8B;CAC3C,CAAC;AAQF,oEAAoE;AACpE,MAAa,kBAAmB,SAAQ,KAAK;IAC3C,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;IACnC,CAAC;CACF;AALD,gDAKC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * JSON-file-backed cache for LLM verification results.
3
+ *
4
+ * Re-running the auditor on the same dataset must not re-burn quota. The
5
+ * cache key is a SHA-256 hash of (detector, value, context) so identical
6
+ * values in identical context windows return immediately without an API
7
+ * call.
8
+ *
9
+ * A JSON file is used instead of SQLite to keep the package zero-native-dep
10
+ * (no compilation required on install). For our single-process,
11
+ * single-user audit workflow, this is sufficient.
12
+ */
13
+ import type { VerificationResult } from "./base";
14
+ export declare class VerificationCache {
15
+ private readonly filePath;
16
+ private data;
17
+ constructor(filePath: string);
18
+ get(detector: string, value: string, context: string): VerificationResult | null;
19
+ put(detector: string, value: string, context: string, result: VerificationResult): void;
20
+ private flush;
21
+ close(): void;
22
+ }
23
+ //# sourceMappingURL=cache.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cache.d.ts","sourceRoot":"","sources":["../../src/verifiers/cache.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,kBAAkB,EAAW,MAAM,QAAQ,CAAC;AAc1D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,IAAI,CAA8B;gBAE9B,QAAQ,EAAE,MAAM;IAe5B,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,kBAAkB,GAAG,IAAI;IAYhF,GAAG,CACD,QAAQ,EAAE,MAAM,EAChB,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,kBAAkB,GACzB,IAAI;IAWP,OAAO,CAAC,KAAK;IAIb,KAAK,IAAI,IAAI;CAGd"}