@mneme-ai/core 2.71.0 → 2.73.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.
- package/dist/diaspora/http_bridge.d.ts +9 -0
- package/dist/diaspora/http_bridge.d.ts.map +1 -1
- package/dist/diaspora/http_bridge.js +47 -16
- package/dist/diaspora/http_bridge.js.map +1 -1
- package/dist/polygraph/index.d.ts +4 -0
- package/dist/polygraph/index.d.ts.map +1 -1
- package/dist/polygraph/index.js +73 -14
- package/dist/polygraph/index.js.map +1 -1
- package/dist/protoplasm/super_quan/cull.d.ts +70 -0
- package/dist/protoplasm/super_quan/cull.d.ts.map +1 -0
- package/dist/protoplasm/super_quan/cull.js +218 -0
- package/dist/protoplasm/super_quan/cull.js.map +1 -0
- package/dist/protoplasm/super_quan/index.d.ts +6 -0
- package/dist/protoplasm/super_quan/index.d.ts.map +1 -1
- package/dist/protoplasm/super_quan/index.js +6 -0
- package/dist/protoplasm/super_quan/index.js.map +1 -1
- package/dist/protoplasm/super_quan/prism.d.ts +50 -0
- package/dist/protoplasm/super_quan/prism.d.ts.map +1 -0
- package/dist/protoplasm/super_quan/prism.js +231 -0
- package/dist/protoplasm/super_quan/prism.js.map +1 -0
- package/dist/protoplasm/super_quan/tide_guard.d.ts +71 -0
- package/dist/protoplasm/super_quan/tide_guard.d.ts.map +1 -0
- package/dist/protoplasm/super_quan/tide_guard.js +135 -0
- package/dist/protoplasm/super_quan/tide_guard.js.map +1 -0
- package/dist/protoplasm/super_quan/vulns2.test.d.ts +6 -0
- package/dist/protoplasm/super_quan/vulns2.test.d.ts.map +1 -0
- package/dist/protoplasm/super_quan/vulns2.test.js +164 -0
- package/dist/protoplasm/super_quan/vulns2.test.js.map +1 -0
- package/dist/release_gate/wiring_lag.d.ts.map +1 -1
- package/dist/release_gate/wiring_lag.js +16 -0
- package/dist/release_gate/wiring_lag.js.map +1 -1
- package/dist/truth_gate/claims.d.ts.map +1 -1
- package/dist/truth_gate/claims.js +28 -0
- package/dist/truth_gate/claims.js.map +1 -1
- package/dist/truth_gate/probes.d.ts.map +1 -1
- package/dist/truth_gate/probes.js +81 -0
- package/dist/truth_gate/probes.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 💀 CULL — Process Reaper via Antibody Pattern + Quorum
|
|
3
|
+
*
|
|
4
|
+
* Closes v2.70 Vuln #4: 6 mneme node processes still alive after single
|
|
5
|
+
* test session → resource exhaustion over time.
|
|
6
|
+
*
|
|
7
|
+
* STRATEGY: every Mneme process writes an antibody to .mneme/cull/<pid>.beat
|
|
8
|
+
* containing { startedAt, processType, antibody }. On startup, every
|
|
9
|
+
* Mneme process runs CULL phase:
|
|
10
|
+
*
|
|
11
|
+
* 1. Scan .mneme/cull/ for all heartbeats
|
|
12
|
+
* 2. Filter to processes with same processType as me
|
|
13
|
+
* 3. Verify each is actually alive (process.kill(pid, 0))
|
|
14
|
+
* 4. Remove dead heartbeats (cleanup)
|
|
15
|
+
* 5. Apply policy: if alive count > maxPerType, cull oldest siblings
|
|
16
|
+
* until count == maxPerType
|
|
17
|
+
*
|
|
18
|
+
* Policy modes:
|
|
19
|
+
* - "youngest-wins" newer process kills older siblings (default)
|
|
20
|
+
* - "oldest-wins" new process refuses to start if maxPerType reached
|
|
21
|
+
* - "quorum" requires majority of siblings to vote out a peer
|
|
22
|
+
*
|
|
23
|
+
* Wild twist: MITOSIS BUDGET — process can split (spawn child) but the
|
|
24
|
+
* child inherits parent's antibody. CULL never kills siblings with
|
|
25
|
+
* matching parent-antibody chain.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, readFileSync, writeFileSync, readdirSync, unlinkSync, mkdirSync } from "node:fs";
|
|
28
|
+
import { join } from "node:path";
|
|
29
|
+
import { createHmac } from "node:crypto";
|
|
30
|
+
export const DEFAULT_CULL = {
|
|
31
|
+
cullDir: ".mneme/cull",
|
|
32
|
+
policy: "youngest-wins",
|
|
33
|
+
maxPerType: { daemon: 1, "nucleus-daemon": 1, mcp: 2, bridge: 1, cli: 10 },
|
|
34
|
+
staleAfterMs: 60_000,
|
|
35
|
+
};
|
|
36
|
+
function aliveSafe(pid) {
|
|
37
|
+
if (pid === process.pid)
|
|
38
|
+
return true;
|
|
39
|
+
try {
|
|
40
|
+
process.kill(pid, 0);
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function killSafe(pid) {
|
|
48
|
+
if (pid === process.pid)
|
|
49
|
+
return false;
|
|
50
|
+
try {
|
|
51
|
+
process.kill(pid, "SIGTERM");
|
|
52
|
+
return true;
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
return false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export class Cull {
|
|
59
|
+
cfg;
|
|
60
|
+
constructor(cfg = DEFAULT_CULL) {
|
|
61
|
+
this.cfg = cfg;
|
|
62
|
+
}
|
|
63
|
+
/** Generate a stable per-process antibody. */
|
|
64
|
+
static makeAntibody() {
|
|
65
|
+
return createHmac("sha256", "mneme-cull").update(`${process.pid}::${process.hrtime.bigint()}::${Math.random()}`).digest("hex").slice(0, 12);
|
|
66
|
+
}
|
|
67
|
+
/** Write our heartbeat — call on startup + every N seconds. */
|
|
68
|
+
beat(processType, antibody, parentAntibody) {
|
|
69
|
+
mkdirSync(this.cfg.cullDir, { recursive: true });
|
|
70
|
+
const hb = {
|
|
71
|
+
pid: process.pid,
|
|
72
|
+
ppid: process.ppid,
|
|
73
|
+
startedAt: new Date().toISOString(),
|
|
74
|
+
processType,
|
|
75
|
+
antibody,
|
|
76
|
+
parentAntibody,
|
|
77
|
+
lastBeatAt: new Date().toISOString(),
|
|
78
|
+
};
|
|
79
|
+
writeFileSync(join(this.cfg.cullDir, `${process.pid}.beat`), JSON.stringify(hb), { encoding: "utf8" });
|
|
80
|
+
}
|
|
81
|
+
/** Update lastBeatAt timestamp only. */
|
|
82
|
+
refresh(antibody) {
|
|
83
|
+
const path = join(this.cfg.cullDir, `${process.pid}.beat`);
|
|
84
|
+
if (!existsSync(path))
|
|
85
|
+
return;
|
|
86
|
+
try {
|
|
87
|
+
const hb = JSON.parse(readFileSync(path, "utf8"));
|
|
88
|
+
hb.lastBeatAt = new Date().toISOString();
|
|
89
|
+
writeFileSync(path, JSON.stringify(hb), "utf8");
|
|
90
|
+
}
|
|
91
|
+
catch { /* */ }
|
|
92
|
+
}
|
|
93
|
+
/** Run CULL phase: scan, clean dead, enforce maxPerType. */
|
|
94
|
+
enforce(myProcessType, myAntibody) {
|
|
95
|
+
const reasoning = [];
|
|
96
|
+
if (!existsSync(this.cfg.cullDir)) {
|
|
97
|
+
mkdirSync(this.cfg.cullDir, { recursive: true });
|
|
98
|
+
}
|
|
99
|
+
const files = readdirSync(this.cfg.cullDir).filter((f) => f.endsWith(".beat"));
|
|
100
|
+
let scanned = 0, removedStale = 0, killedSiblings = 0, refusedToKill = 0;
|
|
101
|
+
const aliveOfMyType = [];
|
|
102
|
+
for (const f of files) {
|
|
103
|
+
scanned++;
|
|
104
|
+
const p = join(this.cfg.cullDir, f);
|
|
105
|
+
let hb;
|
|
106
|
+
try {
|
|
107
|
+
hb = JSON.parse(readFileSync(p, "utf8"));
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
try {
|
|
111
|
+
unlinkSync(p);
|
|
112
|
+
}
|
|
113
|
+
catch { /* */ }
|
|
114
|
+
removedStale++;
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
const ageMs = Date.now() - new Date(hb.lastBeatAt).getTime();
|
|
118
|
+
const stillAlive = aliveSafe(hb.pid);
|
|
119
|
+
if (!stillAlive || ageMs > this.cfg.staleAfterMs) {
|
|
120
|
+
try {
|
|
121
|
+
unlinkSync(p);
|
|
122
|
+
removedStale++;
|
|
123
|
+
reasoning.push(`removed stale heartbeat pid=${hb.pid} age=${ageMs}ms alive=${stillAlive}`);
|
|
124
|
+
}
|
|
125
|
+
catch { /* */ }
|
|
126
|
+
continue;
|
|
127
|
+
}
|
|
128
|
+
if (hb.processType === myProcessType)
|
|
129
|
+
aliveOfMyType.push(hb);
|
|
130
|
+
}
|
|
131
|
+
const limit = this.cfg.maxPerType[myProcessType] ?? 1;
|
|
132
|
+
if (aliveOfMyType.length > limit) {
|
|
133
|
+
// Sort by startedAt ASC — oldest first
|
|
134
|
+
aliveOfMyType.sort((a, b) => a.startedAt.localeCompare(b.startedAt));
|
|
135
|
+
const excess = aliveOfMyType.length - limit;
|
|
136
|
+
if (this.cfg.policy === "oldest-wins") {
|
|
137
|
+
// Refuse: don't kill anyone; report so caller can self-exit
|
|
138
|
+
refusedToKill = excess;
|
|
139
|
+
reasoning.push(`oldest-wins policy: ${excess} excess sibling(s) — caller should exit (suicide)`);
|
|
140
|
+
}
|
|
141
|
+
else if (this.cfg.policy === "quorum") {
|
|
142
|
+
// Need majority vote — for now, conservative: kill only if alone is "newest"
|
|
143
|
+
const myStartTime = aliveOfMyType.find((h) => h.pid === process.pid)?.startedAt ?? new Date().toISOString();
|
|
144
|
+
const olderThanMe = aliveOfMyType.filter((h) => h.startedAt < myStartTime).length;
|
|
145
|
+
if (olderThanMe > (aliveOfMyType.length / 2)) {
|
|
146
|
+
refusedToKill = excess;
|
|
147
|
+
reasoning.push(`quorum policy: I am newer than majority — refusing to kill`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
// I am the elder; cull oldest excess
|
|
151
|
+
for (let i = 0; i < excess; i++) {
|
|
152
|
+
const victim = aliveOfMyType[i];
|
|
153
|
+
if (victim.pid === process.pid)
|
|
154
|
+
continue;
|
|
155
|
+
// Don't kill mitosis siblings (matching parent_antibody chain)
|
|
156
|
+
if (victim.parentAntibody && victim.parentAntibody === myAntibody) {
|
|
157
|
+
refusedToKill++;
|
|
158
|
+
reasoning.push(`refused to kill mitosis child pid=${victim.pid}`);
|
|
159
|
+
continue;
|
|
160
|
+
}
|
|
161
|
+
if (killSafe(victim.pid)) {
|
|
162
|
+
killedSiblings++;
|
|
163
|
+
reasoning.push(`killed sibling pid=${victim.pid} (started ${victim.startedAt})`);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
refusedToKill++;
|
|
167
|
+
reasoning.push(`could not kill pid=${victim.pid} (permission?)`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// "youngest-wins" (default) — newer process (likely me) kills older siblings
|
|
174
|
+
for (let i = 0; i < excess; i++) {
|
|
175
|
+
const victim = aliveOfMyType[i];
|
|
176
|
+
if (victim.pid === process.pid)
|
|
177
|
+
continue;
|
|
178
|
+
if (victim.parentAntibody && victim.parentAntibody === myAntibody) {
|
|
179
|
+
refusedToKill++;
|
|
180
|
+
reasoning.push(`refused to kill mitosis child pid=${victim.pid}`);
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
if (killSafe(victim.pid)) {
|
|
184
|
+
killedSiblings++;
|
|
185
|
+
reasoning.push(`culled older sibling pid=${victim.pid}`);
|
|
186
|
+
}
|
|
187
|
+
else {
|
|
188
|
+
refusedToKill++;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
const finalAlive = aliveOfMyType.length - killedSiblings;
|
|
194
|
+
const body = { scanned, removedStale, killedSiblings, refusedToKill, finalAlive, processType: myProcessType, myAntibody };
|
|
195
|
+
const hmac = createHmac("sha256", "cull-report").update(JSON.stringify(body)).digest("hex").slice(0, 16);
|
|
196
|
+
return {
|
|
197
|
+
scanned, removedStale, killedSiblings, refusedToKill,
|
|
198
|
+
myPid: process.pid, myAntibody, finalAlive,
|
|
199
|
+
policy: this.cfg.policy, reasoning, hmac,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/** Count of alive processes by type (for monitoring). */
|
|
203
|
+
censusAlive() {
|
|
204
|
+
if (!existsSync(this.cfg.cullDir))
|
|
205
|
+
return {};
|
|
206
|
+
const counts = {};
|
|
207
|
+
for (const f of readdirSync(this.cfg.cullDir).filter((f) => f.endsWith(".beat"))) {
|
|
208
|
+
try {
|
|
209
|
+
const hb = JSON.parse(readFileSync(join(this.cfg.cullDir, f), "utf8"));
|
|
210
|
+
if (aliveSafe(hb.pid))
|
|
211
|
+
counts[hb.processType] = (counts[hb.processType] ?? 0) + 1;
|
|
212
|
+
}
|
|
213
|
+
catch { /* */ }
|
|
214
|
+
}
|
|
215
|
+
return counts;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
//# sourceMappingURL=cull.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cull.js","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/cull.ts"],"names":[],"mappings":"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"}
|
|
@@ -21,4 +21,10 @@ export { canonicalize, shouldReVerify } from "./homograph_guard.js";
|
|
|
21
21
|
export type { CanonicalizeResult } from "./homograph_guard.js";
|
|
22
22
|
export { checkInputSize, emitEnvelope, detectInputSource } from "./input_size_guard.js";
|
|
23
23
|
export type { SizeCheckResult, InputSource, CheckInputSizeOptions } from "./input_size_guard.js";
|
|
24
|
+
export { runPrism, lensFakeAuthority, lensFakeCommit, lensStatisticalReality, lensMagicNumber, lensNullInformation, } from "./prism.js";
|
|
25
|
+
export type { PrismResult, PrismVerdict, LensResult, FakeCommitOptions } from "./prism.js";
|
|
26
|
+
export { TideGuard, DEFAULT_TIDE } from "./tide_guard.js";
|
|
27
|
+
export type { TideGuardConfig, TideRequest, TideDecision } from "./tide_guard.js";
|
|
28
|
+
export { Cull, DEFAULT_CULL } from "./cull.js";
|
|
29
|
+
export type { CullConfig, CullHeartbeat, CullReport, CullPolicy } from "./cull.js";
|
|
24
30
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,kBAAkB,EAAE,cAAc,EAAE,cAAc,GACnD,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAAE,cAAc,EAAE,UAAU,GAC/C,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EACL,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAC5D,SAAS,EAAE,gBAAgB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,SAAS,GACvE,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGhG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACxF,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAGH,OAAO,EACL,kBAAkB,EAAE,cAAc,EAAE,cAAc,GACnD,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,kBAAkB,EAAE,cAAc,EAAE,UAAU,GAC/C,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAGnF,OAAO,EACL,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAC5D,SAAS,EAAE,gBAAgB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,SAAS,EAAE,aAAa,EAAE,aAAa,EAAE,kBAAkB,EAAE,SAAS,GACvE,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AACrE,YAAY,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAC;AAGhG,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACpE,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACxF,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAGjG,OAAO,EACL,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EACnE,eAAe,EAAE,mBAAmB,GACrC,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAG3F,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC1D,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGlF,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC/C,YAAY,EAAE,UAAU,EAAE,aAAa,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -21,4 +21,10 @@ export { runStrs, strsBadgeUrl, STRS_PROBE_SET_V1 } from "./strs.js";
|
|
|
21
21
|
export { canonicalize, shouldReVerify } from "./homograph_guard.js";
|
|
22
22
|
// 6. INPUT SIZE GUARD — closes v2.70 vuln #2 (silent 28K reject)
|
|
23
23
|
export { checkInputSize, emitEnvelope, detectInputSource } from "./input_size_guard.js";
|
|
24
|
+
// 7. PRISM — closes v2.70 vuln #3 (multi-lens scope narrow → 86% claims got 0 lenses)
|
|
25
|
+
export { runPrism, lensFakeAuthority, lensFakeCommit, lensStatisticalReality, lensMagicNumber, lensNullInformation, } from "./prism.js";
|
|
26
|
+
// 8. TIDE GUARD — closes v2.70 vuln #1 (rate limit removed regression)
|
|
27
|
+
export { TideGuard, DEFAULT_TIDE } from "./tide_guard.js";
|
|
28
|
+
// 9. CULL — closes v2.70 vuln #4 (process leak — 6 procs per session)
|
|
29
|
+
export { Cull, DEFAULT_CULL } from "./cull.js";
|
|
24
30
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iBAAiB;AACjB,OAAO,EACL,kBAAkB,EAAE,cAAc,EAAE,cAAc,GACnD,MAAM,kBAAkB,CAAC;AAK1B,cAAc;AACd,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,gCAAgC;AAChC,OAAO,EACL,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAC5D,SAAS,EAAE,gBAAgB,GAC5B,MAAM,mBAAmB,CAAC;AAK3B,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGrE,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGpE,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,iBAAiB;AACjB,OAAO,EACL,kBAAkB,EAAE,cAAc,EAAE,cAAc,GACnD,MAAM,kBAAkB,CAAC;AAK1B,cAAc;AACd,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGzC,gCAAgC;AAChC,OAAO,EACL,kBAAkB,EAAE,qBAAqB,EAAE,iBAAiB,EAC5D,SAAS,EAAE,gBAAgB,GAC5B,MAAM,mBAAmB,CAAC;AAK3B,UAAU;AACV,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAGrE,6DAA6D;AAC7D,OAAO,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAGpE,iEAAiE;AACjE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAGxF,sFAAsF;AACtF,OAAO,EACL,QAAQ,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EACnE,eAAe,EAAE,mBAAmB,GACrC,MAAM,YAAY,CAAC;AAGpB,uEAAuE;AACvE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG1D,sEAAsE;AACtE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔮 PRISM — Universal Multi-Lens Verification Engine
|
|
3
|
+
*
|
|
4
|
+
* Closes v2.70 Vuln #3: multi-lens engine activated only on Mneme-self
|
|
5
|
+
* claims (6/7 generic test claims → 0 lenses → unknown). PRISM extends
|
|
6
|
+
* the lens engine to fire on ANY claim by adding 5 universal lenses
|
|
7
|
+
* that need no Mneme-specific entity to activate.
|
|
8
|
+
*
|
|
9
|
+
* 5 UNIVERSAL LENSES:
|
|
10
|
+
* 1. FAKE_AUTHORITY — "According to MIT, X" without verifiable cite
|
|
11
|
+
* 2. FAKE_COMMIT — "commit deadbeef" / "PR #N" that doesn't exist
|
|
12
|
+
* 3. STATISTICAL_REALITY — "all X are Y" / "every X is Y" absolutes
|
|
13
|
+
* 4. MAGIC_NUMBER — implausible numeric claim vs reality table
|
|
14
|
+
* 5. NULL_INFORMATION — TODO / AAAAAA / empty / noise → honest refusal
|
|
15
|
+
*
|
|
16
|
+
* Each lens emits {triggered, verdict, evidence, confidence}.
|
|
17
|
+
* Caller combines with Mneme-self lenses for unified verdict.
|
|
18
|
+
*
|
|
19
|
+
* Design principle: NO lens should produce false positives on legitimate
|
|
20
|
+
* factual claims. Each lens has narrow trigger pattern. If no pattern
|
|
21
|
+
* matches, lens returns {triggered: false} — caller stacks lenses freely.
|
|
22
|
+
*/
|
|
23
|
+
export type PrismVerdict = "REFUTED" | "SUSPICIOUS" | "INSUFFICIENT_DATA" | "PASSTHROUGH";
|
|
24
|
+
export interface LensResult {
|
|
25
|
+
lens: string;
|
|
26
|
+
triggered: boolean;
|
|
27
|
+
verdict?: PrismVerdict;
|
|
28
|
+
evidence?: string;
|
|
29
|
+
confidence?: number;
|
|
30
|
+
}
|
|
31
|
+
export interface PrismResult {
|
|
32
|
+
claim: string;
|
|
33
|
+
lensesActivated: number;
|
|
34
|
+
lensesAvailable: number;
|
|
35
|
+
results: LensResult[];
|
|
36
|
+
combinedVerdict: PrismVerdict;
|
|
37
|
+
combinedConfidence: number;
|
|
38
|
+
rationale: string;
|
|
39
|
+
}
|
|
40
|
+
export declare function lensFakeAuthority(claim: string): LensResult;
|
|
41
|
+
export interface FakeCommitOptions {
|
|
42
|
+
validateSha?: (sha: string) => boolean;
|
|
43
|
+
validatePR?: (n: number) => boolean;
|
|
44
|
+
}
|
|
45
|
+
export declare function lensFakeCommit(claim: string, opts?: FakeCommitOptions): LensResult;
|
|
46
|
+
export declare function lensStatisticalReality(claim: string): LensResult;
|
|
47
|
+
export declare function lensMagicNumber(claim: string): LensResult;
|
|
48
|
+
export declare function lensNullInformation(claim: string): LensResult;
|
|
49
|
+
export declare function runPrism(claim: string, opts?: FakeCommitOptions): PrismResult;
|
|
50
|
+
//# sourceMappingURL=prism.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prism.d.ts","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/prism.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,YAAY,GAAG,SAAS,GAAG,YAAY,GAAG,mBAAmB,GAAG,aAAa,CAAC;AAE1F,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,eAAe,EAAE,YAAY,CAAC;IAC9B,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;CACnB;AAaD,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAmB3D;AAOD,MAAM,WAAW,iBAAiB;IAChC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC;IACvC,UAAU,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC;CACrC;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,UAAU,CAwCtF;AASD,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CAchE;AAoBD,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA2BzD;AAWD,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,UAAU,CA0B7D;AAGD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,GAAE,iBAAsB,GAAG,WAAW,CAyCjF"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🔮 PRISM — Universal Multi-Lens Verification Engine
|
|
3
|
+
*
|
|
4
|
+
* Closes v2.70 Vuln #3: multi-lens engine activated only on Mneme-self
|
|
5
|
+
* claims (6/7 generic test claims → 0 lenses → unknown). PRISM extends
|
|
6
|
+
* the lens engine to fire on ANY claim by adding 5 universal lenses
|
|
7
|
+
* that need no Mneme-specific entity to activate.
|
|
8
|
+
*
|
|
9
|
+
* 5 UNIVERSAL LENSES:
|
|
10
|
+
* 1. FAKE_AUTHORITY — "According to MIT, X" without verifiable cite
|
|
11
|
+
* 2. FAKE_COMMIT — "commit deadbeef" / "PR #N" that doesn't exist
|
|
12
|
+
* 3. STATISTICAL_REALITY — "all X are Y" / "every X is Y" absolutes
|
|
13
|
+
* 4. MAGIC_NUMBER — implausible numeric claim vs reality table
|
|
14
|
+
* 5. NULL_INFORMATION — TODO / AAAAAA / empty / noise → honest refusal
|
|
15
|
+
*
|
|
16
|
+
* Each lens emits {triggered, verdict, evidence, confidence}.
|
|
17
|
+
* Caller combines with Mneme-self lenses for unified verdict.
|
|
18
|
+
*
|
|
19
|
+
* Design principle: NO lens should produce false positives on legitimate
|
|
20
|
+
* factual claims. Each lens has narrow trigger pattern. If no pattern
|
|
21
|
+
* matches, lens returns {triggered: false} — caller stacks lenses freely.
|
|
22
|
+
*/
|
|
23
|
+
// ── Lens 1: FAKE_AUTHORITY ─────────────────────────────────────
|
|
24
|
+
const AUTHORITY_PATTERNS = [
|
|
25
|
+
/according to (?:the )?(MIT|Harvard|Stanford|Yale|Princeton|Oxford|Cambridge|CMU|Berkeley|UCLA|NASA|CERN|WHO|UN|World Bank|IMF|FAO|UNESCO|Microsoft|Google|Apple|Meta|OpenAI|Anthropic|xAI|IBM|Bloomberg|Reuters|NYT|Forbes|TechCrunch)/i,
|
|
26
|
+
/(?:study|research|paper|report)(?:\s+by\s+|\s+from\s+)([A-Z][a-zA-Z ]+)\s+(?:says?|finds?|shows?|claims?|reports?|concludes?)/,
|
|
27
|
+
/([A-Z][a-zA-Z]+(?:\s+(?:University|Institute|Foundation|Lab|Laboratory|Corp(?:oration)?|Inc|Ltd))+)\s+(?:says?|reports?|claims?)/,
|
|
28
|
+
];
|
|
29
|
+
const URL_RE = /https?:\/\/[^\s)]+/;
|
|
30
|
+
const DOI_RE = /\b10\.\d{4,}\/[-._;()/:\w]+/;
|
|
31
|
+
const ARXIV_RE = /\barxiv[:\s]+\d{4}\.\d{4,}/i;
|
|
32
|
+
export function lensFakeAuthority(claim) {
|
|
33
|
+
const hits = [];
|
|
34
|
+
for (const re of AUTHORITY_PATTERNS) {
|
|
35
|
+
const m = claim.match(re);
|
|
36
|
+
if (m)
|
|
37
|
+
hits.push(m[0]);
|
|
38
|
+
}
|
|
39
|
+
if (hits.length === 0)
|
|
40
|
+
return { lens: "fake_authority", triggered: false };
|
|
41
|
+
const hasCitation = URL_RE.test(claim) || DOI_RE.test(claim) || ARXIV_RE.test(claim);
|
|
42
|
+
if (hasCitation) {
|
|
43
|
+
return { lens: "fake_authority", triggered: true, verdict: "PASSTHROUGH", evidence: `authority cited (${hits[0]}) + has URL/DOI/arXiv reference`, confidence: 0.4 };
|
|
44
|
+
}
|
|
45
|
+
return {
|
|
46
|
+
lens: "fake_authority",
|
|
47
|
+
triggered: true,
|
|
48
|
+
verdict: "SUSPICIOUS",
|
|
49
|
+
evidence: `cites "${hits[0]}" without URL/DOI/arXiv — likely fabricated authority`,
|
|
50
|
+
confidence: 0.75,
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
// ── Lens 2: FAKE_COMMIT ────────────────────────────────────────
|
|
54
|
+
const COMMIT_SHA_RE = /\bcommit\s+([0-9a-f]{6,40})\b/i;
|
|
55
|
+
const PR_RE = /\b(?:PR|pull request)\s*#?(\d+)\b/i;
|
|
56
|
+
const ISSUE_RE = /\bissue\s*#(\d+)\b/i;
|
|
57
|
+
export function lensFakeCommit(claim, opts = {}) {
|
|
58
|
+
const shaMatch = claim.match(COMMIT_SHA_RE);
|
|
59
|
+
const prMatch = claim.match(PR_RE);
|
|
60
|
+
const issueMatch = claim.match(ISSUE_RE);
|
|
61
|
+
if (!shaMatch && !prMatch && !issueMatch) {
|
|
62
|
+
return { lens: "fake_commit", triggered: false };
|
|
63
|
+
}
|
|
64
|
+
if (shaMatch && opts.validateSha) {
|
|
65
|
+
const sha = shaMatch[1];
|
|
66
|
+
if (!opts.validateSha(sha)) {
|
|
67
|
+
return {
|
|
68
|
+
lens: "fake_commit", triggered: true, verdict: "REFUTED",
|
|
69
|
+
evidence: `commit ${sha} does not exist in git log`,
|
|
70
|
+
confidence: 0.95,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return { lens: "fake_commit", triggered: true, verdict: "PASSTHROUGH", evidence: `commit ${sha} verified in git log`, confidence: 0.9 };
|
|
74
|
+
}
|
|
75
|
+
// No validator provided OR no SHA — flag SHA-like strings that are clearly
|
|
76
|
+
// placeholder (deadbeef, cafebabe, 0xabcdef) regardless.
|
|
77
|
+
if (shaMatch) {
|
|
78
|
+
const sha = shaMatch[1].toLowerCase();
|
|
79
|
+
const placeholders = ["deadbeef", "cafebabe", "abcdef", "0000000", "fedcba", "12345678", "badf00d", "feedface"];
|
|
80
|
+
if (placeholders.some((p) => sha.startsWith(p))) {
|
|
81
|
+
return {
|
|
82
|
+
lens: "fake_commit", triggered: true, verdict: "REFUTED",
|
|
83
|
+
evidence: `commit "${sha}" matches well-known placeholder/joke SHA`,
|
|
84
|
+
confidence: 0.9,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return {
|
|
89
|
+
lens: "fake_commit", triggered: true, verdict: "SUSPICIOUS",
|
|
90
|
+
evidence: `references commit/PR/issue but no validator provided — caller should verify against git/forge`,
|
|
91
|
+
confidence: 0.5,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
// ── Lens 3: STATISTICAL_REALITY ────────────────────────────────
|
|
95
|
+
const ABSOLUTE_POPULATION_PATTERNS = [
|
|
96
|
+
/\b(?:all|every|each)\s+([a-z]+(?:s|men|women|people|users|engineers|programmers|developers|students|teachers|workers|employees|companies|countries|cities|cars|phones|computers))\s+(?:are|is|have|has|do|does|will|can|always)\b/i,
|
|
97
|
+
/\b(?:no|none of the|not a single)\s+([a-z]+(?:s|men|women|people|users|engineers|programmers|developers|students|teachers|workers|employees|companies))\s+(?:are|is|have|has|do|does)\b/i,
|
|
98
|
+
/\b(?:always|never)\b.*\b(?:fails?|works?|crash(?:es)?|pass(?:es)?|succeed(?:s)?)\b/i,
|
|
99
|
+
];
|
|
100
|
+
export function lensStatisticalReality(claim) {
|
|
101
|
+
for (const re of ABSOLUTE_POPULATION_PATTERNS) {
|
|
102
|
+
const m = claim.match(re);
|
|
103
|
+
if (m) {
|
|
104
|
+
return {
|
|
105
|
+
lens: "statistical_reality",
|
|
106
|
+
triggered: true,
|
|
107
|
+
verdict: "SUSPICIOUS",
|
|
108
|
+
evidence: `absolute claim about population ("${m[0]}") — natural variance makes universal claims almost always REFUTABLE`,
|
|
109
|
+
confidence: 0.8,
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { lens: "statistical_reality", triggered: false };
|
|
114
|
+
}
|
|
115
|
+
const PLAUSIBILITY_TABLE = [
|
|
116
|
+
{ pattern: /(\d+)\s*million(?:aires?)?/i, metric: "millionaire-status", realisticMin: 0, realisticMax: 100_000_000, realisticTypical: 1_000_000, unit: "people-with-≥$1M" },
|
|
117
|
+
{ pattern: /(?:engineers?|developers?|programmers?).*?\$?(\d{1,3}(?:,\d{3})*(?:\.\d+)?|\d+)\s*(?:k|K)?\s*(?:salary|per year|annually|yearly)/i, metric: "engineer-salary-USD", realisticMin: 30_000, realisticMax: 800_000, realisticTypical: 110_000, unit: "USD/year" },
|
|
118
|
+
{ pattern: /(?:speed|velocity).*?(\d+(?:\.\d+)?)\s*(?:km\/?s|km per sec)/i, metric: "velocity-km-per-sec", realisticMin: 0, realisticMax: 300_000, realisticTypical: 7.8, unit: "km/s" },
|
|
119
|
+
{ pattern: /(?:LEO|low earth orbit).*?(\d+(?:\.\d+)?)\s*(?:km\/?s|km per sec)/i, metric: "LEO-velocity", realisticMin: 7.5, realisticMax: 8.0, realisticTypical: 7.8, unit: "km/s" },
|
|
120
|
+
{ pattern: /(\d{4,})\s*(?:files?|lines? of code|loc)/i, metric: "loc-count", realisticMin: 1, realisticMax: 10_000_000, realisticTypical: 100_000, unit: "lines" },
|
|
121
|
+
];
|
|
122
|
+
export function lensMagicNumber(claim) {
|
|
123
|
+
for (const row of PLAUSIBILITY_TABLE) {
|
|
124
|
+
const m = claim.match(row.pattern);
|
|
125
|
+
if (!m)
|
|
126
|
+
continue;
|
|
127
|
+
let value = parseFloat(m[1].replace(/,/g, ""));
|
|
128
|
+
if (Number.isNaN(value))
|
|
129
|
+
continue;
|
|
130
|
+
// If the original match had "k" or "K" suffix, multiply by 1000
|
|
131
|
+
if (/\d+\s*[kK]\b/.test(m[0]))
|
|
132
|
+
value *= 1000;
|
|
133
|
+
if (value < row.realisticMin || value > row.realisticMax) {
|
|
134
|
+
return {
|
|
135
|
+
lens: "magic_number",
|
|
136
|
+
triggered: true,
|
|
137
|
+
verdict: "REFUTED",
|
|
138
|
+
evidence: `claim asserts ${value} ${row.unit} for ${row.metric}; realistic range is [${row.realisticMin}, ${row.realisticMax}]`,
|
|
139
|
+
confidence: 0.85,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
// value within range — passthrough
|
|
143
|
+
return {
|
|
144
|
+
lens: "magic_number",
|
|
145
|
+
triggered: true,
|
|
146
|
+
verdict: "PASSTHROUGH",
|
|
147
|
+
evidence: `claim's ${row.metric} of ${value} ${row.unit} is within plausible range`,
|
|
148
|
+
confidence: 0.5,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
return { lens: "magic_number", triggered: false };
|
|
152
|
+
}
|
|
153
|
+
// ── Lens 5: NULL_INFORMATION ───────────────────────────────────
|
|
154
|
+
const NOISE_PATTERNS = [
|
|
155
|
+
/^[A-Z]{4,}$/i, // AAAAAA / YYYYYY
|
|
156
|
+
/^\s*(?:todo|tbd|wip|n\/a|xxx|fixme)\s*$/i,
|
|
157
|
+
/^[^a-zA-Z0-9]*$/, // punctuation only
|
|
158
|
+
/^\s*$/, // whitespace
|
|
159
|
+
/^(.)\1{5,}$/, // same char repeated
|
|
160
|
+
];
|
|
161
|
+
export function lensNullInformation(claim) {
|
|
162
|
+
if (claim.length === 0) {
|
|
163
|
+
return { lens: "null_information", triggered: true, verdict: "INSUFFICIENT_DATA", evidence: "empty input — nothing to verify", confidence: 1 };
|
|
164
|
+
}
|
|
165
|
+
for (const re of NOISE_PATTERNS) {
|
|
166
|
+
if (re.test(claim.trim())) {
|
|
167
|
+
return {
|
|
168
|
+
lens: "null_information",
|
|
169
|
+
triggered: true,
|
|
170
|
+
verdict: "INSUFFICIENT_DATA",
|
|
171
|
+
evidence: `input is noise/placeholder/empty — Mneme refuses to invent a verdict`,
|
|
172
|
+
confidence: 1,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
// Has structure but very short
|
|
177
|
+
if (claim.trim().split(/\s+/).filter(Boolean).length < 2) {
|
|
178
|
+
return {
|
|
179
|
+
lens: "null_information",
|
|
180
|
+
triggered: true,
|
|
181
|
+
verdict: "INSUFFICIENT_DATA",
|
|
182
|
+
evidence: `single-word input has no checkable assertion`,
|
|
183
|
+
confidence: 0.8,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
return { lens: "null_information", triggered: false };
|
|
187
|
+
}
|
|
188
|
+
// ── Compose all 5 ───────────────────────────────────────────────
|
|
189
|
+
export function runPrism(claim, opts = {}) {
|
|
190
|
+
const lensFns = [
|
|
191
|
+
() => lensFakeAuthority(claim),
|
|
192
|
+
() => lensFakeCommit(claim, opts),
|
|
193
|
+
() => lensStatisticalReality(claim),
|
|
194
|
+
() => lensMagicNumber(claim),
|
|
195
|
+
() => lensNullInformation(claim),
|
|
196
|
+
];
|
|
197
|
+
const results = lensFns.map((f) => f());
|
|
198
|
+
const activated = results.filter((r) => r.triggered);
|
|
199
|
+
// Combine: REFUTED wins, then SUSPICIOUS, then INSUFFICIENT_DATA, else PASSTHROUGH
|
|
200
|
+
let combinedVerdict = "PASSTHROUGH";
|
|
201
|
+
let combinedConfidence = 0;
|
|
202
|
+
if (activated.some((r) => r.verdict === "REFUTED")) {
|
|
203
|
+
combinedVerdict = "REFUTED";
|
|
204
|
+
combinedConfidence = Math.max(...activated.filter((r) => r.verdict === "REFUTED").map((r) => r.confidence ?? 0.5));
|
|
205
|
+
}
|
|
206
|
+
else if (activated.some((r) => r.verdict === "SUSPICIOUS")) {
|
|
207
|
+
combinedVerdict = "SUSPICIOUS";
|
|
208
|
+
combinedConfidence = Math.max(...activated.filter((r) => r.verdict === "SUSPICIOUS").map((r) => r.confidence ?? 0.5));
|
|
209
|
+
}
|
|
210
|
+
else if (activated.some((r) => r.verdict === "INSUFFICIENT_DATA")) {
|
|
211
|
+
combinedVerdict = "INSUFFICIENT_DATA";
|
|
212
|
+
combinedConfidence = Math.max(...activated.filter((r) => r.verdict === "INSUFFICIENT_DATA").map((r) => r.confidence ?? 0.5));
|
|
213
|
+
}
|
|
214
|
+
else if (activated.length > 0) {
|
|
215
|
+
combinedConfidence = activated.reduce((a, r) => a + (r.confidence ?? 0), 0) / activated.length;
|
|
216
|
+
}
|
|
217
|
+
const evidenceTexts = activated.filter((r) => r.evidence).map((r) => `${r.lens}: ${r.evidence}`);
|
|
218
|
+
const rationale = activated.length === 0
|
|
219
|
+
? "no universal lens triggered — claim is generic-factual; needs domain-specific verification"
|
|
220
|
+
: `${activated.length}/${lensFns.length} lenses triggered. ${evidenceTexts.join(" | ")}`;
|
|
221
|
+
return {
|
|
222
|
+
claim,
|
|
223
|
+
lensesActivated: activated.length,
|
|
224
|
+
lensesAvailable: lensFns.length,
|
|
225
|
+
results,
|
|
226
|
+
combinedVerdict,
|
|
227
|
+
combinedConfidence,
|
|
228
|
+
rationale,
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=prism.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prism.js","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/prism.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🌊 TIDE GUARD — Entropy-aware adaptive rate limiter
|
|
3
|
+
*
|
|
4
|
+
* Closes v2.70 Vuln #1: rate limit removed (regression) → DoS surface.
|
|
5
|
+
* Standard token bucket is brittle: bots can match the rate. TIDE GUARD
|
|
6
|
+
* adds an ENTROPY signal — low-entropy bursts (repetitive payloads,
|
|
7
|
+
* identical user-agents, similar timing) get throttled harder, even
|
|
8
|
+
* if they're under the nominal rate.
|
|
9
|
+
*
|
|
10
|
+
* Per-source bucket:
|
|
11
|
+
* - refillRatePerSec R (legitimate human baseline)
|
|
12
|
+
* - capacity C (burst tolerance)
|
|
13
|
+
* - entropyAdjuster downscales R by (1 - lowEntropyPenalty)
|
|
14
|
+
*
|
|
15
|
+
* Entropy computed over rolling N-request payload-shape window. If recent
|
|
16
|
+
* Shannon entropy < threshold → assume bot, halve effective rate.
|
|
17
|
+
*
|
|
18
|
+
* Fingerprint-tier hook: caller can supply trust score → tier multiplier:
|
|
19
|
+
* trust ≥ 0.9 → 10× R (verified human / known-good vendor)
|
|
20
|
+
* trust ≥ 0.6 → 3× R (NEMESIS classified, low refute rate)
|
|
21
|
+
* trust ≥ 0.3 → 1× R (default)
|
|
22
|
+
* trust < 0.3 → 0.3× R (suspicious)
|
|
23
|
+
*
|
|
24
|
+
* Output: { allowed, tokensLeft, retryAfterMs, reason, hmac } — HMAC
|
|
25
|
+
* lets caller present "I was rate-limited" receipt to support.
|
|
26
|
+
*/
|
|
27
|
+
export interface TideGuardConfig {
|
|
28
|
+
/** Tokens per second baseline. */
|
|
29
|
+
refillRatePerSec: number;
|
|
30
|
+
/** Max bucket capacity. */
|
|
31
|
+
capacity: number;
|
|
32
|
+
/** Window size for entropy computation (last N requests). */
|
|
33
|
+
entropyWindow: number;
|
|
34
|
+
/** Shannon-entropy threshold below which throttle kicks in. */
|
|
35
|
+
entropyFloor: number;
|
|
36
|
+
/** Max penalty when entropy is at minimum (e.g. 0.5 = halve rate). */
|
|
37
|
+
maxLowEntropyPenalty: number;
|
|
38
|
+
/** HMAC key for signed reject receipts. */
|
|
39
|
+
hmacKey: string;
|
|
40
|
+
}
|
|
41
|
+
export declare const DEFAULT_TIDE: TideGuardConfig;
|
|
42
|
+
export interface TideRequest {
|
|
43
|
+
sourceId: string;
|
|
44
|
+
payloadShape?: string;
|
|
45
|
+
trustScore?: number;
|
|
46
|
+
}
|
|
47
|
+
export interface TideDecision {
|
|
48
|
+
allowed: boolean;
|
|
49
|
+
tokensLeft: number;
|
|
50
|
+
retryAfterMs: number;
|
|
51
|
+
effectiveRate: number;
|
|
52
|
+
entropyBits: number;
|
|
53
|
+
trustMultiplier: number;
|
|
54
|
+
reason: string;
|
|
55
|
+
hmac: string;
|
|
56
|
+
}
|
|
57
|
+
export declare class TideGuard {
|
|
58
|
+
readonly cfg: TideGuardConfig;
|
|
59
|
+
private sources;
|
|
60
|
+
constructor(cfg?: TideGuardConfig);
|
|
61
|
+
check(req: TideRequest, now?: number): TideDecision;
|
|
62
|
+
/** Reset source — e.g. on admin override. */
|
|
63
|
+
reset(sourceId: string): void;
|
|
64
|
+
/** Snapshot for diagnostics. */
|
|
65
|
+
snapshot(): Array<{
|
|
66
|
+
sourceId: string;
|
|
67
|
+
tokensLeft: number;
|
|
68
|
+
recentShapes: number;
|
|
69
|
+
}>;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=tide_guard.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tide_guard.d.ts","sourceRoot":"","sources":["../../../src/protoplasm/super_quan/tide_guard.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAIH,MAAM,WAAW,eAAe;IAC9B,kCAAkC;IAClC,gBAAgB,EAAE,MAAM,CAAC;IACzB,2BAA2B;IAC3B,QAAQ,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,aAAa,EAAE,MAAM,CAAC;IACtB,+DAA+D;IAC/D,YAAY,EAAE,MAAM,CAAC;IACrB,sEAAsE;IACtE,oBAAoB,EAAE,MAAM,CAAC;IAC7B,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,eAAO,MAAM,YAAY,EAAE,eAO1B,CAAC;AAQF,MAAM,WAAW,WAAW;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACd;AAsBD,qBAAa,SAAS;aAGQ,GAAG,EAAE,eAAe;IAFhD,OAAO,CAAC,OAAO,CAAkC;gBAErB,GAAG,GAAE,eAA8B;IAE/D,KAAK,CAAC,GAAG,EAAE,WAAW,EAAE,GAAG,SAAa,GAAG,YAAY;IAiEvD,6CAA6C;IAC7C,KAAK,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAE7B,gCAAgC;IAChC,QAAQ,IAAI,KAAK,CAAC;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAA;KAAE,CAAC;CAKlF"}
|