@vorionsys/atsf-core 0.2.2 → 0.2.3

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 (326) hide show
  1. package/CHANGELOG.md +3 -3
  2. package/README.md +77 -11
  3. package/dist/api/index.d.ts +1 -1
  4. package/dist/api/index.js +1 -1
  5. package/dist/api/server.d.ts +5 -2
  6. package/dist/api/server.d.ts.map +1 -1
  7. package/dist/api/server.js +186 -149
  8. package/dist/api/server.js.map +1 -1
  9. package/dist/arbitration/index.d.ts +4 -4
  10. package/dist/arbitration/index.d.ts.map +1 -1
  11. package/dist/arbitration/index.js +46 -41
  12. package/dist/arbitration/index.js.map +1 -1
  13. package/dist/arbitration/types.d.ts +10 -10
  14. package/dist/arbitration/types.d.ts.map +1 -1
  15. package/dist/basis/evaluator.d.ts +1 -1
  16. package/dist/basis/evaluator.d.ts.map +1 -1
  17. package/dist/basis/evaluator.js +56 -54
  18. package/dist/basis/evaluator.js.map +1 -1
  19. package/dist/basis/index.d.ts +3 -3
  20. package/dist/basis/index.js +3 -3
  21. package/dist/basis/parser.d.ts +16 -16
  22. package/dist/basis/parser.d.ts.map +1 -1
  23. package/dist/basis/parser.js +32 -25
  24. package/dist/basis/parser.js.map +1 -1
  25. package/dist/basis/types.d.ts +2 -2
  26. package/dist/chain/index.d.ts.map +1 -1
  27. package/dist/chain/index.js +16 -16
  28. package/dist/chain/index.js.map +1 -1
  29. package/dist/cognigate/index.d.ts +1 -1
  30. package/dist/cognigate/index.d.ts.map +1 -1
  31. package/dist/cognigate/index.js +44 -33
  32. package/dist/cognigate/index.js.map +1 -1
  33. package/dist/common/adapters.d.ts +18 -11
  34. package/dist/common/adapters.d.ts.map +1 -1
  35. package/dist/common/adapters.js +100 -79
  36. package/dist/common/adapters.js.map +1 -1
  37. package/dist/common/config.d.ts +67 -67
  38. package/dist/common/config.js +49 -49
  39. package/dist/common/config.js.map +1 -1
  40. package/dist/common/index.d.ts +4 -4
  41. package/dist/common/index.js +4 -4
  42. package/dist/common/logger.d.ts +1 -1
  43. package/dist/common/logger.js +8 -8
  44. package/dist/common/types.d.ts +8 -8
  45. package/dist/common/types.js +5 -5
  46. package/dist/containment/index.d.ts +3 -3
  47. package/dist/containment/index.d.ts.map +1 -1
  48. package/dist/containment/index.js +119 -105
  49. package/dist/containment/index.js.map +1 -1
  50. package/dist/containment/types.d.ts +11 -11
  51. package/dist/containment/types.d.ts.map +1 -1
  52. package/dist/contracts/index.d.ts +9 -9
  53. package/dist/contracts/index.d.ts.map +1 -1
  54. package/dist/contracts/index.js +59 -54
  55. package/dist/contracts/index.js.map +1 -1
  56. package/dist/contracts/types.d.ts +12 -12
  57. package/dist/contracts/types.d.ts.map +1 -1
  58. package/dist/crewai/callback.d.ts +91 -0
  59. package/dist/crewai/callback.d.ts.map +1 -0
  60. package/dist/crewai/callback.js +271 -0
  61. package/dist/crewai/callback.js.map +1 -0
  62. package/dist/crewai/executor.d.ts +135 -0
  63. package/dist/crewai/executor.d.ts.map +1 -0
  64. package/dist/crewai/executor.js +381 -0
  65. package/dist/crewai/executor.js.map +1 -0
  66. package/dist/crewai/index.d.ts +12 -0
  67. package/dist/crewai/index.d.ts.map +1 -0
  68. package/dist/crewai/index.js +12 -0
  69. package/dist/crewai/index.js.map +1 -0
  70. package/dist/crewai/tools.d.ts +21 -0
  71. package/dist/crewai/tools.d.ts.map +1 -0
  72. package/dist/crewai/tools.js +164 -0
  73. package/dist/crewai/tools.js.map +1 -0
  74. package/dist/crewai/types.d.ts +139 -0
  75. package/dist/crewai/types.d.ts.map +1 -0
  76. package/dist/crewai/types.js +9 -0
  77. package/dist/crewai/types.js.map +1 -0
  78. package/dist/enforce/index.d.ts +48 -222
  79. package/dist/enforce/index.d.ts.map +1 -1
  80. package/dist/enforce/index.js +144 -47
  81. package/dist/enforce/index.js.map +1 -1
  82. package/dist/enforce/trust-aware-enforcement-service.d.ts +121 -0
  83. package/dist/enforce/trust-aware-enforcement-service.d.ts.map +1 -0
  84. package/dist/enforce/trust-aware-enforcement-service.js +601 -0
  85. package/dist/enforce/trust-aware-enforcement-service.js.map +1 -0
  86. package/dist/enforce/types.d.ts +234 -0
  87. package/dist/enforce/types.d.ts.map +1 -0
  88. package/dist/enforce/types.js +10 -0
  89. package/dist/enforce/types.js.map +1 -0
  90. package/dist/governance/fluid-workflow.d.ts +8 -8
  91. package/dist/governance/fluid-workflow.d.ts.map +1 -1
  92. package/dist/governance/fluid-workflow.js +114 -86
  93. package/dist/governance/fluid-workflow.js.map +1 -1
  94. package/dist/governance/index.d.ts +7 -7
  95. package/dist/governance/index.d.ts.map +1 -1
  96. package/dist/governance/index.js +81 -74
  97. package/dist/governance/index.js.map +1 -1
  98. package/dist/governance/proof-bridge.d.ts +6 -6
  99. package/dist/governance/proof-bridge.d.ts.map +1 -1
  100. package/dist/governance/proof-bridge.js +5 -5
  101. package/dist/governance/proof-bridge.js.map +1 -1
  102. package/dist/governance/types.d.ts +16 -9
  103. package/dist/governance/types.d.ts.map +1 -1
  104. package/dist/governance/types.js.map +1 -1
  105. package/dist/index.d.ts +29 -25
  106. package/dist/index.d.ts.map +1 -1
  107. package/dist/index.js +33 -23
  108. package/dist/index.js.map +1 -1
  109. package/dist/intent/index.d.ts +21 -56
  110. package/dist/intent/index.d.ts.map +1 -1
  111. package/dist/intent/index.js +58 -24
  112. package/dist/intent/index.js.map +1 -1
  113. package/dist/intent/persistent-intent-service.d.ts +68 -0
  114. package/dist/intent/persistent-intent-service.d.ts.map +1 -0
  115. package/dist/intent/persistent-intent-service.js +277 -0
  116. package/dist/intent/persistent-intent-service.js.map +1 -0
  117. package/dist/intent/types.d.ts +69 -0
  118. package/dist/intent/types.d.ts.map +1 -0
  119. package/dist/intent/types.js +10 -0
  120. package/dist/intent/types.js.map +1 -0
  121. package/dist/intent-gateway/index.d.ts +522 -0
  122. package/dist/intent-gateway/index.d.ts.map +1 -0
  123. package/dist/intent-gateway/index.js +1499 -0
  124. package/dist/intent-gateway/index.js.map +1 -0
  125. package/dist/langchain/callback.d.ts +2 -2
  126. package/dist/langchain/callback.d.ts.map +1 -1
  127. package/dist/langchain/callback.js +30 -30
  128. package/dist/langchain/callback.js.map +1 -1
  129. package/dist/langchain/executor.d.ts +4 -4
  130. package/dist/langchain/executor.d.ts.map +1 -1
  131. package/dist/langchain/executor.js +82 -80
  132. package/dist/langchain/executor.js.map +1 -1
  133. package/dist/langchain/index.d.ts +5 -5
  134. package/dist/langchain/index.js +5 -5
  135. package/dist/langchain/tools.d.ts +1 -1
  136. package/dist/langchain/tools.d.ts.map +1 -1
  137. package/dist/langchain/tools.js +33 -33
  138. package/dist/langchain/tools.js.map +1 -1
  139. package/dist/langchain/types.d.ts +3 -3
  140. package/dist/langchain/types.d.ts.map +1 -1
  141. package/dist/layers/implementations/L0-request-format.d.ts +37 -0
  142. package/dist/layers/implementations/L0-request-format.d.ts.map +1 -0
  143. package/dist/layers/implementations/L0-request-format.js +218 -0
  144. package/dist/layers/implementations/L0-request-format.js.map +1 -0
  145. package/dist/layers/implementations/L1-input-size.d.ts +36 -0
  146. package/dist/layers/implementations/L1-input-size.d.ts.map +1 -0
  147. package/dist/layers/implementations/L1-input-size.js +160 -0
  148. package/dist/layers/implementations/L1-input-size.js.map +1 -0
  149. package/dist/layers/implementations/L2-charset-sanitizer.d.ts +28 -0
  150. package/dist/layers/implementations/L2-charset-sanitizer.d.ts.map +1 -0
  151. package/dist/layers/implementations/L2-charset-sanitizer.js +230 -0
  152. package/dist/layers/implementations/L2-charset-sanitizer.js.map +1 -0
  153. package/dist/layers/implementations/L3-schema-conformance.d.ts +47 -0
  154. package/dist/layers/implementations/L3-schema-conformance.d.ts.map +1 -0
  155. package/dist/layers/implementations/L3-schema-conformance.js +267 -0
  156. package/dist/layers/implementations/L3-schema-conformance.js.map +1 -0
  157. package/dist/layers/implementations/L4-injection-detector.d.ts +47 -0
  158. package/dist/layers/implementations/L4-injection-detector.d.ts.map +1 -0
  159. package/dist/layers/implementations/L4-injection-detector.js +260 -0
  160. package/dist/layers/implementations/L4-injection-detector.js.map +1 -0
  161. package/dist/layers/implementations/L5-rate-limiter.d.ts +51 -0
  162. package/dist/layers/implementations/L5-rate-limiter.d.ts.map +1 -0
  163. package/dist/layers/implementations/L5-rate-limiter.js +183 -0
  164. package/dist/layers/implementations/L5-rate-limiter.js.map +1 -0
  165. package/dist/layers/implementations/index.d.ts +16 -0
  166. package/dist/layers/implementations/index.d.ts.map +1 -0
  167. package/dist/layers/implementations/index.js +16 -0
  168. package/dist/layers/implementations/index.js.map +1 -0
  169. package/dist/layers/index.d.ts +3 -3
  170. package/dist/layers/index.d.ts.map +1 -1
  171. package/dist/layers/index.js +99 -71
  172. package/dist/layers/index.js.map +1 -1
  173. package/dist/layers/types.d.ts +16 -16
  174. package/dist/layers/types.d.ts.map +1 -1
  175. package/dist/persistence/file.d.ts +3 -3
  176. package/dist/persistence/file.d.ts.map +1 -1
  177. package/dist/persistence/file.js +32 -28
  178. package/dist/persistence/file.js.map +1 -1
  179. package/dist/persistence/index.d.ts +7 -7
  180. package/dist/persistence/index.d.ts.map +1 -1
  181. package/dist/persistence/index.js +18 -18
  182. package/dist/persistence/index.js.map +1 -1
  183. package/dist/persistence/memory.d.ts +3 -3
  184. package/dist/persistence/memory.d.ts.map +1 -1
  185. package/dist/persistence/memory.js +10 -8
  186. package/dist/persistence/memory.js.map +1 -1
  187. package/dist/persistence/sqlite.d.ts +3 -3
  188. package/dist/persistence/sqlite.d.ts.map +1 -1
  189. package/dist/persistence/sqlite.js +36 -36
  190. package/dist/persistence/sqlite.js.map +1 -1
  191. package/dist/persistence/supabase.d.ts +3 -3
  192. package/dist/persistence/supabase.d.ts.map +1 -1
  193. package/dist/persistence/supabase.js +41 -43
  194. package/dist/persistence/supabase.js.map +1 -1
  195. package/dist/persistence/types.d.ts +5 -5
  196. package/dist/phase6/ceiling.d.ts +5 -5
  197. package/dist/phase6/ceiling.d.ts.map +1 -1
  198. package/dist/phase6/ceiling.js +67 -34
  199. package/dist/phase6/ceiling.js.map +1 -1
  200. package/dist/phase6/context.d.ts +3 -3
  201. package/dist/phase6/context.d.ts.map +1 -1
  202. package/dist/phase6/context.js +91 -45
  203. package/dist/phase6/context.js.map +1 -1
  204. package/dist/phase6/index.d.ts +13 -13
  205. package/dist/phase6/index.d.ts.map +1 -1
  206. package/dist/phase6/index.js +16 -16
  207. package/dist/phase6/index.js.map +1 -1
  208. package/dist/phase6/presets.d.ts +2 -2
  209. package/dist/phase6/presets.d.ts.map +1 -1
  210. package/dist/phase6/presets.js +39 -33
  211. package/dist/phase6/presets.js.map +1 -1
  212. package/dist/phase6/provenance.d.ts +4 -4
  213. package/dist/phase6/provenance.d.ts.map +1 -1
  214. package/dist/phase6/provenance.js +42 -35
  215. package/dist/phase6/provenance.js.map +1 -1
  216. package/dist/phase6/role-gates/index.d.ts +2 -2
  217. package/dist/phase6/role-gates/index.js +2 -2
  218. package/dist/phase6/role-gates/kernel.d.ts.map +1 -1
  219. package/dist/phase6/role-gates/kernel.js +16 -16
  220. package/dist/phase6/role-gates/kernel.js.map +1 -1
  221. package/dist/phase6/role-gates/policy.d.ts +2 -2
  222. package/dist/phase6/role-gates/policy.js +6 -6
  223. package/dist/phase6/role-gates.d.ts +4 -4
  224. package/dist/phase6/role-gates.d.ts.map +1 -1
  225. package/dist/phase6/role-gates.js +80 -58
  226. package/dist/phase6/role-gates.js.map +1 -1
  227. package/dist/phase6/types.d.ts +35 -35
  228. package/dist/phase6/types.d.ts.map +1 -1
  229. package/dist/phase6/types.js +166 -66
  230. package/dist/phase6/types.js.map +1 -1
  231. package/dist/phase6/weight-presets/canonical.d.ts +2 -2
  232. package/dist/phase6/weight-presets/canonical.d.ts.map +1 -1
  233. package/dist/phase6/weight-presets/canonical.js +12 -12
  234. package/dist/phase6/weight-presets/canonical.js.map +1 -1
  235. package/dist/phase6/weight-presets/deltas.d.ts +2 -2
  236. package/dist/phase6/weight-presets/deltas.d.ts.map +1 -1
  237. package/dist/phase6/weight-presets/deltas.js +27 -27
  238. package/dist/phase6/weight-presets/deltas.js.map +1 -1
  239. package/dist/phase6/weight-presets/index.d.ts +4 -4
  240. package/dist/phase6/weight-presets/index.js +4 -4
  241. package/dist/phase6/weight-presets/merger.d.ts +3 -3
  242. package/dist/phase6/weight-presets/merger.d.ts.map +1 -1
  243. package/dist/phase6/weight-presets/merger.js +40 -44
  244. package/dist/phase6/weight-presets/merger.js.map +1 -1
  245. package/dist/proof/index.d.ts +3 -3
  246. package/dist/proof/index.d.ts.map +1 -1
  247. package/dist/proof/index.js +44 -38
  248. package/dist/proof/index.js.map +1 -1
  249. package/dist/proof/merkle.d.ts +3 -3
  250. package/dist/proof/merkle.d.ts.map +1 -1
  251. package/dist/proof/merkle.js +26 -25
  252. package/dist/proof/merkle.js.map +1 -1
  253. package/dist/proof/zk-proofs.d.ts +6 -6
  254. package/dist/proof/zk-proofs.d.ts.map +1 -1
  255. package/dist/proof/zk-proofs.js +42 -43
  256. package/dist/proof/zk-proofs.js.map +1 -1
  257. package/dist/provenance/index.d.ts +3 -3
  258. package/dist/provenance/index.d.ts.map +1 -1
  259. package/dist/provenance/index.js +19 -17
  260. package/dist/provenance/index.js.map +1 -1
  261. package/dist/provenance/types.d.ts +4 -4
  262. package/dist/provenance/types.d.ts.map +1 -1
  263. package/dist/sandbox-training/challenges.d.ts +1 -1
  264. package/dist/sandbox-training/challenges.d.ts.map +1 -1
  265. package/dist/sandbox-training/challenges.js +228 -228
  266. package/dist/sandbox-training/challenges.js.map +1 -1
  267. package/dist/sandbox-training/graduation.d.ts +1 -1
  268. package/dist/sandbox-training/graduation.d.ts.map +1 -1
  269. package/dist/sandbox-training/graduation.js +14 -15
  270. package/dist/sandbox-training/graduation.js.map +1 -1
  271. package/dist/sandbox-training/index.d.ts +9 -9
  272. package/dist/sandbox-training/index.d.ts.map +1 -1
  273. package/dist/sandbox-training/index.js +6 -6
  274. package/dist/sandbox-training/index.js.map +1 -1
  275. package/dist/sandbox-training/promotion-service.d.ts +4 -4
  276. package/dist/sandbox-training/promotion-service.d.ts.map +1 -1
  277. package/dist/sandbox-training/promotion-service.js +5 -5
  278. package/dist/sandbox-training/promotion-service.js.map +1 -1
  279. package/dist/sandbox-training/runner.d.ts +1 -1
  280. package/dist/sandbox-training/runner.d.ts.map +1 -1
  281. package/dist/sandbox-training/runner.js +74 -73
  282. package/dist/sandbox-training/runner.js.map +1 -1
  283. package/dist/sandbox-training/scorer.d.ts +4 -4
  284. package/dist/sandbox-training/scorer.js +5 -5
  285. package/dist/sandbox-training/types.d.ts +4 -4
  286. package/dist/sandbox-training/types.d.ts.map +1 -1
  287. package/dist/sandbox-training/types.js +11 -7
  288. package/dist/sandbox-training/types.js.map +1 -1
  289. package/dist/trust-engine/ceiling-enforcement/audit.d.ts +1 -1
  290. package/dist/trust-engine/ceiling-enforcement/audit.d.ts.map +1 -1
  291. package/dist/trust-engine/ceiling-enforcement/audit.js +3 -4
  292. package/dist/trust-engine/ceiling-enforcement/audit.js.map +1 -1
  293. package/dist/trust-engine/ceiling-enforcement/index.d.ts +2 -2
  294. package/dist/trust-engine/ceiling-enforcement/index.js +2 -2
  295. package/dist/trust-engine/ceiling-enforcement/kernel.d.ts +1 -1
  296. package/dist/trust-engine/ceiling-enforcement/kernel.d.ts.map +1 -1
  297. package/dist/trust-engine/ceiling-enforcement/kernel.js +1 -1
  298. package/dist/trust-engine/context-policy/enforcement.d.ts.map +1 -1
  299. package/dist/trust-engine/context-policy/factory.d.ts +1 -1
  300. package/dist/trust-engine/context-policy/factory.d.ts.map +1 -1
  301. package/dist/trust-engine/context-policy/factory.js +1 -1
  302. package/dist/trust-engine/context-policy/factory.js.map +1 -1
  303. package/dist/trust-engine/context-policy/index.d.ts +2 -2
  304. package/dist/trust-engine/context-policy/index.js +2 -2
  305. package/dist/trust-engine/creation-modifiers/index.d.ts +1 -1
  306. package/dist/trust-engine/creation-modifiers/index.js +1 -1
  307. package/dist/trust-engine/creation-modifiers/types.d.ts.map +1 -1
  308. package/dist/trust-engine/creation-modifiers/types.js +2 -3
  309. package/dist/trust-engine/creation-modifiers/types.js.map +1 -1
  310. package/dist/trust-engine/decay-profiles.d.ts +1 -1
  311. package/dist/trust-engine/decay-profiles.d.ts.map +1 -1
  312. package/dist/trust-engine/decay-profiles.js +4 -4
  313. package/dist/trust-engine/decay-profiles.js.map +1 -1
  314. package/dist/trust-engine/index.d.ts +111 -45
  315. package/dist/trust-engine/index.d.ts.map +1 -1
  316. package/dist/trust-engine/index.js +418 -61
  317. package/dist/trust-engine/index.js.map +1 -1
  318. package/dist/trust-engine/phase6-types.d.ts +10 -10
  319. package/dist/trust-engine/phase6-types.d.ts.map +1 -1
  320. package/dist/trust-engine/phase6-types.js +25 -23
  321. package/dist/trust-engine/phase6-types.js.map +1 -1
  322. package/dist/trust-engine/types.d.ts +77 -0
  323. package/dist/trust-engine/types.d.ts.map +1 -0
  324. package/dist/trust-engine/types.js +20 -0
  325. package/dist/trust-engine/types.js.map +1 -0
  326. package/package.json +5 -4
@@ -6,9 +6,11 @@
6
6
  *
7
7
  * @packageDocumentation
8
8
  */
9
- import { EventEmitter } from 'events';
10
- import { createLogger } from '../common/logger.js';
11
- const logger = createLogger({ component: 'trust-engine' });
9
+ import { EventEmitter } from "events";
10
+ import { createLogger } from "../common/logger.js";
11
+ import { READINESS_EXCEPTION_REASON_CODES, } from "./types.js";
12
+ export * from "./types.js";
13
+ const logger = createLogger({ component: "trust-engine" });
12
14
  /**
13
15
  * Trust level thresholds (8 tiers T0-T7) - per BASIS specification
14
16
  */
@@ -26,14 +28,14 @@ export const TRUST_THRESHOLDS = {
26
28
  * Trust level names (8 tiers T0-T7) - per BASIS specification
27
29
  */
28
30
  export const TRUST_LEVEL_NAMES = {
29
- 0: 'Sandbox',
30
- 1: 'Observed',
31
- 2: 'Provisional',
32
- 3: 'Monitored',
33
- 4: 'Standard',
34
- 5: 'Trusted',
35
- 6: 'Certified',
36
- 7: 'Autonomous',
31
+ 0: "Sandbox",
32
+ 1: "Observed",
33
+ 2: "Provisional",
34
+ 3: "Monitored",
35
+ 4: "Standard",
36
+ 5: "Trusted",
37
+ 6: "Certified",
38
+ 7: "Autonomous",
37
39
  };
38
40
  /**
39
41
  * Signal weights for score calculation
@@ -44,6 +46,25 @@ export const SIGNAL_WEIGHTS = {
44
46
  identity: 0.2,
45
47
  context: 0.15,
46
48
  };
49
+ const DEFAULT_READINESS_CHECKPOINT_DAYS = [
50
+ 7, 14, 28, 42, 56, 84, 112, 140, 182,
51
+ ];
52
+ const DEFAULT_READINESS_REDUCTIONS = [
53
+ 0.06, 0.06, 0.06, 0.06, 0.06, 0.05, 0.05, 0.05, 0.05,
54
+ ];
55
+ const DEFAULT_READINESS_EXCEPTION_MAX_DURATION_MS = 30 * 24 * 60 * 60 * 1000;
56
+ function toMs(days) {
57
+ return days * 24 * 60 * 60 * 1000;
58
+ }
59
+ function clampReductionScale(value) {
60
+ if (value === undefined || Number.isNaN(value))
61
+ return 1;
62
+ if (value < 0)
63
+ return 0;
64
+ if (value > 1)
65
+ return 1;
66
+ return value;
67
+ }
47
68
  /**
48
69
  * Trust Engine service with event emission and subscription limits
49
70
  */
@@ -70,20 +91,26 @@ export class TrustEngine extends EventEmitter {
70
91
  _listenerWarningThreshold;
71
92
  _listenerCounts = new Map();
72
93
  _totalListeners = 0;
94
+ _readinessMode;
95
+ _readinessCheckpointDays;
96
+ _readinessCheckpointReductions;
97
+ _allowedReadinessExceptionReasons;
98
+ _readinessExceptionMaxDurationMs;
73
99
  constructor(config = {}) {
74
100
  super();
75
101
  this._decayRate = config.decayRate ?? 0.01;
76
102
  this._decayIntervalMs = config.decayIntervalMs ?? 60000;
77
103
  this._failureThreshold = config.failureThreshold ?? 0.3;
78
- this._acceleratedDecayMultiplier = config.acceleratedDecayMultiplier ?? 3.0;
104
+ this._acceleratedDecayMultiplier = config.acceleratedDecayMultiplier ?? 1.0;
79
105
  this._failureWindowMs = config.failureWindowMs ?? 3600000; // 1 hour
80
106
  this._minFailuresForAcceleration = config.minFailuresForAcceleration ?? 2;
81
107
  this._persistence = config.persistence;
82
- this._autoPersist = config.autoPersist ?? (config.persistence !== undefined);
108
+ this._autoPersist = config.autoPersist ?? config.persistence !== undefined;
83
109
  // Recovery configuration
84
110
  this._successThreshold = config.successThreshold ?? 0.7;
85
111
  this._recoveryRate = config.recoveryRate ?? 0.02;
86
- this._acceleratedRecoveryMultiplier = config.acceleratedRecoveryMultiplier ?? 1.5;
112
+ this._acceleratedRecoveryMultiplier =
113
+ config.acceleratedRecoveryMultiplier ?? 1.5;
87
114
  this._minSuccessesForAcceleration = config.minSuccessesForAcceleration ?? 3;
88
115
  this._successWindowMs = config.successWindowMs ?? 3600000; // 1 hour
89
116
  this._maxRecoveryPerSignal = config.maxRecoveryPerSignal ?? 50;
@@ -91,9 +118,219 @@ export class TrustEngine extends EventEmitter {
91
118
  this._maxListenersPerEvent = config.maxListenersPerEvent ?? 100;
92
119
  this._maxTotalListeners = config.maxTotalListeners ?? 1000;
93
120
  this._listenerWarningThreshold = config.listenerWarningThreshold ?? 0.8;
121
+ this._readinessMode =
122
+ config.readinessMode ??
123
+ config.freshnessMode ??
124
+ (config.decayIntervalMs !== undefined || config.decayRate !== undefined
125
+ ? "legacy_interval"
126
+ : "checkpoint_schedule");
127
+ this._readinessCheckpointDays = config.readinessCheckpointDays ??
128
+ config.freshnessCheckpointDays ?? [...DEFAULT_READINESS_CHECKPOINT_DAYS];
129
+ this._readinessCheckpointReductions =
130
+ config.readinessCheckpointReductions ??
131
+ config.freshnessCheckpointReductions ?? [
132
+ ...DEFAULT_READINESS_REDUCTIONS,
133
+ ];
134
+ if (this._readinessCheckpointDays.length !==
135
+ this._readinessCheckpointReductions.length) {
136
+ throw new Error("freshnessCheckpointDays and freshnessCheckpointReductions must have equal length");
137
+ }
138
+ this._allowedReadinessExceptionReasons = new Set(config.readinessExceptionAllowedReasons ??
139
+ config.freshnessExceptionAllowedReasons ?? [
140
+ ...READINESS_EXCEPTION_REASON_CODES,
141
+ ]);
142
+ this._readinessExceptionMaxDurationMs =
143
+ config.readinessExceptionMaxDurationMs ??
144
+ config.freshnessExceptionMaxDurationMs ??
145
+ DEFAULT_READINESS_EXCEPTION_MAX_DURATION_MS;
94
146
  // Set default max listeners on EventEmitter
95
147
  this.setMaxListeners(this._maxListenersPerEvent);
96
148
  }
149
+ validateReadinessExceptionOptions(options) {
150
+ if (!this._allowedReadinessExceptionReasons.has(options.reason)) {
151
+ throw new Error(`Unsupported readiness exception reason: ${options.reason}. ` +
152
+ `Allowed reasons: ${Array.from(this._allowedReadinessExceptionReasons).join(", ")}`);
153
+ }
154
+ const now = Date.now();
155
+ const expiresAtMs = new Date(options.expiresAt).getTime();
156
+ if (Number.isNaN(expiresAtMs)) {
157
+ throw new Error("Invalid expiresAt timestamp for readiness exception");
158
+ }
159
+ if (expiresAtMs <= now) {
160
+ throw new Error("Readiness exception expiresAt must be in the future");
161
+ }
162
+ if (expiresAtMs - now > this._readinessExceptionMaxDurationMs) {
163
+ throw new Error(`Readiness exception duration exceeds configured maximum (${this._readinessExceptionMaxDurationMs} ms)`);
164
+ }
165
+ }
166
+ getCheckpointIntervalMs(index) {
167
+ if (index <= 0) {
168
+ return toMs(this._readinessCheckpointDays[0] ?? 7);
169
+ }
170
+ const current = this._readinessCheckpointDays[index] ??
171
+ this._readinessCheckpointDays[this._readinessCheckpointDays.length - 1] ??
172
+ 7;
173
+ const previous = this._readinessCheckpointDays[index - 1] ?? 0;
174
+ return toMs(Math.max(1, current - previous));
175
+ }
176
+ ensureReadinessState(record) {
177
+ record.readinessCheckpointIndex ??= record.freshnessCheckpointIndex ?? 0;
178
+ record.deferredReadinessMultiplier ??=
179
+ record.deferredFreshnessMultiplier ?? 1;
180
+ record.readinessBaselineScore ??=
181
+ record.freshnessBaselineScore ?? record.score;
182
+ record.freshnessCheckpointIndex = record.readinessCheckpointIndex;
183
+ record.deferredFreshnessMultiplier = record.deferredReadinessMultiplier;
184
+ record.freshnessBaselineScore = record.readinessBaselineScore;
185
+ record.freshnessException =
186
+ record.readinessException ?? record.freshnessException;
187
+ }
188
+ isUsingDefaultReadinessSchedule() {
189
+ if (this._readinessCheckpointDays.length !==
190
+ DEFAULT_READINESS_CHECKPOINT_DAYS.length) {
191
+ return false;
192
+ }
193
+ if (this._readinessCheckpointReductions.length !==
194
+ DEFAULT_READINESS_REDUCTIONS.length) {
195
+ return false;
196
+ }
197
+ return (this._readinessCheckpointDays.every((v, i) => v === DEFAULT_READINESS_CHECKPOINT_DAYS[i]) &&
198
+ this._readinessCheckpointReductions.every((v, i) => v === DEFAULT_READINESS_REDUCTIONS[i]));
199
+ }
200
+ isReadinessExceptionActive(record, now) {
201
+ const exception = record.readinessException ?? record.freshnessException;
202
+ if (!exception)
203
+ return false;
204
+ const issuedAt = new Date(exception.issuedAt).getTime();
205
+ const expiresAt = new Date(exception.expiresAt).getTime();
206
+ return now >= issuedAt && now < expiresAt;
207
+ }
208
+ async applyDeferredReadinessCatchupIfExpired(record) {
209
+ const exception = record.readinessException ?? record.freshnessException;
210
+ if (!exception)
211
+ return;
212
+ const now = Date.now();
213
+ const expiresAt = new Date(exception.expiresAt).getTime();
214
+ if (now < expiresAt)
215
+ return;
216
+ this.ensureReadinessState(record);
217
+ const deferredMultiplier = record.deferredReadinessMultiplier ?? 1;
218
+ if (deferredMultiplier < 1) {
219
+ const previousScore = record.score;
220
+ const adjustedScore = Math.max(0, Math.round(record.score * deferredMultiplier));
221
+ record.score = adjustedScore;
222
+ record.level = this.scoreToLevel(adjustedScore);
223
+ record.deferredReadinessMultiplier = 1;
224
+ record.deferredFreshnessMultiplier = 1;
225
+ this.emitReadinessAdjustmentEvents(record.entityId, {
226
+ previousScore,
227
+ newScore: record.score,
228
+ stalenessMs: 0,
229
+ accelerated: false,
230
+ });
231
+ }
232
+ delete record.readinessException;
233
+ delete record.freshnessException;
234
+ }
235
+ async applyScheduledReadinessAdjustment(record) {
236
+ this.ensureReadinessState(record);
237
+ await this.applyDeferredReadinessCatchupIfExpired(record);
238
+ while ((record.readinessCheckpointIndex ?? 0) <
239
+ this._readinessCheckpointDays.length) {
240
+ const checkpointIndex = record.readinessCheckpointIndex ?? 0;
241
+ const intervalMs = this.getCheckpointIntervalMs(checkpointIndex);
242
+ const stalenessMs = Date.now() - new Date(record.lastCalculatedAt).getTime();
243
+ if (stalenessMs < intervalMs) {
244
+ break;
245
+ }
246
+ const previousScore = record.score;
247
+ const previousLevel = record.level;
248
+ const fullReduction = this._readinessCheckpointReductions[checkpointIndex] ?? 0;
249
+ const activeException = this.isReadinessExceptionActive(record, Date.now());
250
+ const scale = activeException
251
+ ? clampReductionScale((record.readinessException ?? record.freshnessException)
252
+ ?.reductionScale)
253
+ : 1;
254
+ const appliedReduction = fullReduction * scale;
255
+ const appliedMultiplier = 1 - appliedReduction;
256
+ const fullMultiplier = 1 - fullReduction;
257
+ record.score = Math.max(0, Math.round(record.score * appliedMultiplier));
258
+ const isFinalCheckpoint = checkpointIndex === this._readinessCheckpointDays.length - 1;
259
+ if (isFinalCheckpoint &&
260
+ !activeException &&
261
+ this.isUsingDefaultReadinessSchedule()) {
262
+ const baseline = record.readinessBaselineScore ??
263
+ record.freshnessBaselineScore ??
264
+ record.score;
265
+ record.score = Math.max(0, Math.round(baseline * 0.5));
266
+ }
267
+ record.level = this.scoreToLevel(record.score);
268
+ record.readinessCheckpointIndex = checkpointIndex + 1;
269
+ record.freshnessCheckpointIndex = record.readinessCheckpointIndex;
270
+ const lastCalculatedMs = new Date(record.lastCalculatedAt).getTime();
271
+ record.lastCalculatedAt = new Date(lastCalculatedMs + intervalMs).toISOString();
272
+ if (activeException && appliedMultiplier > 0 && fullMultiplier >= 0) {
273
+ const debtFactor = fullMultiplier / appliedMultiplier;
274
+ record.deferredReadinessMultiplier =
275
+ (record.deferredReadinessMultiplier ?? 1) * debtFactor;
276
+ record.deferredFreshnessMultiplier = record.deferredReadinessMultiplier;
277
+ }
278
+ if (previousScore !== record.score) {
279
+ this.emitReadinessAdjustmentEvents(record.entityId, {
280
+ previousScore,
281
+ newScore: record.score,
282
+ stalenessMs,
283
+ accelerated: false,
284
+ });
285
+ if (previousLevel !== record.level) {
286
+ this.emitTrustEvent({
287
+ type: "trust:tier_changed",
288
+ entityId: record.entityId,
289
+ timestamp: new Date().toISOString(),
290
+ previousLevel,
291
+ newLevel: record.level,
292
+ previousLevelName: TRUST_LEVEL_NAMES[previousLevel],
293
+ newLevelName: TRUST_LEVEL_NAMES[record.level],
294
+ direction: record.level < previousLevel ? "demoted" : "promoted",
295
+ });
296
+ }
297
+ await this.autoPersistRecord(record);
298
+ }
299
+ }
300
+ }
301
+ emitReadinessAdjustmentEvents(entityId, details) {
302
+ const adjustmentAmount = details.previousScore - details.newScore;
303
+ this.emitTrustEvent({
304
+ type: "trust:readiness_adjusted",
305
+ entityId,
306
+ timestamp: new Date().toISOString(),
307
+ previousScore: details.previousScore,
308
+ newScore: details.newScore,
309
+ adjustmentAmount,
310
+ stalenessMs: details.stalenessMs,
311
+ accelerated: details.accelerated,
312
+ });
313
+ this.emitTrustEvent({
314
+ type: "trust:freshness_adjusted",
315
+ entityId,
316
+ timestamp: new Date().toISOString(),
317
+ previousScore: details.previousScore,
318
+ newScore: details.newScore,
319
+ adjustmentAmount,
320
+ stalenessMs: details.stalenessMs,
321
+ accelerated: details.accelerated,
322
+ });
323
+ this.emitTrustEvent({
324
+ type: "trust:decay_applied",
325
+ entityId,
326
+ timestamp: new Date().toISOString(),
327
+ previousScore: details.previousScore,
328
+ newScore: details.newScore,
329
+ decayAmount: adjustmentAmount,
330
+ stalenessMs: details.stalenessMs,
331
+ accelerated: details.accelerated,
332
+ });
333
+ }
97
334
  /**
98
335
  * Add event listener with subscription limits
99
336
  * @throws Error if listener limits are exceeded
@@ -164,10 +401,14 @@ export class TrustEngine extends EventEmitter {
164
401
  const eventThreshold = this._maxListenersPerEvent * this._listenerWarningThreshold;
165
402
  const totalThreshold = this._maxTotalListeners * this._listenerWarningThreshold;
166
403
  if (currentEventCount >= eventThreshold) {
167
- logger.warn({ eventName, current: currentEventCount, max: this._maxListenersPerEvent }, `Approaching listener limit for event "${eventName}"`);
404
+ logger.warn({
405
+ eventName,
406
+ current: currentEventCount,
407
+ max: this._maxListenersPerEvent,
408
+ }, `Approaching listener limit for event "${eventName}"`);
168
409
  }
169
410
  if (this._totalListeners >= totalThreshold) {
170
- logger.warn({ current: this._totalListeners, max: this._maxTotalListeners }, 'Approaching total listener limit');
411
+ logger.warn({ current: this._totalListeners, max: this._maxTotalListeners }, "Approaching total listener limit");
171
412
  }
172
413
  }
173
414
  /**
@@ -252,14 +493,14 @@ export class TrustEngine extends EventEmitter {
252
493
  */
253
494
  async loadFromPersistence() {
254
495
  if (!this._persistence) {
255
- throw new Error('No persistence provider configured');
496
+ throw new Error("No persistence provider configured");
256
497
  }
257
498
  const records = await this._persistence.query();
258
499
  this.records.clear();
259
500
  for (const record of records) {
260
501
  this.records.set(record.entityId, record);
261
502
  }
262
- logger.info({ count: records.length }, 'Loaded trust records from persistence');
503
+ logger.info({ count: records.length }, "Loaded trust records from persistence");
263
504
  return records.length;
264
505
  }
265
506
  /**
@@ -267,14 +508,14 @@ export class TrustEngine extends EventEmitter {
267
508
  */
268
509
  async saveToPersistence() {
269
510
  if (!this._persistence) {
270
- throw new Error('No persistence provider configured');
511
+ throw new Error("No persistence provider configured");
271
512
  }
272
513
  let count = 0;
273
514
  for (const record of this.records.values()) {
274
515
  await this._persistence.save(record);
275
516
  count++;
276
517
  }
277
- logger.info({ count }, 'Saved trust records to persistence');
518
+ logger.info({ count }, "Saved trust records to persistence");
278
519
  return count;
279
520
  }
280
521
  /**
@@ -299,8 +540,8 @@ export class TrustEngine extends EventEmitter {
299
540
  */
300
541
  emitTrustEvent(event) {
301
542
  this.emit(event.type, event);
302
- this.emit('trust:*', event); // Wildcard for all events
303
- logger.debug({ event }, 'Trust event emitted');
543
+ this.emit("trust:*", event); // Wildcard for all events
544
+ logger.debug({ event }, "Trust event emitted");
304
545
  }
305
546
  /**
306
547
  * Calculate trust score for an entity
@@ -308,8 +549,9 @@ export class TrustEngine extends EventEmitter {
308
549
  async calculate(entityId) {
309
550
  const record = this.records.get(entityId);
310
551
  const signals = record?.signals ?? [];
552
+ const currentLevel = record?.level ?? 1;
311
553
  // Calculate component scores
312
- const components = this.calculateComponents(signals);
554
+ const components = this.calculateComponents(signals, currentLevel);
313
555
  // Calculate weighted total
314
556
  const score = Math.round(components.behavioral * SIGNAL_WEIGHTS.behavioral * 1000 +
315
557
  components.compliance * SIGNAL_WEIGHTS.compliance * 1000 +
@@ -319,7 +561,7 @@ export class TrustEngine extends EventEmitter {
319
561
  const clampedScore = Math.max(0, Math.min(1000, score));
320
562
  const level = this.scoreToLevel(clampedScore);
321
563
  const factors = this.getSignificantFactors(components);
322
- logger.debug({ entityId, score: clampedScore, level, components }, 'Trust calculated');
564
+ logger.debug({ entityId, score: clampedScore, level, components }, "Trust calculated");
323
565
  return {
324
566
  score: clampedScore,
325
567
  level,
@@ -386,7 +628,7 @@ export class TrustEngine extends EventEmitter {
386
628
  record.lastCalculatedAt = new Date().toISOString();
387
629
  // Emit recovery event
388
630
  this.emitTrustEvent({
389
- type: 'trust:recovery_applied',
631
+ type: "trust:recovery_applied",
390
632
  entityId: record.entityId,
391
633
  timestamp: new Date().toISOString(),
392
634
  signal,
@@ -399,10 +641,10 @@ export class TrustEngine extends EventEmitter {
399
641
  // Check for milestones
400
642
  if (previousLevel !== record.level && record.level > previousLevel) {
401
643
  this.emitTrustEvent({
402
- type: 'trust:recovery_milestone',
644
+ type: "trust:recovery_milestone",
403
645
  entityId: record.entityId,
404
646
  timestamp: new Date().toISOString(),
405
- milestone: 'tier_restored',
647
+ milestone: "tier_restored",
406
648
  previousScore,
407
649
  newScore: record.score,
408
650
  details: `Promoted from ${TRUST_LEVEL_NAMES[previousLevel]} to ${TRUST_LEVEL_NAMES[record.level]}`,
@@ -411,10 +653,10 @@ export class TrustEngine extends EventEmitter {
411
653
  // Check if accelerated recovery was just earned
412
654
  if (record.consecutiveSuccesses === this._minSuccessesForAcceleration) {
413
655
  this.emitTrustEvent({
414
- type: 'trust:recovery_milestone',
656
+ type: "trust:recovery_milestone",
415
657
  entityId: record.entityId,
416
658
  timestamp: new Date().toISOString(),
417
- milestone: 'accelerated_recovery_earned',
659
+ milestone: "accelerated_recovery_earned",
418
660
  previousScore,
419
661
  newScore: record.score,
420
662
  details: `Earned accelerated recovery after ${this._minSuccessesForAcceleration} consecutive successes`,
@@ -423,10 +665,10 @@ export class TrustEngine extends EventEmitter {
423
665
  // Check for full recovery
424
666
  if (record.score >= record.peakScore && previousScore < record.peakScore) {
425
667
  this.emitTrustEvent({
426
- type: 'trust:recovery_milestone',
668
+ type: "trust:recovery_milestone",
427
669
  entityId: record.entityId,
428
670
  timestamp: new Date().toISOString(),
429
- milestone: 'full_recovery',
671
+ milestone: "full_recovery",
430
672
  previousScore,
431
673
  newScore: record.score,
432
674
  details: `Fully recovered to peak score of ${record.peakScore}`,
@@ -438,7 +680,7 @@ export class TrustEngine extends EventEmitter {
438
680
  newScore: record.score,
439
681
  recoveryAmount,
440
682
  accelerated,
441
- }, 'Trust recovery applied');
683
+ }, "Trust recovery applied");
442
684
  }
443
685
  /**
444
686
  * Get trust score for an entity (with automatic decay)
@@ -448,6 +690,10 @@ export class TrustEngine extends EventEmitter {
448
690
  if (record) {
449
691
  // Clean up old failures
450
692
  this.cleanupFailures(record);
693
+ if (this._readinessMode === "checkpoint_schedule") {
694
+ await this.applyScheduledReadinessAdjustment(record);
695
+ return record;
696
+ }
451
697
  // Apply decay if stale
452
698
  const staleness = Date.now() - new Date(record.lastCalculatedAt).getTime();
453
699
  if (staleness > this._decayIntervalMs) {
@@ -469,7 +715,7 @@ export class TrustEngine extends EventEmitter {
469
715
  // Emit decay event
470
716
  if (previousScore !== record.score) {
471
717
  this.emitTrustEvent({
472
- type: 'trust:decay_applied',
718
+ type: "trust:decay_applied",
473
719
  entityId,
474
720
  timestamp: new Date().toISOString(),
475
721
  previousScore,
@@ -481,14 +727,14 @@ export class TrustEngine extends EventEmitter {
481
727
  // Emit tier change if applicable
482
728
  if (previousLevel !== record.level) {
483
729
  this.emitTrustEvent({
484
- type: 'trust:tier_changed',
730
+ type: "trust:tier_changed",
485
731
  entityId,
486
732
  timestamp: new Date().toISOString(),
487
733
  previousLevel,
488
734
  newLevel: record.level,
489
735
  previousLevelName: TRUST_LEVEL_NAMES[previousLevel],
490
736
  newLevelName: TRUST_LEVEL_NAMES[record.level],
491
- direction: record.level < previousLevel ? 'demoted' : 'promoted',
737
+ direction: record.level < previousLevel ? "demoted" : "promoted",
492
738
  });
493
739
  }
494
740
  // Auto-persist after decay
@@ -519,7 +765,7 @@ export class TrustEngine extends EventEmitter {
519
765
  record.consecutiveSuccesses = 0;
520
766
  const acceleratedDecayActive = this.hasAcceleratedDecay(record);
521
767
  this.emitTrustEvent({
522
- type: 'trust:failure_detected',
768
+ type: "trust:failure_detected",
523
769
  entityId: signal.entityId,
524
770
  timestamp: new Date().toISOString(),
525
771
  signal,
@@ -532,7 +778,7 @@ export class TrustEngine extends EventEmitter {
532
778
  signalValue: signal.value,
533
779
  failureCount: record.recentFailures.length,
534
780
  acceleratedDecayActive,
535
- }, 'Failure signal detected');
781
+ }, "Failure signal detected");
536
782
  }
537
783
  // Detect success signals and apply recovery
538
784
  if (signal.value >= this._successThreshold) {
@@ -550,7 +796,7 @@ export class TrustEngine extends EventEmitter {
550
796
  signalValue: signal.value,
551
797
  consecutiveSuccesses: record.consecutiveSuccesses,
552
798
  recoveryAmount,
553
- }, 'Success signal detected');
799
+ }, "Success signal detected");
554
800
  }
555
801
  // Add signal
556
802
  record.signals.push(signal);
@@ -565,6 +811,12 @@ export class TrustEngine extends EventEmitter {
565
811
  record.level = calculation.level;
566
812
  record.components = calculation.components;
567
813
  record.lastCalculatedAt = new Date().toISOString();
814
+ record.readinessCheckpointIndex = 0;
815
+ record.deferredReadinessMultiplier = 1;
816
+ record.readinessBaselineScore = calculation.score;
817
+ record.freshnessCheckpointIndex = 0;
818
+ record.deferredFreshnessMultiplier = 1;
819
+ record.freshnessBaselineScore = calculation.score;
568
820
  // Record history if significant change
569
821
  if (Math.abs(calculation.score - previousScore) >= 10) {
570
822
  record.history.push({
@@ -580,7 +832,7 @@ export class TrustEngine extends EventEmitter {
580
832
  }
581
833
  // Emit signal recorded event
582
834
  this.emitTrustEvent({
583
- type: 'trust:signal_recorded',
835
+ type: "trust:signal_recorded",
584
836
  entityId: signal.entityId,
585
837
  timestamp: new Date().toISOString(),
586
838
  signal,
@@ -590,7 +842,7 @@ export class TrustEngine extends EventEmitter {
590
842
  // Emit score changed event if significant
591
843
  if (Math.abs(calculation.score - previousScore) >= 5) {
592
844
  this.emitTrustEvent({
593
- type: 'trust:score_changed',
845
+ type: "trust:score_changed",
594
846
  entityId: signal.entityId,
595
847
  timestamp: new Date().toISOString(),
596
848
  previousScore,
@@ -602,14 +854,14 @@ export class TrustEngine extends EventEmitter {
602
854
  // Emit tier changed event if applicable
603
855
  if (previousLevel !== calculation.level && !isNewEntity) {
604
856
  this.emitTrustEvent({
605
- type: 'trust:tier_changed',
857
+ type: "trust:tier_changed",
606
858
  entityId: signal.entityId,
607
859
  timestamp: new Date().toISOString(),
608
860
  previousLevel,
609
861
  newLevel: calculation.level,
610
862
  previousLevelName: TRUST_LEVEL_NAMES[previousLevel],
611
863
  newLevelName: TRUST_LEVEL_NAMES[calculation.level],
612
- direction: calculation.level > previousLevel ? 'promoted' : 'demoted',
864
+ direction: calculation.level > previousLevel ? "promoted" : "demoted",
613
865
  });
614
866
  }
615
867
  // Auto-persist if enabled
@@ -618,7 +870,7 @@ export class TrustEngine extends EventEmitter {
618
870
  entityId: signal.entityId,
619
871
  signalType: signal.type,
620
872
  newScore: calculation.score,
621
- }, 'Signal recorded');
873
+ }, "Signal recorded");
622
874
  }
623
875
  /**
624
876
  * Initialize trust for a new entity
@@ -641,7 +893,7 @@ export class TrustEngine extends EventEmitter {
641
893
  {
642
894
  score,
643
895
  level: initialLevel,
644
- reason: 'Initial registration',
896
+ reason: "Initial registration",
645
897
  timestamp: new Date().toISOString(),
646
898
  },
647
899
  ],
@@ -649,19 +901,25 @@ export class TrustEngine extends EventEmitter {
649
901
  recentSuccesses: [],
650
902
  peakScore: score,
651
903
  consecutiveSuccesses: 0,
904
+ readinessCheckpointIndex: 0,
905
+ deferredReadinessMultiplier: 1,
906
+ readinessBaselineScore: score,
907
+ freshnessCheckpointIndex: 0,
908
+ deferredFreshnessMultiplier: 1,
909
+ freshnessBaselineScore: score,
652
910
  };
653
911
  this.records.set(entityId, record);
654
912
  // Auto-persist if enabled
655
913
  await this.autoPersistRecord(record);
656
914
  // Emit initialized event
657
915
  this.emitTrustEvent({
658
- type: 'trust:initialized',
916
+ type: "trust:initialized",
659
917
  entityId,
660
918
  timestamp: new Date().toISOString(),
661
919
  initialScore: score,
662
920
  initialLevel,
663
921
  });
664
- logger.info({ entityId, initialLevel }, 'Entity trust initialized');
922
+ logger.info({ entityId, initialLevel }, "Entity trust initialized");
665
923
  return record;
666
924
  }
667
925
  /**
@@ -690,23 +948,23 @@ export class TrustEngine extends EventEmitter {
690
948
  /**
691
949
  * Calculate component scores from signals
692
950
  */
693
- calculateComponents(signals) {
951
+ calculateComponents(signals, currentLevel) {
694
952
  // Group signals by type
695
- const behavioral = signals.filter((s) => s.type.startsWith('behavioral.'));
696
- const compliance = signals.filter((s) => s.type.startsWith('compliance.'));
697
- const identity = signals.filter((s) => s.type.startsWith('identity.'));
698
- const context = signals.filter((s) => s.type.startsWith('context.'));
953
+ const behavioral = signals.filter((s) => s.type.startsWith("behavioral."));
954
+ const compliance = signals.filter((s) => s.type.startsWith("compliance."));
955
+ const identity = signals.filter((s) => s.type.startsWith("identity."));
956
+ const context = signals.filter((s) => s.type.startsWith("context."));
699
957
  return {
700
- behavioral: this.averageSignalValue(behavioral, 0.5),
701
- compliance: this.averageSignalValue(compliance, 0.5),
702
- identity: this.averageSignalValue(identity, 0.5),
703
- context: this.averageSignalValue(context, 0.5),
958
+ behavioral: this.averageSignalValue(behavioral, 0.5, currentLevel),
959
+ compliance: this.averageSignalValue(compliance, 0.5, currentLevel),
960
+ identity: this.averageSignalValue(identity, 0.5, currentLevel),
961
+ context: this.averageSignalValue(context, 0.5, currentLevel),
704
962
  };
705
963
  }
706
964
  /**
707
965
  * Calculate average signal value with default
708
966
  */
709
- averageSignalValue(signals, defaultValue) {
967
+ averageSignalValue(signals, defaultValue, currentLevel) {
710
968
  if (signals.length === 0)
711
969
  return defaultValue;
712
970
  // Weight recent signals more heavily
@@ -716,27 +974,66 @@ export class TrustEngine extends EventEmitter {
716
974
  for (const signal of signals) {
717
975
  const age = now - new Date(signal.timestamp).getTime();
718
976
  const weight = Math.exp(-age / (7 * 24 * 60 * 60 * 1000)); // 7-day half-life
719
- weightedSum += signal.value * weight;
977
+ const adjustedValue = this.adjustSignalValueForTier(signal, defaultValue, currentLevel);
978
+ weightedSum += adjustedValue * weight;
720
979
  totalWeight += weight;
721
980
  }
722
981
  return totalWeight > 0 ? weightedSum / totalWeight : defaultValue;
723
982
  }
983
+ /**
984
+ * Human/manual positive approvals carry less upward impact at higher tiers.
985
+ */
986
+ adjustSignalValueForTier(signal, defaultValue, currentLevel) {
987
+ if (!this.isHumanApprovalSignal(signal) || signal.value <= defaultValue) {
988
+ return signal.value;
989
+ }
990
+ const assistFactor = this.getHumanApprovalAssistFactor(currentLevel);
991
+ return defaultValue + (signal.value - defaultValue) * assistFactor;
992
+ }
993
+ isHumanApprovalSignal(signal) {
994
+ const source = signal.source?.toLowerCase() ?? "";
995
+ return (source === "manual" ||
996
+ source === "human" ||
997
+ source === "human_review" ||
998
+ source === "human-approval");
999
+ }
1000
+ getHumanApprovalAssistFactor(level) {
1001
+ switch (level) {
1002
+ case 0:
1003
+ case 1:
1004
+ return 1.0;
1005
+ case 2:
1006
+ return 0.85;
1007
+ case 3:
1008
+ return 0.7;
1009
+ case 4:
1010
+ return 0.55;
1011
+ case 5:
1012
+ return 0.4;
1013
+ case 6:
1014
+ return 0.3;
1015
+ case 7:
1016
+ return 0.2;
1017
+ default:
1018
+ return 1.0;
1019
+ }
1020
+ }
724
1021
  /**
725
1022
  * Get significant factors affecting the score
726
1023
  */
727
1024
  getSignificantFactors(components) {
728
1025
  const factors = [];
729
1026
  if (components.behavioral < 0.3) {
730
- factors.push('Low behavioral trust');
1027
+ factors.push("Low behavioral trust");
731
1028
  }
732
1029
  if (components.compliance < 0.3) {
733
- factors.push('Low compliance score');
1030
+ factors.push("Low compliance score");
734
1031
  }
735
1032
  if (components.identity < 0.3) {
736
- factors.push('Weak identity verification');
1033
+ factors.push("Weak identity verification");
737
1034
  }
738
1035
  if (components.context < 0.3) {
739
- factors.push('Unusual context signals');
1036
+ factors.push("Unusual context signals");
740
1037
  }
741
1038
  return factors;
742
1039
  }
@@ -762,7 +1059,67 @@ export class TrustEngine extends EventEmitter {
762
1059
  recentSuccesses: [],
763
1060
  peakScore: initialScore,
764
1061
  consecutiveSuccesses: 0,
1062
+ readinessCheckpointIndex: 0,
1063
+ deferredReadinessMultiplier: 1,
1064
+ readinessBaselineScore: initialScore,
1065
+ freshnessCheckpointIndex: 0,
1066
+ deferredFreshnessMultiplier: 1,
1067
+ freshnessBaselineScore: initialScore,
1068
+ };
1069
+ }
1070
+ /**
1071
+ * Configure a time-bound Readiness Degree exception for an entity.
1072
+ */
1073
+ setReadinessException(entityId, options) {
1074
+ const record = this.records.get(entityId);
1075
+ if (!record) {
1076
+ throw new Error(`Entity not found: ${entityId}`);
1077
+ }
1078
+ this.validateReadinessExceptionOptions(options);
1079
+ this.ensureReadinessState(record);
1080
+ record.readinessException = {
1081
+ reason: options.reason,
1082
+ issuedAt: new Date().toISOString(),
1083
+ expiresAt: options.expiresAt,
1084
+ reductionScale: clampReductionScale(options.reductionScale),
765
1085
  };
1086
+ record.freshnessException = record.readinessException;
1087
+ }
1088
+ /**
1089
+ * @deprecated Use setReadinessException.
1090
+ */
1091
+ setFreshnessException(entityId, options) {
1092
+ this.setReadinessException(entityId, options);
1093
+ }
1094
+ /**
1095
+ * Clear Readiness Degree exception for an entity.
1096
+ */
1097
+ clearReadinessException(entityId) {
1098
+ const record = this.records.get(entityId);
1099
+ if (!record) {
1100
+ return;
1101
+ }
1102
+ delete record.readinessException;
1103
+ delete record.freshnessException;
1104
+ }
1105
+ /**
1106
+ * @deprecated Use clearReadinessException.
1107
+ */
1108
+ clearFreshnessException(entityId) {
1109
+ this.clearReadinessException(entityId);
1110
+ }
1111
+ /**
1112
+ * Get active Readiness Degree exception for an entity.
1113
+ */
1114
+ getReadinessException(entityId) {
1115
+ const record = this.records.get(entityId);
1116
+ return record?.readinessException ?? record?.freshnessException;
1117
+ }
1118
+ /**
1119
+ * @deprecated Use getReadinessException.
1120
+ */
1121
+ getFreshnessException(entityId) {
1122
+ return this.getReadinessException(entityId);
766
1123
  }
767
1124
  /**
768
1125
  * Check if accelerated decay is currently active for an entity