shield360 1.0.1 → 1.2.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 (424) hide show
  1. package/README.md +392 -37
  2. package/dist/__tests__/build-info.test.d.ts +1 -0
  3. package/dist/__tests__/build-info.test.js +196 -0
  4. package/dist/__tests__/build-info.test.js.map +1 -0
  5. package/dist/__tests__/code-location.test.d.ts +1 -0
  6. package/dist/__tests__/code-location.test.js +180 -0
  7. package/dist/__tests__/code-location.test.js.map +1 -0
  8. package/dist/__tests__/masking.test.d.ts +1 -0
  9. package/dist/__tests__/masking.test.js +66 -0
  10. package/dist/__tests__/masking.test.js.map +1 -0
  11. package/dist/__tests__/pricing-claude-5.test.js +3 -0
  12. package/dist/__tests__/pricing-claude-5.test.js.map +1 -1
  13. package/dist/__tests__/register.e2e.test.d.ts +1 -0
  14. package/dist/__tests__/register.e2e.test.js +264 -0
  15. package/dist/__tests__/register.e2e.test.js.map +1 -0
  16. package/dist/__tests__/register.test.js +60 -0
  17. package/dist/__tests__/register.test.js.map +1 -1
  18. package/dist/agents/__tests__/agents.test.d.ts +1 -0
  19. package/dist/agents/__tests__/agents.test.js +529 -0
  20. package/dist/agents/__tests__/agents.test.js.map +1 -0
  21. package/dist/agents/index.d.ts +15 -0
  22. package/dist/agents/index.js +25 -0
  23. package/dist/agents/index.js.map +1 -0
  24. package/dist/agents/passport.d.ts +92 -0
  25. package/dist/agents/passport.js +301 -0
  26. package/dist/agents/passport.js.map +1 -0
  27. package/dist/agents/policy.d.ts +24 -0
  28. package/dist/agents/policy.js +93 -0
  29. package/dist/agents/policy.js.map +1 -0
  30. package/dist/agents/replay.d.ts +20 -0
  31. package/dist/agents/replay.js +47 -0
  32. package/dist/agents/replay.js.map +1 -0
  33. package/dist/agents/report.d.ts +30 -0
  34. package/dist/agents/report.js +93 -0
  35. package/dist/agents/report.js.map +1 -0
  36. package/dist/agents/types.d.ts +148 -0
  37. package/dist/agents/types.js +37 -0
  38. package/dist/agents/types.js.map +1 -0
  39. package/dist/agents/verifier.d.ts +33 -0
  40. package/dist/agents/verifier.js +276 -0
  41. package/dist/agents/verifier.js.map +1 -0
  42. package/dist/ai-security/__tests__/bench.test.d.ts +1 -0
  43. package/dist/ai-security/__tests__/bench.test.js +50 -0
  44. package/dist/ai-security/__tests__/bench.test.js.map +1 -0
  45. package/dist/ai-security/__tests__/checks.test.d.ts +1 -0
  46. package/dist/ai-security/__tests__/checks.test.js +248 -0
  47. package/dist/ai-security/__tests__/checks.test.js.map +1 -0
  48. package/dist/ai-security/__tests__/config.test.d.ts +1 -0
  49. package/dist/ai-security/__tests__/config.test.js +164 -0
  50. package/dist/ai-security/__tests__/config.test.js.map +1 -0
  51. package/dist/ai-security/__tests__/detection.test.d.ts +1 -0
  52. package/dist/ai-security/__tests__/detection.test.js +114 -0
  53. package/dist/ai-security/__tests__/detection.test.js.map +1 -0
  54. package/dist/ai-security/__tests__/fixtures.d.ts +8 -0
  55. package/dist/ai-security/__tests__/fixtures.js +30 -0
  56. package/dist/ai-security/__tests__/fixtures.js.map +1 -0
  57. package/dist/ai-security/__tests__/hooks.test.d.ts +1 -0
  58. package/dist/ai-security/__tests__/hooks.test.js +174 -0
  59. package/dist/ai-security/__tests__/hooks.test.js.map +1 -0
  60. package/dist/ai-security/__tests__/stream.test.d.ts +1 -0
  61. package/dist/ai-security/__tests__/stream.test.js +85 -0
  62. package/dist/ai-security/__tests__/stream.test.js.map +1 -0
  63. package/dist/ai-security/config.d.ts +94 -0
  64. package/dist/ai-security/config.js +241 -0
  65. package/dist/ai-security/config.js.map +1 -0
  66. package/dist/ai-security/context.d.ts +45 -0
  67. package/dist/ai-security/context.js +108 -0
  68. package/dist/ai-security/context.js.map +1 -0
  69. package/dist/ai-security/custom-kinds.d.ts +23 -0
  70. package/dist/ai-security/custom-kinds.js +97 -0
  71. package/dist/ai-security/custom-kinds.js.map +1 -0
  72. package/dist/ai-security/events.d.ts +77 -0
  73. package/dist/ai-security/events.js +153 -0
  74. package/dist/ai-security/events.js.map +1 -0
  75. package/dist/ai-security/hooks.d.ts +48 -0
  76. package/dist/ai-security/hooks.js +461 -0
  77. package/dist/ai-security/hooks.js.map +1 -0
  78. package/dist/ai-security/index.d.ts +209 -0
  79. package/dist/ai-security/index.js +587 -0
  80. package/dist/ai-security/index.js.map +1 -0
  81. package/dist/ai-security/injection-rules.json +1024 -0
  82. package/dist/ai-security/injection.d.ts +46 -0
  83. package/dist/ai-security/injection.js +635 -0
  84. package/dist/ai-security/injection.js.map +1 -0
  85. package/dist/ai-security/jailbreak.d.ts +38 -0
  86. package/dist/ai-security/jailbreak.js +73 -0
  87. package/dist/ai-security/jailbreak.js.map +1 -0
  88. package/dist/ai-security/limits.d.ts +84 -0
  89. package/dist/ai-security/limits.js +195 -0
  90. package/dist/ai-security/limits.js.map +1 -0
  91. package/dist/ai-security/mcp.d.ts +82 -0
  92. package/dist/ai-security/mcp.js +150 -0
  93. package/dist/ai-security/mcp.js.map +1 -0
  94. package/dist/ai-security/output.d.ts +107 -0
  95. package/dist/ai-security/output.js +390 -0
  96. package/dist/ai-security/output.js.map +1 -0
  97. package/dist/ai-security/policy.d.ts +125 -0
  98. package/dist/ai-security/policy.js +196 -0
  99. package/dist/ai-security/policy.js.map +1 -0
  100. package/dist/ai-security/rag.d.ts +70 -0
  101. package/dist/ai-security/rag.js +174 -0
  102. package/dist/ai-security/rag.js.map +1 -0
  103. package/dist/ai-security/tool-rules.json +203 -0
  104. package/dist/ai-security/tools.d.ts +46 -0
  105. package/dist/ai-security/tools.js +62 -0
  106. package/dist/ai-security/tools.js.map +1 -0
  107. package/dist/budgets/__tests__/budgets.test.d.ts +1 -0
  108. package/dist/budgets/__tests__/budgets.test.js +134 -0
  109. package/dist/budgets/__tests__/budgets.test.js.map +1 -0
  110. package/dist/budgets/auto.d.ts +25 -0
  111. package/dist/budgets/auto.js +63 -0
  112. package/dist/budgets/auto.js.map +1 -0
  113. package/dist/budgets/index.d.ts +110 -0
  114. package/dist/budgets/index.js +239 -0
  115. package/dist/budgets/index.js.map +1 -0
  116. package/dist/config.js +1 -1
  117. package/dist/config.js.map +1 -1
  118. package/dist/customer/__tests__/customer.test.d.ts +1 -0
  119. package/dist/customer/__tests__/customer.test.js +155 -0
  120. package/dist/customer/__tests__/customer.test.js.map +1 -0
  121. package/dist/customer/index.d.ts +48 -0
  122. package/dist/customer/index.js +132 -0
  123. package/dist/customer/index.js.map +1 -0
  124. package/dist/feedback/__tests__/feedback.test.d.ts +1 -0
  125. package/dist/feedback/__tests__/feedback.test.js +80 -0
  126. package/dist/feedback/__tests__/feedback.test.js.map +1 -0
  127. package/dist/feedback/index.d.ts +48 -0
  128. package/dist/feedback/index.js +97 -0
  129. package/dist/feedback/index.js.map +1 -0
  130. package/dist/flags/__tests__/flags.test.d.ts +1 -0
  131. package/dist/flags/__tests__/flags.test.js +301 -0
  132. package/dist/flags/__tests__/flags.test.js.map +1 -0
  133. package/dist/flags/client.d.ts +131 -0
  134. package/dist/flags/client.js +301 -0
  135. package/dist/flags/client.js.map +1 -0
  136. package/dist/flags/engine.d.ts +200 -0
  137. package/dist/flags/engine.js +677 -0
  138. package/dist/flags/engine.js.map +1 -0
  139. package/dist/flags/index.d.ts +4 -0
  140. package/dist/flags/index.js +16 -0
  141. package/dist/flags/index.js.map +1 -0
  142. package/dist/guard/__tests__/findings.test.js +28 -9
  143. package/dist/guard/__tests__/findings.test.js.map +1 -1
  144. package/dist/guard/__tests__/report.test.js +67 -0
  145. package/dist/guard/__tests__/report.test.js.map +1 -1
  146. package/dist/guard/base.d.ts +2 -0
  147. package/dist/guard/base.js +4 -0
  148. package/dist/guard/base.js.map +1 -1
  149. package/dist/guard/findings.d.ts +12 -2
  150. package/dist/guard/findings.js +19 -49
  151. package/dist/guard/findings.js.map +1 -1
  152. package/dist/guard/heartbeat.d.ts +34 -0
  153. package/dist/guard/heartbeat.js +83 -0
  154. package/dist/guard/heartbeat.js.map +1 -0
  155. package/dist/guard/integration.d.ts +33 -3
  156. package/dist/guard/integration.js +106 -32
  157. package/dist/guard/integration.js.map +1 -1
  158. package/dist/guard/pipeline.d.ts +10 -1
  159. package/dist/guard/pipeline.js +14 -0
  160. package/dist/guard/pipeline.js.map +1 -1
  161. package/dist/guard/report.d.ts +24 -1
  162. package/dist/guard/report.js +67 -18
  163. package/dist/guard/report.js.map +1 -1
  164. package/dist/index.d.ts +90 -0
  165. package/dist/index.js +225 -3
  166. package/dist/index.js.map +1 -1
  167. package/dist/instrumentation/__tests__/langchain-wrapper.test.js +1 -1
  168. package/dist/instrumentation/__tests__/langchain-wrapper.test.js.map +1 -1
  169. package/dist/instrumentation/anthropic/wrapper.js +4 -0
  170. package/dist/instrumentation/anthropic/wrapper.js.map +1 -1
  171. package/dist/instrumentation/mcp/wrapper.js +7 -1
  172. package/dist/instrumentation/mcp/wrapper.js.map +1 -1
  173. package/dist/instrumentation/openai/wrapper.js +6 -0
  174. package/dist/instrumentation/openai/wrapper.js.map +1 -1
  175. package/dist/masking.d.ts +42 -0
  176. package/dist/masking.js +197 -0
  177. package/dist/masking.js.map +1 -0
  178. package/dist/otel/__tests__/app-logs-safety.test.d.ts +1 -0
  179. package/dist/otel/__tests__/app-logs-safety.test.js +129 -0
  180. package/dist/otel/__tests__/app-logs-safety.test.js.map +1 -0
  181. package/dist/otel/__tests__/app-logs.test.d.ts +1 -0
  182. package/dist/otel/__tests__/app-logs.test.js +269 -0
  183. package/dist/otel/__tests__/app-logs.test.js.map +1 -0
  184. package/dist/otel/__tests__/log-auto.test.d.ts +1 -0
  185. package/dist/otel/__tests__/log-auto.test.js +125 -0
  186. package/dist/otel/__tests__/log-auto.test.js.map +1 -0
  187. package/dist/otel/__tests__/log-bridges.test.d.ts +1 -0
  188. package/dist/otel/__tests__/log-bridges.test.js +170 -0
  189. package/dist/otel/__tests__/log-bridges.test.js.map +1 -0
  190. package/dist/otel/__tests__/system-metrics.test.d.ts +1 -0
  191. package/dist/otel/__tests__/system-metrics.test.js +79 -0
  192. package/dist/otel/__tests__/system-metrics.test.js.map +1 -0
  193. package/dist/otel/app-logs.d.ts +80 -0
  194. package/dist/otel/app-logs.js +195 -0
  195. package/dist/otel/app-logs.js.map +1 -0
  196. package/dist/otel/build-info.d.ts +23 -0
  197. package/dist/otel/build-info.js +176 -0
  198. package/dist/otel/build-info.js.map +1 -0
  199. package/dist/otel/code-location.d.ts +49 -0
  200. package/dist/otel/code-location.js +233 -0
  201. package/dist/otel/code-location.js.map +1 -0
  202. package/dist/otel/events.d.ts +1 -0
  203. package/dist/otel/events.js +21 -12
  204. package/dist/otel/events.js.map +1 -1
  205. package/dist/otel/log-auto.d.ts +44 -0
  206. package/dist/otel/log-auto.js +200 -0
  207. package/dist/otel/log-auto.js.map +1 -0
  208. package/dist/otel/log-bridges.d.ts +54 -0
  209. package/dist/otel/log-bridges.js +307 -0
  210. package/dist/otel/log-bridges.js.map +1 -0
  211. package/dist/otel/system-metrics.d.ts +39 -0
  212. package/dist/otel/system-metrics.js +166 -0
  213. package/dist/otel/system-metrics.js.map +1 -0
  214. package/dist/otel/tracing.js +12 -1
  215. package/dist/otel/tracing.js.map +1 -1
  216. package/dist/pricing.json +100 -42
  217. package/dist/protect/__tests__/protect.test.d.ts +1 -0
  218. package/dist/protect/__tests__/protect.test.js +210 -0
  219. package/dist/protect/__tests__/protect.test.js.map +1 -0
  220. package/dist/protect/index.d.ts +103 -0
  221. package/dist/protect/index.js +196 -0
  222. package/dist/protect/index.js.map +1 -0
  223. package/dist/protect/mcp.d.ts +13 -0
  224. package/dist/protect/mcp.js +49 -0
  225. package/dist/protect/mcp.js.map +1 -0
  226. package/dist/protect/mode.d.ts +89 -0
  227. package/dist/protect/mode.js +134 -0
  228. package/dist/protect/mode.js.map +1 -0
  229. package/dist/rasp/__tests__/auto-http.test.d.ts +1 -0
  230. package/dist/rasp/__tests__/auto-http.test.js +136 -0
  231. package/dist/rasp/__tests__/auto-http.test.js.map +1 -0
  232. package/dist/rasp/__tests__/baseline.test.d.ts +1 -0
  233. package/dist/rasp/__tests__/baseline.test.js +86 -0
  234. package/dist/rasp/__tests__/baseline.test.js.map +1 -0
  235. package/dist/rasp/__tests__/benign-corpus.test.d.ts +1 -0
  236. package/dist/rasp/__tests__/benign-corpus.test.js +68 -0
  237. package/dist/rasp/__tests__/benign-corpus.test.js.map +1 -0
  238. package/dist/rasp/__tests__/capture-context.test.d.ts +1 -0
  239. package/dist/rasp/__tests__/capture-context.test.js +135 -0
  240. package/dist/rasp/__tests__/capture-context.test.js.map +1 -0
  241. package/dist/rasp/__tests__/code-hook.test.d.ts +1 -0
  242. package/dist/rasp/__tests__/code-hook.test.js +218 -0
  243. package/dist/rasp/__tests__/code-hook.test.js.map +1 -0
  244. package/dist/rasp/__tests__/config-client.test.d.ts +1 -0
  245. package/dist/rasp/__tests__/config-client.test.js +283 -0
  246. package/dist/rasp/__tests__/config-client.test.js.map +1 -0
  247. package/dist/rasp/__tests__/corpus.d.ts +13 -0
  248. package/dist/rasp/__tests__/corpus.js +111 -0
  249. package/dist/rasp/__tests__/corpus.js.map +1 -0
  250. package/dist/rasp/__tests__/custom-rules.test.d.ts +1 -0
  251. package/dist/rasp/__tests__/custom-rules.test.js +276 -0
  252. package/dist/rasp/__tests__/custom-rules.test.js.map +1 -0
  253. package/dist/rasp/__tests__/db-hook.test.d.ts +1 -0
  254. package/dist/rasp/__tests__/db-hook.test.js +438 -0
  255. package/dist/rasp/__tests__/db-hook.test.js.map +1 -0
  256. package/dist/rasp/__tests__/deception.test.d.ts +1 -0
  257. package/dist/rasp/__tests__/deception.test.js +567 -0
  258. package/dist/rasp/__tests__/deception.test.js.map +1 -0
  259. package/dist/rasp/__tests__/detect.test.d.ts +1 -0
  260. package/dist/rasp/__tests__/detect.test.js +276 -0
  261. package/dist/rasp/__tests__/detect.test.js.map +1 -0
  262. package/dist/rasp/__tests__/esm-exports.test.d.ts +1 -0
  263. package/dist/rasp/__tests__/esm-exports.test.js +20 -0
  264. package/dist/rasp/__tests__/esm-exports.test.js.map +1 -0
  265. package/dist/rasp/__tests__/fs-hook.test.d.ts +1 -0
  266. package/dist/rasp/__tests__/fs-hook.test.js +241 -0
  267. package/dist/rasp/__tests__/fs-hook.test.js.map +1 -0
  268. package/dist/rasp/__tests__/hook-contracts.test.d.ts +1 -0
  269. package/dist/rasp/__tests__/hook-contracts.test.js +201 -0
  270. package/dist/rasp/__tests__/hook-contracts.test.js.map +1 -0
  271. package/dist/rasp/__tests__/hook-kit.d.ts +42 -0
  272. package/dist/rasp/__tests__/hook-kit.js +139 -0
  273. package/dist/rasp/__tests__/hook-kit.js.map +1 -0
  274. package/dist/rasp/__tests__/http-hook.test.d.ts +1 -0
  275. package/dist/rasp/__tests__/http-hook.test.js +250 -0
  276. package/dist/rasp/__tests__/http-hook.test.js.map +1 -0
  277. package/dist/rasp/__tests__/iast.test.d.ts +1 -0
  278. package/dist/rasp/__tests__/iast.test.js +361 -0
  279. package/dist/rasp/__tests__/iast.test.js.map +1 -0
  280. package/dist/rasp/__tests__/include-hook.test.d.ts +1 -0
  281. package/dist/rasp/__tests__/include-hook.test.js +122 -0
  282. package/dist/rasp/__tests__/include-hook.test.js.map +1 -0
  283. package/dist/rasp/__tests__/middleware.test.d.ts +1 -0
  284. package/dist/rasp/__tests__/middleware.test.js +302 -0
  285. package/dist/rasp/__tests__/middleware.test.js.map +1 -0
  286. package/dist/rasp/__tests__/process-hook.test.d.ts +1 -0
  287. package/dist/rasp/__tests__/process-hook.test.js +238 -0
  288. package/dist/rasp/__tests__/process-hook.test.js.map +1 -0
  289. package/dist/rasp/__tests__/reporter.test.d.ts +1 -0
  290. package/dist/rasp/__tests__/reporter.test.js +114 -0
  291. package/dist/rasp/__tests__/reporter.test.js.map +1 -0
  292. package/dist/rasp/__tests__/route.test.d.ts +1 -0
  293. package/dist/rasp/__tests__/route.test.js +46 -0
  294. package/dist/rasp/__tests__/route.test.js.map +1 -0
  295. package/dist/rasp/__tests__/rule-expr.test.d.ts +1 -0
  296. package/dist/rasp/__tests__/rule-expr.test.js +151 -0
  297. package/dist/rasp/__tests__/rule-expr.test.js.map +1 -0
  298. package/dist/rasp/__tests__/rule-phases.test.d.ts +1 -0
  299. package/dist/rasp/__tests__/rule-phases.test.js +271 -0
  300. package/dist/rasp/__tests__/rule-phases.test.js.map +1 -0
  301. package/dist/rasp/__tests__/sinks-hook.test.d.ts +1 -0
  302. package/dist/rasp/__tests__/sinks-hook.test.js +177 -0
  303. package/dist/rasp/__tests__/sinks-hook.test.js.map +1 -0
  304. package/dist/rasp/__tests__/targets.test.d.ts +1 -0
  305. package/dist/rasp/__tests__/targets.test.js +82 -0
  306. package/dist/rasp/__tests__/targets.test.js.map +1 -0
  307. package/dist/rasp/__tests__/template-hook.test.d.ts +1 -0
  308. package/dist/rasp/__tests__/template-hook.test.js +254 -0
  309. package/dist/rasp/__tests__/template-hook.test.js.map +1 -0
  310. package/dist/rasp/__tests__/upload.test.d.ts +1 -0
  311. package/dist/rasp/__tests__/upload.test.js +81 -0
  312. package/dist/rasp/__tests__/upload.test.js.map +1 -0
  313. package/dist/rasp/__tests__/vpatch-engine.test.d.ts +1 -0
  314. package/dist/rasp/__tests__/vpatch-engine.test.js +177 -0
  315. package/dist/rasp/__tests__/vpatch-engine.test.js.map +1 -0
  316. package/dist/rasp/auto-http.d.ts +6 -0
  317. package/dist/rasp/auto-http.js +194 -0
  318. package/dist/rasp/auto-http.js.map +1 -0
  319. package/dist/rasp/baseline.d.ts +35 -0
  320. package/dist/rasp/baseline.js +91 -0
  321. package/dist/rasp/baseline.js.map +1 -0
  322. package/dist/rasp/capture.d.ts +76 -0
  323. package/dist/rasp/capture.js +304 -0
  324. package/dist/rasp/capture.js.map +1 -0
  325. package/dist/rasp/config-client.d.ts +122 -0
  326. package/dist/rasp/config-client.js +337 -0
  327. package/dist/rasp/config-client.js.map +1 -0
  328. package/dist/rasp/context.d.ts +65 -0
  329. package/dist/rasp/context.js +68 -0
  330. package/dist/rasp/context.js.map +1 -0
  331. package/dist/rasp/custom-rules.d.ts +68 -0
  332. package/dist/rasp/custom-rules.js +222 -0
  333. package/dist/rasp/custom-rules.js.map +1 -0
  334. package/dist/rasp/data/default-rules.json +199 -0
  335. package/dist/rasp/data/default-sinks.json +4 -0
  336. package/dist/rasp/data/dnslog-domains.json +11 -0
  337. package/dist/rasp/deception.d.ts +70 -0
  338. package/dist/rasp/deception.js +220 -0
  339. package/dist/rasp/deception.js.map +1 -0
  340. package/dist/rasp/detect.d.ts +68 -0
  341. package/dist/rasp/detect.js +671 -0
  342. package/dist/rasp/detect.js.map +1 -0
  343. package/dist/rasp/engine.d.ts +107 -0
  344. package/dist/rasp/engine.js +330 -0
  345. package/dist/rasp/engine.js.map +1 -0
  346. package/dist/rasp/hooks/code.d.ts +20 -0
  347. package/dist/rasp/hooks/code.js +334 -0
  348. package/dist/rasp/hooks/code.js.map +1 -0
  349. package/dist/rasp/hooks/db.d.ts +48 -0
  350. package/dist/rasp/hooks/db.js +322 -0
  351. package/dist/rasp/hooks/db.js.map +1 -0
  352. package/dist/rasp/hooks/esm.d.ts +7 -0
  353. package/dist/rasp/hooks/esm.js +18 -0
  354. package/dist/rasp/hooks/esm.js.map +1 -0
  355. package/dist/rasp/hooks/fs.d.ts +3 -0
  356. package/dist/rasp/hooks/fs.js +206 -0
  357. package/dist/rasp/hooks/fs.js.map +1 -0
  358. package/dist/rasp/hooks/http.d.ts +4 -0
  359. package/dist/rasp/hooks/http.js +213 -0
  360. package/dist/rasp/hooks/http.js.map +1 -0
  361. package/dist/rasp/hooks/include.d.ts +9 -0
  362. package/dist/rasp/hooks/include.js +79 -0
  363. package/dist/rasp/hooks/include.js.map +1 -0
  364. package/dist/rasp/hooks/marks.d.ts +2 -0
  365. package/dist/rasp/hooks/marks.js +16 -0
  366. package/dist/rasp/hooks/marks.js.map +1 -0
  367. package/dist/rasp/hooks/process.d.ts +22 -0
  368. package/dist/rasp/hooks/process.js +191 -0
  369. package/dist/rasp/hooks/process.js.map +1 -0
  370. package/dist/rasp/hooks/sinks.d.ts +54 -0
  371. package/dist/rasp/hooks/sinks.js +329 -0
  372. package/dist/rasp/hooks/sinks.js.map +1 -0
  373. package/dist/rasp/hooks/template.d.ts +21 -0
  374. package/dist/rasp/hooks/template.js +152 -0
  375. package/dist/rasp/hooks/template.js.map +1 -0
  376. package/dist/rasp/iast-rules.d.ts +82 -0
  377. package/dist/rasp/iast-rules.js +240 -0
  378. package/dist/rasp/iast-rules.js.map +1 -0
  379. package/dist/rasp/iast-scope.d.ts +29 -0
  380. package/dist/rasp/iast-scope.js +54 -0
  381. package/dist/rasp/iast-scope.js.map +1 -0
  382. package/dist/rasp/iast.d.ts +81 -0
  383. package/dist/rasp/iast.js +272 -0
  384. package/dist/rasp/iast.js.map +1 -0
  385. package/dist/rasp/index.d.ts +52 -0
  386. package/dist/rasp/index.js +280 -0
  387. package/dist/rasp/index.js.map +1 -0
  388. package/dist/rasp/lexers.d.ts +32 -0
  389. package/dist/rasp/lexers.js +444 -0
  390. package/dist/rasp/lexers.js.map +1 -0
  391. package/dist/rasp/middleware.d.ts +155 -0
  392. package/dist/rasp/middleware.js +568 -0
  393. package/dist/rasp/middleware.js.map +1 -0
  394. package/dist/rasp/model-output.d.ts +14 -0
  395. package/dist/rasp/model-output.js +107 -0
  396. package/dist/rasp/model-output.js.map +1 -0
  397. package/dist/rasp/normalize.d.ts +23 -0
  398. package/dist/rasp/normalize.js +140 -0
  399. package/dist/rasp/normalize.js.map +1 -0
  400. package/dist/rasp/reporter.d.ts +60 -0
  401. package/dist/rasp/reporter.js +230 -0
  402. package/dist/rasp/reporter.js.map +1 -0
  403. package/dist/rasp/rule-expr.d.ts +236 -0
  404. package/dist/rasp/rule-expr.js +1253 -0
  405. package/dist/rasp/rule-expr.js.map +1 -0
  406. package/dist/rasp/template.d.ts +53 -0
  407. package/dist/rasp/template.js +336 -0
  408. package/dist/rasp/template.js.map +1 -0
  409. package/dist/rasp/types.d.ts +110 -0
  410. package/dist/rasp/types.js +51 -0
  411. package/dist/rasp/types.js.map +1 -0
  412. package/dist/rasp/vpatch.d.ts +55 -0
  413. package/dist/rasp/vpatch.js +120 -0
  414. package/dist/rasp/vpatch.js.map +1 -0
  415. package/dist/register.js +52 -11
  416. package/dist/register.js.map +1 -1
  417. package/dist/semantic-convention.d.ts +2 -0
  418. package/dist/semantic-convention.js +5 -0
  419. package/dist/semantic-convention.js.map +1 -1
  420. package/dist/types.d.ts +96 -0
  421. package/dist/zero-code.d.ts +8 -0
  422. package/dist/zero-code.js +38 -0
  423. package/dist/zero-code.js.map +1 -0
  424. package/package.json +18 -2
@@ -0,0 +1,677 @@
1
+ "use strict";
2
+ /**
3
+ * Shield360 feature flags: the evaluation engine.
4
+ *
5
+ * Canonical source: sdk/flags-core/src/engine.ts. Byte-identical copies live at
6
+ * sdk/typescript/src/flags/engine.ts (the TypeScript SDK) and
7
+ * src/client/src/lib/platform/flags/engine.ts (the server); tests in both fail
8
+ * when a copy differs. The Python, Go and .NET SDKs port it
9
+ * (sdk/python/src/shield360/flags/_engine.py, sdk/go/flags/engine.go,
10
+ * sdk/dotnet/src/Shield360/Flags/FlagEngine.cs), and every implementation is
11
+ * held to sdk/flags-core/testdata/vectors.json. Change the canonical file,
12
+ * copy it, port it, and add vectors.
13
+ *
14
+ * Pure and dependency-free: no imports, no Node built-ins, no clock, no
15
+ * randomness. The same flag and context always give the same answer.
16
+ */
17
+ Object.defineProperty(exports, "__esModule", { value: true });
18
+ exports.isOperator = exports.isAttributeName = exports.isVariationKey = exports.isFlagKey = exports.LIMITS = exports.DEFAULT_BUCKET_BY = exports.BUCKETS = exports.isSegmentOperator = exports.SEGMENT_ATTRIBUTE = exports.SEGMENT_OPERATORS = exports.OPERATORS = exports.FLAG_TYPES = void 0;
19
+ exports.utf8 = utf8;
20
+ exports.murmur3 = murmur3;
21
+ exports.bucketOf = bucketOf;
22
+ exports.textOf = textOf;
23
+ exports.numberOf = numberOf;
24
+ exports.parseSemver = parseSemver;
25
+ exports.compareSemver = compareSemver;
26
+ exports.conditionMatches = conditionMatches;
27
+ exports.findSegment = findSegment;
28
+ exports.segmentMatches = segmentMatches;
29
+ exports.ruleMatches = ruleMatches;
30
+ exports.segmentKeysOf = segmentKeysOf;
31
+ exports.rolloutVariation = rolloutVariation;
32
+ exports.valueMatchesType = valueMatchesType;
33
+ exports.plainJson = plainJson;
34
+ exports.validateFlag = validateFlag;
35
+ exports.validateSegment = validateSegment;
36
+ exports.evaluate = evaluate;
37
+ exports.FLAG_TYPES = ['boolean', 'string', 'number', 'json'];
38
+ exports.OPERATORS = [
39
+ 'equals',
40
+ 'not_equals',
41
+ 'in',
42
+ 'not_in',
43
+ 'contains',
44
+ 'starts_with',
45
+ 'lt',
46
+ 'lte',
47
+ 'gt',
48
+ 'gte',
49
+ 'semver_eq',
50
+ 'semver_lt',
51
+ 'semver_lte',
52
+ 'semver_gt',
53
+ 'semver_gte',
54
+ 'in_segment',
55
+ 'not_in_segment',
56
+ ];
57
+ /**
58
+ * Segment operators: the condition's attribute is the literal `segment` and its
59
+ * values are segment keys. `in_segment` holds when the context is in any of
60
+ * them, `not_in_segment` when it is in none. A condition naming a segment the
61
+ * caller did not pass (or one that does not validate) never holds, either way.
62
+ */
63
+ exports.SEGMENT_OPERATORS = ['in_segment', 'not_in_segment'];
64
+ exports.SEGMENT_ATTRIBUTE = 'segment';
65
+ const isSegmentOperator = (v) => typeof v === 'string' && exports.SEGMENT_OPERATORS.indexOf(v) >= 0;
66
+ exports.isSegmentOperator = isSegmentOperator;
67
+ /** Buckets run 0..99,999: a rollout weight of 1 is a thousandth of a percent. */
68
+ exports.BUCKETS = 100000;
69
+ exports.DEFAULT_BUCKET_BY = 'key';
70
+ /**
71
+ * Counts every implementation checks alike. Lengths and sizes (names, text
72
+ * values, JSON size) are the server's to limit: string length is counted
73
+ * differently from one language to the next.
74
+ */
75
+ exports.LIMITS = {
76
+ variations: 20,
77
+ rules: 50,
78
+ conditions: 20,
79
+ conditionValues: 100,
80
+ /** Segments one condition may name. */
81
+ segmentsPerCondition: 20,
82
+ };
83
+ const FLAG_KEY = /^[a-z0-9](?:[a-z0-9._-]{0,62}[a-z0-9])?$/;
84
+ const VARIATION_KEY = /^[A-Za-z0-9][A-Za-z0-9_-]{0,39}$/;
85
+ const RULE_ID = /^[A-Za-z0-9_-]{1,64}$/;
86
+ const ATTRIBUTE = /^[A-Za-z_][A-Za-z0-9_.-]{0,63}$/;
87
+ const SALT = /^[A-Za-z0-9_-]{1,64}$/;
88
+ const isFlagKey = (v) => typeof v === 'string' && FLAG_KEY.test(v);
89
+ exports.isFlagKey = isFlagKey;
90
+ const isVariationKey = (v) => typeof v === 'string' && VARIATION_KEY.test(v);
91
+ exports.isVariationKey = isVariationKey;
92
+ const isAttributeName = (v) => typeof v === 'string' && ATTRIBUTE.test(v);
93
+ exports.isAttributeName = isAttributeName;
94
+ const isOperator = (v) => typeof v === 'string' && exports.OPERATORS.indexOf(v) >= 0;
95
+ exports.isOperator = isOperator;
96
+ const isRecord = (v) => !!v && typeof v === 'object' && !Array.isArray(v);
97
+ /** The context's own attribute; never one inherited from Object.prototype (`constructor`, `toString`). */
98
+ const own = (context, attribute) => Object.prototype.hasOwnProperty.call(context, attribute) ? context[attribute] : undefined;
99
+ // ------------------------------------------------------------------ hashing
100
+ /** UTF-8 bytes of a string, without TextEncoder (so nothing global is assumed). */
101
+ function utf8(text) {
102
+ const out = [];
103
+ for (let i = 0; i < text.length; i++) {
104
+ let c = text.charCodeAt(i);
105
+ if (c >= 0xd800 && c <= 0xdbff && i + 1 < text.length) {
106
+ const d = text.charCodeAt(i + 1);
107
+ if (d >= 0xdc00 && d <= 0xdfff) {
108
+ c = 0x10000 + ((c - 0xd800) << 10) + (d - 0xdc00);
109
+ i++;
110
+ }
111
+ }
112
+ if (c >= 0xd800 && c <= 0xdfff)
113
+ c = 0xfffd; // a lone surrogate, as TextEncoder writes it
114
+ if (c < 0x80)
115
+ out.push(c);
116
+ else if (c < 0x800)
117
+ out.push(0xc0 | (c >> 6), 0x80 | (c & 63));
118
+ else if (c < 0x10000)
119
+ out.push(0xe0 | (c >> 12), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));
120
+ else
121
+ out.push(0xf0 | (c >> 18), 0x80 | ((c >> 12) & 63), 0x80 | ((c >> 6) & 63), 0x80 | (c & 63));
122
+ }
123
+ return out;
124
+ }
125
+ /** MurmurHash3 (x86, 32-bit, seed 0) of the UTF-8 bytes of `text`, unsigned. */
126
+ function murmur3(text) {
127
+ const bytes = utf8(text);
128
+ const c1 = 0xcc9e2d51;
129
+ const c2 = 0x1b873593;
130
+ let h = 0;
131
+ const blocks = bytes.length - (bytes.length % 4);
132
+ for (let i = 0; i < blocks; i += 4) {
133
+ let k = bytes[i] | (bytes[i + 1] << 8) | (bytes[i + 2] << 16) | (bytes[i + 3] << 24);
134
+ k = Math.imul(k, c1);
135
+ k = (k << 15) | (k >>> 17);
136
+ k = Math.imul(k, c2);
137
+ h ^= k;
138
+ h = (h << 13) | (h >>> 19);
139
+ h = (Math.imul(h, 5) + 0xe6546b64) | 0;
140
+ }
141
+ let k = 0;
142
+ const tail = bytes.length % 4;
143
+ if (tail === 3)
144
+ k ^= bytes[blocks + 2] << 16;
145
+ if (tail >= 2)
146
+ k ^= bytes[blocks + 1] << 8;
147
+ if (tail >= 1) {
148
+ k ^= bytes[blocks];
149
+ k = Math.imul(k, c1);
150
+ k = (k << 15) | (k >>> 17);
151
+ k = Math.imul(k, c2);
152
+ h ^= k;
153
+ }
154
+ h ^= bytes.length;
155
+ h ^= h >>> 16;
156
+ h = Math.imul(h, 0x85ebca6b);
157
+ h ^= h >>> 13;
158
+ h = Math.imul(h, 0xc2b2ae35);
159
+ h ^= h >>> 16;
160
+ return h >>> 0;
161
+ }
162
+ /** The bucket (0..99,999) a value falls in for a flag: stable across runs, processes and SDKs. */
163
+ function bucketOf(flagKey, salt, value) {
164
+ return murmur3(flagKey + '.' + salt + '.' + value) % exports.BUCKETS;
165
+ }
166
+ // ----------------------------------------------------------- attribute text
167
+ /**
168
+ * The text of a scalar, the same in every SDK: strings as they are, booleans
169
+ * as true/false, integers without a decimal point, other numbers as their
170
+ * shortest round-trip form. Null for anything else.
171
+ */
172
+ function textOf(v) {
173
+ if (typeof v === 'string')
174
+ return v;
175
+ if (typeof v === 'boolean')
176
+ return v ? 'true' : 'false';
177
+ if (typeof v === 'number')
178
+ return isFinite(v) ? String(v) : null;
179
+ return null;
180
+ }
181
+ const NUMBER_TEXT = /^-?([0-9]+\.?[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?$/;
182
+ /** A finite number, or the text of one (no spaces); null otherwise. */
183
+ function numberOf(v) {
184
+ if (typeof v === 'number')
185
+ return isFinite(v) ? v : null;
186
+ if (typeof v === 'string' && NUMBER_TEXT.test(v)) {
187
+ const n = Number(v);
188
+ return isFinite(n) ? n : null;
189
+ }
190
+ return null;
191
+ }
192
+ const SEMVER = /^v?(0|[1-9][0-9]*)(?:\.(0|[1-9][0-9]*))?(?:\.(0|[1-9][0-9]*))?(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
193
+ /** A semantic version; a missing minor or patch is 0, build metadata is ignored. */
194
+ function parseSemver(v) {
195
+ if (typeof v !== 'string')
196
+ return null;
197
+ const m = SEMVER.exec(v);
198
+ if (!m)
199
+ return null;
200
+ return {
201
+ major: Number(m[1]),
202
+ minor: m[2] === undefined ? 0 : Number(m[2]),
203
+ patch: m[3] === undefined ? 0 : Number(m[3]),
204
+ pre: m[4] === undefined ? [] : m[4].split('.'),
205
+ };
206
+ }
207
+ const NUMERIC_ID = /^[0-9]+$/;
208
+ /** -1, 0 or 1, by semver precedence. */
209
+ function compareSemver(a, b) {
210
+ for (const part of ['major', 'minor', 'patch']) {
211
+ if (a[part] !== b[part])
212
+ return a[part] < b[part] ? -1 : 1;
213
+ }
214
+ if (!a.pre.length || !b.pre.length) {
215
+ if (a.pre.length === b.pre.length)
216
+ return 0;
217
+ return a.pre.length ? -1 : 1; // a pre-release comes before its release
218
+ }
219
+ const n = Math.min(a.pre.length, b.pre.length);
220
+ for (let i = 0; i < n; i++) {
221
+ const x = a.pre[i];
222
+ const y = b.pre[i];
223
+ if (x === y)
224
+ continue;
225
+ const xn = NUMERIC_ID.test(x);
226
+ const yn = NUMERIC_ID.test(y);
227
+ if (xn && yn)
228
+ return Number(x) < Number(y) ? -1 : 1;
229
+ if (xn !== yn)
230
+ return xn ? -1 : 1;
231
+ return x < y ? -1 : 1;
232
+ }
233
+ if (a.pre.length === b.pre.length)
234
+ return 0;
235
+ return a.pre.length < b.pre.length ? -1 : 1;
236
+ }
237
+ // ---------------------------------------------------------------- matching
238
+ /** Whether one scalar attribute value satisfies a positive operator against the condition's values. */
239
+ function scalarMatches(op, actual, values) {
240
+ switch (op) {
241
+ case 'equals':
242
+ case 'in': {
243
+ const text = textOf(actual);
244
+ return text !== null && values.some((v) => textOf(v) === text);
245
+ }
246
+ case 'contains':
247
+ case 'starts_with': {
248
+ const text = textOf(actual);
249
+ if (text === null)
250
+ return false;
251
+ return values.some((v) => {
252
+ const want = textOf(v);
253
+ if (want === null)
254
+ return false;
255
+ return op === 'contains' ? text.indexOf(want) >= 0 : text.slice(0, want.length) === want;
256
+ });
257
+ }
258
+ case 'lt':
259
+ case 'lte':
260
+ case 'gt':
261
+ case 'gte': {
262
+ const n = numberOf(actual);
263
+ if (n === null)
264
+ return false;
265
+ return values.some((v) => {
266
+ const w = numberOf(v);
267
+ if (w === null)
268
+ return false;
269
+ return op === 'lt' ? n < w : op === 'lte' ? n <= w : op === 'gt' ? n > w : n >= w;
270
+ });
271
+ }
272
+ case 'semver_eq':
273
+ case 'semver_lt':
274
+ case 'semver_lte':
275
+ case 'semver_gt':
276
+ case 'semver_gte': {
277
+ const a = parseSemver(actual);
278
+ if (!a)
279
+ return false;
280
+ return values.some((v) => {
281
+ const b = parseSemver(v);
282
+ if (!b)
283
+ return false;
284
+ const c = compareSemver(a, b);
285
+ if (op === 'semver_eq')
286
+ return c === 0;
287
+ if (op === 'semver_lt')
288
+ return c < 0;
289
+ if (op === 'semver_lte')
290
+ return c <= 0;
291
+ if (op === 'semver_gt')
292
+ return c > 0;
293
+ return c >= 0;
294
+ });
295
+ }
296
+ default:
297
+ return false;
298
+ }
299
+ }
300
+ const NEGATED = { not_equals: 'equals', not_in: 'in' };
301
+ /**
302
+ * Whether the context satisfies one condition. A missing (or null) attribute
303
+ * never matches, negated operators included. An array attribute matches a
304
+ * positive operator when any element does, and a negated one when none does.
305
+ */
306
+ function conditionMatches(condition, context, segments) {
307
+ if ((0, exports.isSegmentOperator)(condition.operator))
308
+ return segmentConditionMatches(condition, context, segments);
309
+ const actual = own(context, condition.attribute);
310
+ if (actual === undefined || actual === null)
311
+ return false;
312
+ const items = Array.isArray(actual) ? actual : [actual];
313
+ if (!items.length)
314
+ return false;
315
+ const positive = NEGATED[condition.operator];
316
+ if (positive)
317
+ return !items.some((item) => scalarMatches(positive, item, condition.values));
318
+ return items.some((item) => scalarMatches(condition.operator, item, condition.values));
319
+ }
320
+ /** The valid segment of this key among `segments`, or null. */
321
+ function findSegment(segments, key) {
322
+ if (!Array.isArray(segments) || typeof key !== 'string')
323
+ return null;
324
+ for (const s of segments) {
325
+ if (isRecord(s) && s.key === key)
326
+ return validateSegment(s).length ? null : s;
327
+ }
328
+ return null;
329
+ }
330
+ /** Whether the context is in the segment: every one of its conditions holds. */
331
+ function segmentMatches(segment, context) {
332
+ if (!segment.conditions.length)
333
+ return false;
334
+ return segment.conditions.every((c) => !(0, exports.isSegmentOperator)(c.operator) && conditionMatches(c, context));
335
+ }
336
+ function segmentConditionMatches(condition, context, segments) {
337
+ let inAny = false;
338
+ for (const key of condition.values) {
339
+ const segment = findSegment(segments, key);
340
+ if (!segment)
341
+ return false; // an unknown segment never matches, either way
342
+ if (segmentMatches(segment, context))
343
+ inAny = true;
344
+ }
345
+ return condition.operator === 'in_segment' ? inAny : !inAny;
346
+ }
347
+ /** Every condition holds (a rule with none never matches). */
348
+ function ruleMatches(rule, context, segments) {
349
+ if (!rule.conditions.length)
350
+ return false;
351
+ return rule.conditions.every((c) => conditionMatches(c, context, segments));
352
+ }
353
+ /** The segment keys a flag's rules name, each once, in order of first use. */
354
+ function segmentKeysOf(flag) {
355
+ const keys = [];
356
+ if (!Array.isArray(flag.rules))
357
+ return keys;
358
+ for (const rule of flag.rules) {
359
+ if (!isRecord(rule) || !Array.isArray(rule.conditions))
360
+ continue;
361
+ for (const c of rule.conditions) {
362
+ if (!isRecord(c) || !(0, exports.isSegmentOperator)(c.operator) || !Array.isArray(c.values))
363
+ continue;
364
+ for (const v of c.values)
365
+ if (typeof v === 'string' && keys.indexOf(v) < 0)
366
+ keys.push(v);
367
+ }
368
+ }
369
+ return keys;
370
+ }
371
+ /** The variation a rollout serves this context, and the bucket it fell in. */
372
+ function rolloutVariation(flag, rollout, context) {
373
+ const by = rollout.bucketBy || exports.DEFAULT_BUCKET_BY;
374
+ const text = textOf(own(context, by));
375
+ // Without the attribute everyone is bucket 0: the first variation with weight.
376
+ const bucket = text === null ? 0 : bucketOf(flag.key, flag.salt, text);
377
+ let upper = 0;
378
+ for (const w of rollout.weights) {
379
+ upper += w.weight;
380
+ if (bucket < upper)
381
+ return { variation: w.variation, bucket };
382
+ }
383
+ // Weights are validated to sum to BUCKETS; this is unreachable for a valid flag.
384
+ const last = rollout.weights[rollout.weights.length - 1];
385
+ return { variation: last ? last.variation : '', bucket };
386
+ }
387
+ /** Whether `value` is of the flag's type. */
388
+ function valueMatchesType(type, value) {
389
+ if (type === 'boolean')
390
+ return typeof value === 'boolean';
391
+ if (type === 'string')
392
+ return typeof value === 'string';
393
+ if (type === 'number')
394
+ return typeof value === 'number' && isFinite(value);
395
+ if (type === 'json')
396
+ return plainJson(value, 0);
397
+ return false;
398
+ }
399
+ /** Null, a string, a boolean, a finite number, or arrays and plain objects of them, at most 20 deep. */
400
+ function plainJson(v, depth) {
401
+ if (depth > 20)
402
+ return false;
403
+ if (v === null || typeof v === 'string' || typeof v === 'boolean')
404
+ return true;
405
+ if (typeof v === 'number')
406
+ return isFinite(v);
407
+ if (Array.isArray(v))
408
+ return v.every((x) => plainJson(x, depth + 1));
409
+ if (isRecord(v)) {
410
+ const proto = Object.getPrototypeOf(v);
411
+ if (proto !== Object.prototype && proto !== null)
412
+ return false;
413
+ return Object.keys(v).every((k) => plainJson(v[k], depth + 1));
414
+ }
415
+ return false;
416
+ }
417
+ function validateServe(serve, path, variationKeys, errors) {
418
+ if (!isRecord(serve)) {
419
+ errors.push({ path, code: 'serve_invalid' });
420
+ return;
421
+ }
422
+ const hasVariation = serve.variation !== undefined;
423
+ const hasRollout = serve.rollout !== undefined;
424
+ if (hasVariation === hasRollout) {
425
+ errors.push({ path, code: 'serve_invalid' });
426
+ return;
427
+ }
428
+ if (hasVariation) {
429
+ if (typeof serve.variation !== 'string' || variationKeys.indexOf(serve.variation) < 0)
430
+ errors.push({ path: path + '.variation', code: 'variation_unknown' });
431
+ return;
432
+ }
433
+ const rollout = serve.rollout;
434
+ if (!isRecord(rollout) || !Array.isArray(rollout.weights) || !rollout.weights.length) {
435
+ errors.push({ path: path + '.rollout', code: 'rollout_invalid' });
436
+ return;
437
+ }
438
+ if (rollout.bucketBy !== undefined && !(0, exports.isAttributeName)(rollout.bucketBy))
439
+ errors.push({ path: path + '.rollout.bucketBy', code: 'attribute_invalid' });
440
+ if (rollout.weights.length > exports.LIMITS.variations)
441
+ errors.push({ path: path + '.rollout.weights', code: 'too_many' });
442
+ let total = 0;
443
+ const seen = [];
444
+ rollout.weights.forEach((w, i) => {
445
+ const at = path + '.rollout.weights.' + i;
446
+ if (!isRecord(w)) {
447
+ errors.push({ path: at, code: 'rollout_invalid' });
448
+ return;
449
+ }
450
+ if (typeof w.variation !== 'string' || variationKeys.indexOf(w.variation) < 0)
451
+ errors.push({ path: at + '.variation', code: 'variation_unknown' });
452
+ else if (seen.indexOf(w.variation) >= 0)
453
+ errors.push({ path: at + '.variation', code: 'duplicate' });
454
+ else
455
+ seen.push(w.variation);
456
+ if (typeof w.weight !== 'number' ||
457
+ !Number.isInteger(w.weight) ||
458
+ w.weight < 0 ||
459
+ w.weight > exports.BUCKETS)
460
+ errors.push({ path: at + '.weight', code: 'weight_invalid' });
461
+ else
462
+ total += w.weight;
463
+ });
464
+ if (total !== exports.BUCKETS)
465
+ errors.push({ path: path + '.rollout.weights', code: 'weights_sum' });
466
+ }
467
+ function validateCondition(c, path, errors, inSegment) {
468
+ if (!isRecord(c)) {
469
+ errors.push({ path, code: 'condition_invalid' });
470
+ return;
471
+ }
472
+ if ((0, exports.isSegmentOperator)(c.operator)) {
473
+ if (inSegment) {
474
+ errors.push({ path: path + '.operator', code: 'segment_nested' });
475
+ return;
476
+ }
477
+ if (c.attribute !== exports.SEGMENT_ATTRIBUTE)
478
+ errors.push({ path: path + '.attribute', code: 'attribute_invalid' });
479
+ const keys = c.values;
480
+ if (!Array.isArray(keys) || !keys.length || keys.length > exports.LIMITS.segmentsPerCondition) {
481
+ errors.push({ path: path + '.values', code: 'values_invalid' });
482
+ return;
483
+ }
484
+ const seen = [];
485
+ keys.forEach((v, i) => {
486
+ if (!(0, exports.isFlagKey)(v))
487
+ errors.push({ path: path + '.values.' + i, code: 'value_not_segment' });
488
+ else if (seen.indexOf(v) >= 0)
489
+ errors.push({ path: path + '.values.' + i, code: 'duplicate' });
490
+ else
491
+ seen.push(v);
492
+ });
493
+ return;
494
+ }
495
+ if (!(0, exports.isAttributeName)(c.attribute))
496
+ errors.push({ path: path + '.attribute', code: 'attribute_invalid' });
497
+ if (!(0, exports.isOperator)(c.operator))
498
+ errors.push({ path: path + '.operator', code: 'operator_invalid' });
499
+ const values = c.values;
500
+ if (!Array.isArray(values) || !values.length || values.length > exports.LIMITS.conditionValues) {
501
+ errors.push({ path: path + '.values', code: 'values_invalid' });
502
+ return;
503
+ }
504
+ const single = c.operator === 'equals' || c.operator === 'not_equals';
505
+ if (single && values.length !== 1)
506
+ errors.push({ path: path + '.values', code: 'values_invalid' });
507
+ values.forEach((v, i) => {
508
+ const at = path + '.values.' + i;
509
+ const scalar = typeof v === 'string' ||
510
+ typeof v === 'boolean' ||
511
+ (typeof v === 'number' && isFinite(v));
512
+ if (!scalar) {
513
+ errors.push({ path: at, code: 'value_invalid' });
514
+ return;
515
+ }
516
+ const op = String(c.operator);
517
+ if ((op === 'lt' || op === 'lte' || op === 'gt' || op === 'gte') && numberOf(v) === null)
518
+ errors.push({ path: at, code: 'value_not_number' });
519
+ if (op.indexOf('semver_') === 0 && !parseSemver(v))
520
+ errors.push({ path: at, code: 'value_not_semver' });
521
+ });
522
+ }
523
+ /**
524
+ * Everything wrong with a flag definition, by path; empty when it is valid.
525
+ * The server refuses to save an invalid flag; the SDKs and the engine treat
526
+ * one as malformed and serve the caller's default.
527
+ */
528
+ function validateFlag(input) {
529
+ const errors = [];
530
+ if (!isRecord(input))
531
+ return [{ path: '', code: 'flag_invalid' }];
532
+ const f = input;
533
+ if (!(0, exports.isFlagKey)(f.key))
534
+ errors.push({ path: 'key', code: 'key_invalid' });
535
+ const type = f.type;
536
+ if (exports.FLAG_TYPES.indexOf(type) < 0)
537
+ errors.push({ path: 'type', code: 'type_invalid' });
538
+ if (typeof f.on !== 'boolean')
539
+ errors.push({ path: 'on', code: 'on_invalid' });
540
+ if (typeof f.salt !== 'string' || !SALT.test(f.salt))
541
+ errors.push({ path: 'salt', code: 'salt_invalid' });
542
+ if (f.archived !== undefined && typeof f.archived !== 'boolean')
543
+ errors.push({ path: 'archived', code: 'archived_invalid' });
544
+ const keys = [];
545
+ if (!Array.isArray(f.variations) || f.variations.length < 2 || f.variations.length > exports.LIMITS.variations) {
546
+ errors.push({ path: 'variations', code: 'variations_count' });
547
+ }
548
+ else {
549
+ f.variations.forEach((v, i) => {
550
+ const at = 'variations.' + i;
551
+ if (!isRecord(v)) {
552
+ errors.push({ path: at, code: 'variation_invalid' });
553
+ return;
554
+ }
555
+ if (!(0, exports.isVariationKey)(v.key))
556
+ errors.push({ path: at + '.key', code: 'variation_key_invalid' });
557
+ else if (keys.indexOf(v.key) >= 0)
558
+ errors.push({ path: at + '.key', code: 'duplicate' });
559
+ else
560
+ keys.push(v.key);
561
+ if (v.name !== undefined && typeof v.name !== 'string')
562
+ errors.push({ path: at + '.name', code: 'name_invalid' });
563
+ if (exports.FLAG_TYPES.indexOf(type) >= 0 && !valueMatchesType(type, v.value))
564
+ errors.push({ path: at + '.value', code: 'value_type' });
565
+ });
566
+ const variationErrors = errors.some((e) => e.path.indexOf('variations') === 0);
567
+ if (type === 'boolean' && !variationErrors) {
568
+ const values = f.variations.map((v) => v.value);
569
+ if (f.variations.length !== 2 || values[0] === values[1])
570
+ errors.push({ path: 'variations', code: 'boolean_variations' });
571
+ }
572
+ }
573
+ if (typeof f.offVariation !== 'string' || keys.indexOf(f.offVariation) < 0)
574
+ errors.push({ path: 'offVariation', code: 'variation_unknown' });
575
+ if (!Array.isArray(f.rules) || f.rules.length > exports.LIMITS.rules) {
576
+ errors.push({ path: 'rules', code: 'rules_invalid' });
577
+ }
578
+ else {
579
+ const ids = [];
580
+ f.rules.forEach((r, i) => {
581
+ const at = 'rules.' + i;
582
+ if (!isRecord(r)) {
583
+ errors.push({ path: at, code: 'rule_invalid' });
584
+ return;
585
+ }
586
+ if (typeof r.id !== 'string' || !RULE_ID.test(r.id))
587
+ errors.push({ path: at + '.id', code: 'rule_id_invalid' });
588
+ else if (ids.indexOf(r.id) >= 0)
589
+ errors.push({ path: at + '.id', code: 'duplicate' });
590
+ else
591
+ ids.push(r.id);
592
+ if (r.description !== undefined && typeof r.description !== 'string')
593
+ errors.push({ path: at + '.description', code: 'description_invalid' });
594
+ if (!Array.isArray(r.conditions) || !r.conditions.length || r.conditions.length > exports.LIMITS.conditions)
595
+ errors.push({ path: at + '.conditions', code: 'conditions_count' });
596
+ else
597
+ r.conditions.forEach((c, j) => validateCondition(c, at + '.conditions.' + j, errors, false));
598
+ validateServe(r.serve, at + '.serve', keys, errors);
599
+ });
600
+ }
601
+ validateServe(f.fallthrough, 'fallthrough', keys, errors);
602
+ return errors;
603
+ }
604
+ /**
605
+ * Everything wrong with a segment, by path; empty when it is valid. A segment
606
+ * has a key (the flag key pattern) and 1..20 conditions with the same
607
+ * operators as a rule's, except the segment operators: segments do not nest.
608
+ */
609
+ function validateSegment(input) {
610
+ const errors = [];
611
+ if (!isRecord(input))
612
+ return [{ path: '', code: 'segment_invalid' }];
613
+ if (!(0, exports.isFlagKey)(input.key))
614
+ errors.push({ path: 'key', code: 'key_invalid' });
615
+ const conditions = input.conditions;
616
+ if (!Array.isArray(conditions) || !conditions.length || conditions.length > exports.LIMITS.conditions)
617
+ errors.push({ path: 'conditions', code: 'conditions_count' });
618
+ else
619
+ conditions.forEach((c, j) => validateCondition(c, 'conditions.' + j, errors, true));
620
+ return errors;
621
+ }
622
+ // -------------------------------------------------------------- evaluation
623
+ function variationValue(flag, key) {
624
+ for (const v of flag.variations)
625
+ if (v.key === key)
626
+ return v;
627
+ return null;
628
+ }
629
+ function malformed() {
630
+ return { variation: null, value: null, reason: { kind: 'ERROR', errorKind: 'MALFORMED_FLAG' } };
631
+ }
632
+ /**
633
+ * The variation a flag serves a context (`segments` are the environment's
634
+ * segments, for rules that name them):
635
+ * archived -> the off variation (ARCHIVED)
636
+ * off -> the off variation (OFF)
637
+ * on -> the first rule, in order, whose conditions all hold (RULE_MATCH),
638
+ * else the fallthrough (FALLTHROUGH)
639
+ * A rollout picks by bucket. A malformed flag serves nothing (ERROR): the
640
+ * caller's default applies. Never throws.
641
+ */
642
+ function evaluate(flag, context = {}, segments) {
643
+ try {
644
+ if (validateFlag(flag).length)
645
+ return malformed();
646
+ const ctx = isRecord(context) ? context : {};
647
+ const segs = Array.isArray(segments) ? segments : [];
648
+ const off = (kind) => {
649
+ const v = variationValue(flag, flag.offVariation);
650
+ return { variation: v.key, value: v.value, reason: { kind } };
651
+ };
652
+ if (flag.archived)
653
+ return off('ARCHIVED');
654
+ if (!flag.on)
655
+ return off('OFF');
656
+ const serve = (s, reason) => {
657
+ const fixed = s.variation;
658
+ if (fixed !== undefined) {
659
+ const v = variationValue(flag, fixed);
660
+ return { variation: v.key, value: v.value, reason };
661
+ }
662
+ const picked = rolloutVariation(flag, s.rollout, ctx);
663
+ const v = variationValue(flag, picked.variation);
664
+ return { variation: v.key, value: v.value, reason: { ...reason, inRollout: true, bucket: picked.bucket } };
665
+ };
666
+ for (let i = 0; i < flag.rules.length; i++) {
667
+ const rule = flag.rules[i];
668
+ if (ruleMatches(rule, ctx, segs))
669
+ return serve(rule.serve, { kind: 'RULE_MATCH', ruleIndex: i, ruleId: rule.id });
670
+ }
671
+ return serve(flag.fallthrough, { kind: 'FALLTHROUGH' });
672
+ }
673
+ catch {
674
+ return malformed();
675
+ }
676
+ }
677
+ //# sourceMappingURL=engine.js.map