usertrust 0.1.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 (149) hide show
  1. package/dist/audit/canonical.d.ts +7 -0
  2. package/dist/audit/canonical.d.ts.map +1 -0
  3. package/dist/audit/canonical.js +24 -0
  4. package/dist/audit/canonical.js.map +1 -0
  5. package/dist/audit/chain.d.ts +33 -0
  6. package/dist/audit/chain.d.ts.map +1 -0
  7. package/dist/audit/chain.js +285 -0
  8. package/dist/audit/chain.js.map +1 -0
  9. package/dist/audit/entropy.d.ts +95 -0
  10. package/dist/audit/entropy.d.ts.map +1 -0
  11. package/dist/audit/entropy.js +229 -0
  12. package/dist/audit/entropy.js.map +1 -0
  13. package/dist/audit/merkle.d.ts +87 -0
  14. package/dist/audit/merkle.d.ts.map +1 -0
  15. package/dist/audit/merkle.js +315 -0
  16. package/dist/audit/merkle.js.map +1 -0
  17. package/dist/audit/rotation.d.ts +61 -0
  18. package/dist/audit/rotation.d.ts.map +1 -0
  19. package/dist/audit/rotation.js +160 -0
  20. package/dist/audit/rotation.js.map +1 -0
  21. package/dist/audit/verify.d.ts +20 -0
  22. package/dist/audit/verify.d.ts.map +1 -0
  23. package/dist/audit/verify.js +73 -0
  24. package/dist/audit/verify.js.map +1 -0
  25. package/dist/board/board.d.ts +67 -0
  26. package/dist/board/board.d.ts.map +1 -0
  27. package/dist/board/board.js +191 -0
  28. package/dist/board/board.js.map +1 -0
  29. package/dist/board/concerns.d.ts +59 -0
  30. package/dist/board/concerns.d.ts.map +1 -0
  31. package/dist/board/concerns.js +149 -0
  32. package/dist/board/concerns.js.map +1 -0
  33. package/dist/board/director.d.ts +49 -0
  34. package/dist/board/director.d.ts.map +1 -0
  35. package/dist/board/director.js +127 -0
  36. package/dist/board/director.js.map +1 -0
  37. package/dist/cli/health.d.ts +8 -0
  38. package/dist/cli/health.d.ts.map +1 -0
  39. package/dist/cli/health.js +119 -0
  40. package/dist/cli/health.js.map +1 -0
  41. package/dist/cli/init.d.ts +8 -0
  42. package/dist/cli/init.d.ts.map +1 -0
  43. package/dist/cli/init.js +67 -0
  44. package/dist/cli/init.js.map +1 -0
  45. package/dist/cli/inspect.d.ts +8 -0
  46. package/dist/cli/inspect.d.ts.map +1 -0
  47. package/dist/cli/inspect.js +114 -0
  48. package/dist/cli/inspect.js.map +1 -0
  49. package/dist/cli/main.d.ts +3 -0
  50. package/dist/cli/main.d.ts.map +1 -0
  51. package/dist/cli/main.js +35 -0
  52. package/dist/cli/main.js.map +1 -0
  53. package/dist/cli/snapshot.d.ts +10 -0
  54. package/dist/cli/snapshot.d.ts.map +1 -0
  55. package/dist/cli/snapshot.js +61 -0
  56. package/dist/cli/snapshot.js.map +1 -0
  57. package/dist/cli/tb.d.ts +8 -0
  58. package/dist/cli/tb.d.ts.map +1 -0
  59. package/dist/cli/tb.js +43 -0
  60. package/dist/cli/tb.js.map +1 -0
  61. package/dist/cli/verify.d.ts +7 -0
  62. package/dist/cli/verify.d.ts.map +1 -0
  63. package/dist/cli/verify.js +32 -0
  64. package/dist/cli/verify.js.map +1 -0
  65. package/dist/config.d.ts +12 -0
  66. package/dist/config.d.ts.map +1 -0
  67. package/dist/config.js +34 -0
  68. package/dist/config.js.map +1 -0
  69. package/dist/detect.d.ts +18 -0
  70. package/dist/detect.d.ts.map +1 -0
  71. package/dist/detect.js +49 -0
  72. package/dist/detect.js.map +1 -0
  73. package/dist/govern.d.ts +75 -0
  74. package/dist/govern.d.ts.map +1 -0
  75. package/dist/govern.js +581 -0
  76. package/dist/govern.js.map +1 -0
  77. package/dist/index.d.ts +6 -0
  78. package/dist/index.d.ts.map +1 -0
  79. package/dist/index.js +8 -0
  80. package/dist/index.js.map +1 -0
  81. package/dist/ledger/client.d.ts +89 -0
  82. package/dist/ledger/client.d.ts.map +1 -0
  83. package/dist/ledger/client.js +417 -0
  84. package/dist/ledger/client.js.map +1 -0
  85. package/dist/ledger/engine.d.ts +68 -0
  86. package/dist/ledger/engine.d.ts.map +1 -0
  87. package/dist/ledger/engine.js +142 -0
  88. package/dist/ledger/engine.js.map +1 -0
  89. package/dist/ledger/pricing.d.ts +35 -0
  90. package/dist/ledger/pricing.d.ts.map +1 -0
  91. package/dist/ledger/pricing.js +142 -0
  92. package/dist/ledger/pricing.js.map +1 -0
  93. package/dist/memory/patterns.d.ts +35 -0
  94. package/dist/memory/patterns.d.ts.map +1 -0
  95. package/dist/memory/patterns.js +152 -0
  96. package/dist/memory/patterns.js.map +1 -0
  97. package/dist/policy/decay.d.ts +95 -0
  98. package/dist/policy/decay.d.ts.map +1 -0
  99. package/dist/policy/decay.js +133 -0
  100. package/dist/policy/decay.js.map +1 -0
  101. package/dist/policy/default-rules.d.ts +21 -0
  102. package/dist/policy/default-rules.d.ts.map +1 -0
  103. package/dist/policy/default-rules.js +60 -0
  104. package/dist/policy/default-rules.js.map +1 -0
  105. package/dist/policy/gate.d.ts +116 -0
  106. package/dist/policy/gate.d.ts.map +1 -0
  107. package/dist/policy/gate.js +227 -0
  108. package/dist/policy/gate.js.map +1 -0
  109. package/dist/policy/pii.d.ts +28 -0
  110. package/dist/policy/pii.d.ts.map +1 -0
  111. package/dist/policy/pii.js +124 -0
  112. package/dist/policy/pii.js.map +1 -0
  113. package/dist/proxy.d.ts +33 -0
  114. package/dist/proxy.d.ts.map +1 -0
  115. package/dist/proxy.js +36 -0
  116. package/dist/proxy.js.map +1 -0
  117. package/dist/resilience/circuit.d.ts +87 -0
  118. package/dist/resilience/circuit.d.ts.map +1 -0
  119. package/dist/resilience/circuit.js +167 -0
  120. package/dist/resilience/circuit.js.map +1 -0
  121. package/dist/resilience/scope.d.ts +97 -0
  122. package/dist/resilience/scope.d.ts.map +1 -0
  123. package/dist/resilience/scope.js +244 -0
  124. package/dist/resilience/scope.js.map +1 -0
  125. package/dist/shared/constants.d.ts +7 -0
  126. package/dist/shared/constants.d.ts.map +1 -0
  127. package/dist/shared/constants.js +7 -0
  128. package/dist/shared/constants.js.map +1 -0
  129. package/dist/shared/errors.d.ts +31 -0
  130. package/dist/shared/errors.d.ts.map +1 -0
  131. package/dist/shared/errors.js +61 -0
  132. package/dist/shared/errors.js.map +1 -0
  133. package/dist/shared/ids.d.ts +7 -0
  134. package/dist/shared/ids.d.ts.map +1 -0
  135. package/dist/shared/ids.js +31 -0
  136. package/dist/shared/ids.js.map +1 -0
  137. package/dist/shared/types.d.ts +162 -0
  138. package/dist/shared/types.d.ts.map +1 -0
  139. package/dist/shared/types.js +41 -0
  140. package/dist/shared/types.js.map +1 -0
  141. package/dist/snapshot/checkpoint.d.ts +22 -0
  142. package/dist/snapshot/checkpoint.d.ts.map +1 -0
  143. package/dist/snapshot/checkpoint.js +172 -0
  144. package/dist/snapshot/checkpoint.js.map +1 -0
  145. package/dist/streaming.d.ts +44 -0
  146. package/dist/streaming.d.ts.map +1 -0
  147. package/dist/streaming.js +123 -0
  148. package/dist/streaming.js.map +1 -0
  149. package/package.json +54 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Audit Rotation — Daily receipt indexing
3
+ *
4
+ * Writes individual audit receipts to date-organized directories under
5
+ * the vault's audit directory. Maintains a bounded index.json for fast
6
+ * receipt lookup.
7
+ *
8
+ * Structure: .usertrust/audit/<kind>/<YYYY-MM-DD>/<receiptId>.json
9
+ *
10
+ * Adapted from Turf governance audit.ts (receipt emission + daily rotation).
11
+ */
12
+ export interface AuditReceipt {
13
+ v: number;
14
+ ts: string;
15
+ kind: string;
16
+ subsystem: string;
17
+ actor: string;
18
+ correlationId?: string;
19
+ data: Record<string, unknown>;
20
+ }
21
+ export interface WriteReceiptInput {
22
+ kind: string;
23
+ subsystem: string;
24
+ actor: string;
25
+ correlationId?: string;
26
+ data: Record<string, unknown>;
27
+ }
28
+ export interface IndexEntry {
29
+ receiptId: string;
30
+ kind: string;
31
+ ts: string;
32
+ actor: string;
33
+ correlationId?: string;
34
+ path: string;
35
+ }
36
+ /**
37
+ * Write an audit receipt to the daily-rotated directory structure.
38
+ *
39
+ * @param vaultPath - Root vault directory (parent of .usertools/)
40
+ * @param input - Receipt data to write
41
+ * @param indexLimit - Maximum index entries (default: 10000)
42
+ * @returns The written receipt, or undefined if the write failed
43
+ */
44
+ export declare function writeReceipt(vaultPath: string, input: WriteReceiptInput, indexLimit?: number): AuditReceipt | undefined;
45
+ /**
46
+ * List all receipts of a given kind (optionally filtered by date).
47
+ *
48
+ * @param vaultPath - Root vault directory
49
+ * @param kind - Receipt kind to list
50
+ * @param date - Optional date filter (YYYY-MM-DD)
51
+ * @returns Array of receipts, sorted newest-first
52
+ */
53
+ export declare function listReceipts(vaultPath: string, kind: string, date?: string): AuditReceipt[];
54
+ /**
55
+ * Load the audit index.
56
+ *
57
+ * @param vaultPath - Root vault directory
58
+ * @returns Array of index entries
59
+ */
60
+ export declare function loadIndex(vaultPath: string): IndexEntry[];
61
+ //# sourceMappingURL=rotation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.d.ts","sourceRoot":"","sources":["../../src/audit/rotation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AASH,MAAM,WAAW,YAAY;IAC5B,CAAC,EAAE,MAAM,CAAC;IACV,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,iBAAiB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC9B;AAED,MAAM,WAAW,UAAU;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,MAAM,CAAC;CACb;AA4CD;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAC3B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,iBAAiB,EACxB,UAAU,SAAS,GACjB,YAAY,GAAG,SAAS,CA6C1B;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE,CAoC3F;AAED;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,SAAS,EAAE,MAAM,GAAG,UAAU,EAAE,CAUzD"}
@@ -0,0 +1,160 @@
1
+ /**
2
+ * Audit Rotation — Daily receipt indexing
3
+ *
4
+ * Writes individual audit receipts to date-organized directories under
5
+ * the vault's audit directory. Maintains a bounded index.json for fast
6
+ * receipt lookup.
7
+ *
8
+ * Structure: .usertrust/audit/<kind>/<YYYY-MM-DD>/<receiptId>.json
9
+ *
10
+ * Adapted from Turf governance audit.ts (receipt emission + daily rotation).
11
+ */
12
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
13
+ import { join } from "node:path";
14
+ import { AUDIT_DIR, RECEIPT_VERSION, VAULT_DIR } from "../shared/constants.js";
15
+ import { trustId } from "../shared/ids.js";
16
+ // ── Helpers ──
17
+ function getTodayDate() {
18
+ const now = new Date();
19
+ return now.toISOString().split("T")[0] ?? "unknown";
20
+ }
21
+ function getDailyDir(auditRoot, kind) {
22
+ return join(auditRoot, kind, getTodayDate());
23
+ }
24
+ function getIndexPath(auditRoot) {
25
+ return join(auditRoot, "index.json");
26
+ }
27
+ // ── Index management ──
28
+ function updateIndex(auditRoot, entry, indexLimit) {
29
+ try {
30
+ const indexPath = getIndexPath(auditRoot);
31
+ let index = [];
32
+ if (existsSync(indexPath)) {
33
+ const raw = readFileSync(indexPath, "utf-8");
34
+ index = JSON.parse(raw);
35
+ }
36
+ index.push(entry);
37
+ // Keep index bounded
38
+ if (index.length > indexLimit) {
39
+ index = index.slice(-indexLimit);
40
+ }
41
+ writeFileSync(indexPath, JSON.stringify(index, null, "\t"));
42
+ }
43
+ catch {
44
+ // Index update failure is non-fatal
45
+ }
46
+ }
47
+ // ── Public API ──
48
+ /**
49
+ * Write an audit receipt to the daily-rotated directory structure.
50
+ *
51
+ * @param vaultPath - Root vault directory (parent of .usertools/)
52
+ * @param input - Receipt data to write
53
+ * @param indexLimit - Maximum index entries (default: 10000)
54
+ * @returns The written receipt, or undefined if the write failed
55
+ */
56
+ export function writeReceipt(vaultPath, input, indexLimit = 10_000) {
57
+ try {
58
+ const auditRoot = join(vaultPath, VAULT_DIR, AUDIT_DIR);
59
+ const receiptId = trustId("rcpt");
60
+ const ts = new Date().toISOString();
61
+ const receipt = {
62
+ v: RECEIPT_VERSION,
63
+ ts,
64
+ kind: input.kind,
65
+ subsystem: input.subsystem,
66
+ actor: input.actor,
67
+ ...(input.correlationId !== undefined ? { correlationId: input.correlationId } : {}),
68
+ data: {
69
+ receiptId,
70
+ ...input.data,
71
+ },
72
+ };
73
+ // Write individual receipt file with daily rotation
74
+ const dailyDir = getDailyDir(auditRoot, input.kind);
75
+ if (!existsSync(dailyDir)) {
76
+ mkdirSync(dailyDir, { recursive: true });
77
+ }
78
+ const receiptFile = join(dailyDir, `${receiptId}.json`);
79
+ writeFileSync(receiptFile, JSON.stringify(receipt, null, "\t"));
80
+ // Update index
81
+ updateIndex(auditRoot, {
82
+ receiptId,
83
+ kind: input.kind,
84
+ ts,
85
+ actor: input.actor,
86
+ ...(input.correlationId !== undefined ? { correlationId: input.correlationId } : {}),
87
+ path: `${input.kind}/${getTodayDate()}/${receiptId}.json`,
88
+ }, indexLimit);
89
+ return receipt;
90
+ }
91
+ catch {
92
+ return undefined;
93
+ }
94
+ }
95
+ /**
96
+ * List all receipts of a given kind (optionally filtered by date).
97
+ *
98
+ * @param vaultPath - Root vault directory
99
+ * @param kind - Receipt kind to list
100
+ * @param date - Optional date filter (YYYY-MM-DD)
101
+ * @returns Array of receipts, sorted newest-first
102
+ */
103
+ export function listReceipts(vaultPath, kind, date) {
104
+ const kindDir = join(vaultPath, VAULT_DIR, AUDIT_DIR, kind);
105
+ if (!existsSync(kindDir))
106
+ return [];
107
+ try {
108
+ const results = [];
109
+ const entries = readdirSync(kindDir, { withFileTypes: true });
110
+ for (const entry of entries) {
111
+ if (entry.isDirectory()) {
112
+ if (date && entry.name !== date)
113
+ continue;
114
+ const dateDir = join(kindDir, entry.name);
115
+ const files = readdirSync(dateDir).filter((f) => f.endsWith(".json"));
116
+ for (const f of files) {
117
+ try {
118
+ const raw = readFileSync(join(dateDir, f), "utf-8");
119
+ results.push(JSON.parse(raw));
120
+ }
121
+ catch {
122
+ // Skip invalid files
123
+ }
124
+ }
125
+ }
126
+ else if (entry.isFile() && entry.name.endsWith(".json")) {
127
+ try {
128
+ const raw = readFileSync(join(kindDir, entry.name), "utf-8");
129
+ results.push(JSON.parse(raw));
130
+ }
131
+ catch {
132
+ // Skip invalid files
133
+ }
134
+ }
135
+ }
136
+ return results.sort((a, b) => new Date(b.ts).getTime() - new Date(a.ts).getTime());
137
+ }
138
+ catch {
139
+ return [];
140
+ }
141
+ }
142
+ /**
143
+ * Load the audit index.
144
+ *
145
+ * @param vaultPath - Root vault directory
146
+ * @returns Array of index entries
147
+ */
148
+ export function loadIndex(vaultPath) {
149
+ const indexPath = getIndexPath(join(vaultPath, VAULT_DIR, AUDIT_DIR));
150
+ if (!existsSync(indexPath))
151
+ return [];
152
+ try {
153
+ const raw = readFileSync(indexPath, "utf-8");
154
+ return JSON.parse(raw);
155
+ }
156
+ catch {
157
+ return [];
158
+ }
159
+ }
160
+ //# sourceMappingURL=rotation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rotation.js","sourceRoot":"","sources":["../../src/audit/rotation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Audit Chain Verifier
3
+ *
4
+ * Reads a JSONL audit log and verifies:
5
+ * 1. Each event's hash matches the SHA-256 of its canonical representation
6
+ * 2. Each event's previousHash links to the prior event's hash
7
+ * 3. The first event chains from GENESIS_HASH
8
+ *
9
+ * Adapted from usertools-stealth governance/audit/verifier.ts — removes
10
+ * flushAuditWriter dependency (verifier should NOT flush the writer).
11
+ */
12
+ export interface ChainVerificationResult {
13
+ valid: boolean;
14
+ eventsVerified: number;
15
+ errors: string[];
16
+ latestHash: string;
17
+ verifiedAt: string;
18
+ }
19
+ export declare function verifyChain(logPath: string): ChainVerificationResult;
20
+ //# sourceMappingURL=verify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.d.ts","sourceRoot":"","sources":["../../src/audit/verify.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,MAAM,WAAW,uBAAuB;IACvC,KAAK,EAAE,OAAO,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACnB;AAED,wBAAgB,WAAW,CAAC,OAAO,EAAE,MAAM,GAAG,uBAAuB,CAuEpE"}
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Audit Chain Verifier
3
+ *
4
+ * Reads a JSONL audit log and verifies:
5
+ * 1. Each event's hash matches the SHA-256 of its canonical representation
6
+ * 2. Each event's previousHash links to the prior event's hash
7
+ * 3. The first event chains from GENESIS_HASH
8
+ *
9
+ * Adapted from usertools-stealth governance/audit/verifier.ts — removes
10
+ * flushAuditWriter dependency (verifier should NOT flush the writer).
11
+ */
12
+ import { createHash } from "node:crypto";
13
+ import { existsSync, readFileSync } from "node:fs";
14
+ import { GENESIS_HASH } from "../shared/constants.js";
15
+ import { canonicalize } from "./canonical.js";
16
+ export function verifyChain(logPath) {
17
+ const errors = [];
18
+ if (!existsSync(logPath)) {
19
+ return {
20
+ valid: true,
21
+ eventsVerified: 0,
22
+ errors: [],
23
+ latestHash: GENESIS_HASH,
24
+ verifiedAt: new Date().toISOString(),
25
+ };
26
+ }
27
+ const content = readFileSync(logPath, "utf-8").trim();
28
+ if (!content) {
29
+ return {
30
+ valid: true,
31
+ eventsVerified: 0,
32
+ errors: [],
33
+ latestHash: GENESIS_HASH,
34
+ verifiedAt: new Date().toISOString(),
35
+ };
36
+ }
37
+ const lines = content.split("\n").filter((l) => l.trim());
38
+ let expectedPreviousHash = GENESIS_HASH;
39
+ let latestHash = GENESIS_HASH;
40
+ for (let i = 0; i < lines.length; i++) {
41
+ const line = lines[i];
42
+ let event;
43
+ try {
44
+ event = JSON.parse(line);
45
+ }
46
+ catch (parseErr) {
47
+ errors.push(`Event ${i + 1}: malformed JSON — ${parseErr instanceof Error ? parseErr.message : String(parseErr)}`);
48
+ expectedPreviousHash = "";
49
+ continue;
50
+ }
51
+ if (event.previousHash !== expectedPreviousHash) {
52
+ errors.push(`Event ${i + 1} (${event.id}): previousHash mismatch. ` +
53
+ `Expected ${expectedPreviousHash}, got ${event.previousHash}`);
54
+ }
55
+ const { hash: storedHash, ...eventWithoutHash } = event;
56
+ const canonical = canonicalize(eventWithoutHash);
57
+ const computedHash = createHash("sha256").update(canonical).digest("hex");
58
+ if (storedHash !== computedHash) {
59
+ errors.push(`Event ${i + 1} (${event.id}): hash mismatch. ` +
60
+ `Expected ${computedHash}, got ${storedHash}`);
61
+ }
62
+ expectedPreviousHash = storedHash;
63
+ latestHash = storedHash;
64
+ }
65
+ return {
66
+ valid: errors.length === 0,
67
+ eventsVerified: lines.length,
68
+ errors,
69
+ latestHash,
70
+ verifiedAt: new Date().toISOString(),
71
+ };
72
+ }
73
+ //# sourceMappingURL=verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"verify.js","sourceRoot":"","sources":["../../src/audit/verify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Board of Directors — Board Coordination
3
+ *
4
+ * Coordinates two isolated Directors for democratic oversight.
5
+ * Decision matrix:
6
+ * Both APPROVE → approved
7
+ * Unanimous VETO → blocked (requires human escalation)
8
+ * VETO + APPROVE → escalated (conflict, human review)
9
+ * Both ABSTAIN → escalated (insufficient confidence)
10
+ *
11
+ * Persists JSONL session history with a 100-review buffer.
12
+ */
13
+ import type { BoardDecision } from "../shared/types.js";
14
+ import type { BoardRequest } from "./concerns.js";
15
+ import type { DirectorReview } from "./director.js";
16
+ export interface BoardReviewResult {
17
+ request: BoardRequest & {
18
+ reviewId: string;
19
+ requestedAt: string;
20
+ };
21
+ reviews: DirectorReview[];
22
+ decision: BoardDecision;
23
+ reasoning: string;
24
+ requiresHumanEscalation: boolean;
25
+ escalationReason?: string | undefined;
26
+ decidedAt: string;
27
+ }
28
+ export interface BoardOpts {
29
+ /** Maximum completed reviews to keep in the session file (default 100) */
30
+ maxHistory?: number | undefined;
31
+ }
32
+ export interface Board {
33
+ /**
34
+ * Submit, review, and decide in one synchronous call.
35
+ * Returns the full review result.
36
+ */
37
+ reviewNow(decisionType: string, actor: string, description: string, options?: {
38
+ scope?: string[];
39
+ context?: Record<string, unknown>;
40
+ }): BoardReviewResult;
41
+ /** Get recent completed reviews. */
42
+ getRecentReviews(limit?: number): BoardReviewResult[];
43
+ /** Get aggregate stats. */
44
+ getStats(): BoardStats;
45
+ }
46
+ export interface BoardStats {
47
+ totalReviews: number;
48
+ approved: number;
49
+ blocked: number;
50
+ escalated: number;
51
+ }
52
+ /**
53
+ * Determine final Board decision from Director reviews.
54
+ */
55
+ export declare function determineDecision(reviews: DirectorReview[]): {
56
+ decision: BoardDecision;
57
+ requiresHumanEscalation: boolean;
58
+ escalationReason?: string;
59
+ };
60
+ /**
61
+ * Create a Board of Directors instance backed by a vault directory.
62
+ *
63
+ * @param vaultPath — absolute or relative path to `.usertools/` (or custom vault)
64
+ * @param opts — optional configuration
65
+ */
66
+ export declare function createBoard(vaultPath: string, opts?: BoardOpts): Board;
67
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/board/board.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,MAAM,WAAW,iBAAiB;IACjC,OAAO,EAAE,YAAY,GAAG;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,QAAQ,EAAE,aAAa,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;IAClB,uBAAuB,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,MAAM,CAAC;CAClB;AASD,MAAM,WAAW,SAAS;IACzB,0EAA0E;IAC1E,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAED,MAAM,WAAW,KAAK;IACrB;;;OAGG;IACH,SAAS,CACR,YAAY,EAAE,MAAM,EACpB,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,OAAO,CAAC,EAAE;QACT,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;QACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAClC,GACC,iBAAiB,CAAC;IAErB,oCAAoC;IACpC,gBAAgB,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAAC;IAEtD,2BAA2B;IAC3B,QAAQ,IAAI,UAAU,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IAC1B,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;CAClB;AAID;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,cAAc,EAAE,GAAG;IAC7D,QAAQ,EAAE,aAAa,CAAC;IACxB,uBAAuB,EAAE,OAAO,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC1B,CA+CA;AA2ED;;;;;GAKG;AACH,wBAAgB,WAAW,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,SAAS,GAAG,KAAK,CAiEtE"}
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Board of Directors — Board Coordination
3
+ *
4
+ * Coordinates two isolated Directors for democratic oversight.
5
+ * Decision matrix:
6
+ * Both APPROVE → approved
7
+ * Unanimous VETO → blocked (requires human escalation)
8
+ * VETO + APPROVE → escalated (conflict, human review)
9
+ * Both ABSTAIN → escalated (insufficient confidence)
10
+ *
11
+ * Persists JSONL session history with a 100-review buffer.
12
+ */
13
+ import { appendFileSync, existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
14
+ import { join } from "node:path";
15
+ import { trustId } from "../shared/ids.js";
16
+ import { listDirectors, reviewDecision } from "./director.js";
17
+ // ── Decision Logic ──
18
+ /**
19
+ * Determine final Board decision from Director reviews.
20
+ */
21
+ export function determineDecision(reviews) {
22
+ const votes = reviews.map((r) => r.vote);
23
+ const vetoCount = votes.filter((v) => v === "veto").length;
24
+ const approveCount = votes.filter((v) => v === "approve").length;
25
+ const abstainCount = votes.filter((v) => v === "abstain").length;
26
+ // Unanimous veto → blocked
27
+ if (vetoCount === reviews.length) {
28
+ return {
29
+ decision: "blocked",
30
+ requiresHumanEscalation: true,
31
+ escalationReason: "Unanimous Board veto - all Directors flagged critical concerns",
32
+ };
33
+ }
34
+ // Any veto with any approve → conflict, escalate
35
+ if (vetoCount > 0 && approveCount > 0) {
36
+ return {
37
+ decision: "escalated",
38
+ requiresHumanEscalation: true,
39
+ escalationReason: "Director disagreement - veto conflicts with approval",
40
+ };
41
+ }
42
+ // Both abstain → need more info
43
+ if (abstainCount === reviews.length) {
44
+ return {
45
+ decision: "escalated",
46
+ requiresHumanEscalation: true,
47
+ escalationReason: "Both Directors abstained - insufficient confidence",
48
+ };
49
+ }
50
+ // Single veto with abstain → blocked but escalate
51
+ if (vetoCount > 0) {
52
+ return {
53
+ decision: "blocked",
54
+ requiresHumanEscalation: true,
55
+ escalationReason: "Director veto with abstention",
56
+ };
57
+ }
58
+ // Approved (both approve, or approve + abstain)
59
+ return {
60
+ decision: "approved",
61
+ requiresHumanEscalation: false,
62
+ };
63
+ }
64
+ /**
65
+ * Combine Director reasoning into final reasoning string.
66
+ */
67
+ function combineReasoning(reviews, decision) {
68
+ const parts = reviews.map((r) => `[${r.directorId}] ${r.reasoning}`);
69
+ const prefix = decision === "approved"
70
+ ? "Board APPROVED:"
71
+ : decision === "blocked"
72
+ ? "Board BLOCKED:"
73
+ : "Board ESCALATED:";
74
+ return `${prefix} ${parts.join(" | ")}`;
75
+ }
76
+ // ── Session Persistence ──
77
+ function boardDir(vaultPath) {
78
+ return join(vaultPath, "board");
79
+ }
80
+ function sessionPath(vaultPath) {
81
+ return join(boardDir(vaultPath), "session.json");
82
+ }
83
+ function historyPath(vaultPath) {
84
+ return join(boardDir(vaultPath), "history.jsonl");
85
+ }
86
+ function ensureDir(vaultPath) {
87
+ const dir = boardDir(vaultPath);
88
+ if (!existsSync(dir)) {
89
+ mkdirSync(dir, { recursive: true });
90
+ }
91
+ }
92
+ function loadSession(vaultPath) {
93
+ ensureDir(vaultPath);
94
+ const file = sessionPath(vaultPath);
95
+ if (!existsSync(file)) {
96
+ const now = new Date().toISOString();
97
+ return {
98
+ pendingReviews: {},
99
+ completedReviews: [],
100
+ startedAt: now,
101
+ lastActivityAt: now,
102
+ };
103
+ }
104
+ try {
105
+ return JSON.parse(readFileSync(file, "utf-8"));
106
+ }
107
+ catch {
108
+ const now = new Date().toISOString();
109
+ return {
110
+ pendingReviews: {},
111
+ completedReviews: [],
112
+ startedAt: now,
113
+ lastActivityAt: now,
114
+ };
115
+ }
116
+ }
117
+ function saveSession(vaultPath, session) {
118
+ ensureDir(vaultPath);
119
+ session.lastActivityAt = new Date().toISOString();
120
+ writeFileSync(sessionPath(vaultPath), JSON.stringify(session, null, "\t"));
121
+ }
122
+ function appendHistory(vaultPath, result) {
123
+ ensureDir(vaultPath);
124
+ appendFileSync(historyPath(vaultPath), `${JSON.stringify(result)}\n`);
125
+ }
126
+ // ── Factory ──
127
+ /**
128
+ * Create a Board of Directors instance backed by a vault directory.
129
+ *
130
+ * @param vaultPath — absolute or relative path to `.usertools/` (or custom vault)
131
+ * @param opts — optional configuration
132
+ */
133
+ export function createBoard(vaultPath, opts) {
134
+ const maxHistory = opts?.maxHistory ?? 100;
135
+ return {
136
+ reviewNow(decisionType, actor, description, options) {
137
+ const reviewId = trustId("BR");
138
+ const request = {
139
+ reviewId,
140
+ decisionType,
141
+ actor,
142
+ description,
143
+ scope: options?.scope,
144
+ context: options?.context ?? {},
145
+ requestedAt: new Date().toISOString(),
146
+ };
147
+ // Each Director reviews independently
148
+ const directors = listDirectors();
149
+ const reviews = [];
150
+ for (const director of directors) {
151
+ reviews.push(reviewDecision(director.id, request));
152
+ }
153
+ // Determine final decision
154
+ const { decision, requiresHumanEscalation, escalationReason } = determineDecision(reviews);
155
+ const reasoning = combineReasoning(reviews, decision);
156
+ const result = {
157
+ request,
158
+ reviews,
159
+ decision,
160
+ reasoning,
161
+ requiresHumanEscalation,
162
+ escalationReason,
163
+ decidedAt: new Date().toISOString(),
164
+ };
165
+ // Persist
166
+ const session = loadSession(vaultPath);
167
+ session.completedReviews.push(result);
168
+ if (session.completedReviews.length > maxHistory) {
169
+ session.completedReviews = session.completedReviews.slice(-maxHistory);
170
+ }
171
+ saveSession(vaultPath, session);
172
+ appendHistory(vaultPath, result);
173
+ return result;
174
+ },
175
+ getRecentReviews(limit = 10) {
176
+ const session = loadSession(vaultPath);
177
+ return session.completedReviews.slice(-limit);
178
+ },
179
+ getStats() {
180
+ const session = loadSession(vaultPath);
181
+ const completed = session.completedReviews;
182
+ return {
183
+ totalReviews: completed.length,
184
+ approved: completed.filter((r) => r.decision === "approved").length,
185
+ blocked: completed.filter((r) => r.decision === "blocked").length,
186
+ escalated: completed.filter((r) => r.decision === "escalated").length,
187
+ };
188
+ },
189
+ };
190
+ }
191
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/board/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,59 @@
1
+ /**
2
+ * Concern Detection Library
3
+ *
4
+ * 6 pure-function detectors for Board of Directors oversight.
5
+ * Each detector: (request) => Concern | null
6
+ */
7
+ import type { ConcernType, PolicySeverity } from "../shared/types.js";
8
+ export interface Concern {
9
+ type: ConcernType;
10
+ severity: PolicySeverity;
11
+ description: string;
12
+ evidence: string;
13
+ }
14
+ export interface BoardRequest {
15
+ /** Type of decision under review */
16
+ decisionType: string;
17
+ /** Human-readable description of the action */
18
+ description: string;
19
+ /** File/resource scope affected */
20
+ scope?: string[] | undefined;
21
+ /** Arbitrary context for detection heuristics */
22
+ context: Record<string, unknown>;
23
+ }
24
+ /**
25
+ * Hallucination — absolute claims, factual assertions without evidence.
26
+ * Triggers on "always"/"never" overgeneralizations and policy overrides lacking justification.
27
+ */
28
+ export declare function detectHallucination(request: BoardRequest): Concern | null;
29
+ /**
30
+ * Bias — preferential routing, demographic skew.
31
+ * Triggers when a preferred worker is specified during scope expansion.
32
+ */
33
+ export declare function detectBias(request: BoardRequest): Concern | null;
34
+ /**
35
+ * Safety — credentials in scope, dangerous content.
36
+ * Scans scope paths and description for security-sensitive patterns.
37
+ */
38
+ export declare function detectSafety(request: BoardRequest): Concern | null;
39
+ /**
40
+ * Scope creep — root wildcards, unbounded scope.
41
+ * Triggers on root-level ** wildcards or excessive scope breadth (>10 patterns).
42
+ */
43
+ export declare function detectScopeCreep(request: BoardRequest): Concern | null;
44
+ /**
45
+ * Resource abuse — cost exceeds threshold, excessive token usage.
46
+ * Triggers when estimated cost exceeds $100 on resource-intensive operations.
47
+ */
48
+ export declare function detectResourceAbuse(request: BoardRequest): Concern | null;
49
+ /**
50
+ * Policy violation — explicit policy override attempts.
51
+ * Triggers on any policy_override decision type.
52
+ */
53
+ export declare function detectPolicyViolation(request: BoardRequest): Concern | null;
54
+ /**
55
+ * Run all concern detectors against a request.
56
+ * Returns every concern found (zero or more).
57
+ */
58
+ export declare function detectConcerns(request: BoardRequest): Concern[];
59
+ //# sourceMappingURL=concerns.d.ts.map